| /* |
| * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| */ |
| |
| /************************************************************************/ |
| /* */ |
| /* PROJECT : exFAT & FAT12/16/32 File System */ |
| /* FILE : exfat_api.c */ |
| /* PURPOSE : exFAT API Glue Layer */ |
| /* */ |
| /*----------------------------------------------------------------------*/ |
| /* NOTES */ |
| /* */ |
| /*----------------------------------------------------------------------*/ |
| /* REVISION HISTORY (Ver 0.9) */ |
| /* */ |
| /* - 2010.11.15 [Joosun Hahn] : first writing */ |
| /* */ |
| /************************************************************************/ |
| |
| #include <linux/version.h> |
| #include <linux/module.h> |
| #include <linux/init.h> |
| |
| #include "exfat_version.h" |
| #include "exfat_config.h" |
| #include "exfat_data.h" |
| #include "exfat_oal.h" |
| |
| #include "exfat_nls.h" |
| #include "exfat_api.h" |
| #include "exfat_super.h" |
| #include "exfat_core.h" |
| |
| /*----------------------------------------------------------------------*/ |
| /* Constant & Macro Definitions */ |
| /*----------------------------------------------------------------------*/ |
| |
| /*----------------------------------------------------------------------*/ |
| /* Global Variable Definitions */ |
| /*----------------------------------------------------------------------*/ |
| |
| extern struct semaphore z_sem; |
| |
| /*----------------------------------------------------------------------*/ |
| /* Local Variable Definitions */ |
| /*----------------------------------------------------------------------*/ |
| |
| /*----------------------------------------------------------------------*/ |
| /* Local Function Declarations */ |
| /*----------------------------------------------------------------------*/ |
| |
| /*======================================================================*/ |
| /* Global Function Definitions */ |
| /* - All functions for global use have same return value format, */ |
| /* that is, FFS_SUCCESS on success and several FS error code on */ |
| /* various error condition. */ |
| /*======================================================================*/ |
| |
| /*----------------------------------------------------------------------*/ |
| /* exFAT Filesystem Init & Exit Functions */ |
| /*----------------------------------------------------------------------*/ |
| |
| int FsInit(void) |
| { |
| return ffsInit(); |
| } |
| |
| int FsShutdown(void) |
| { |
| return ffsShutdown(); |
| } |
| |
| /*----------------------------------------------------------------------*/ |
| /* Volume Management Functions */ |
| /*----------------------------------------------------------------------*/ |
| |
| /* FsMountVol : mount the file system volume */ |
| int FsMountVol(struct super_block *sb) |
| { |
| int err; |
| |
| sm_P(&z_sem); |
| |
| err = buf_init(sb); |
| if (!err) |
| err = ffsMountVol(sb); |
| else |
| buf_shutdown(sb); |
| |
| sm_V(&z_sem); |
| |
| return err; |
| } /* end of FsMountVol */ |
| |
| /* FsUmountVol : unmount the file system volume */ |
| int FsUmountVol(struct super_block *sb) |
| { |
| int err; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| sm_P(&z_sem); |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsUmountVol(sb); |
| buf_shutdown(sb); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| sm_V(&z_sem); |
| |
| return err; |
| } /* end of FsUmountVol */ |
| |
| /* FsGetVolInfo : get the information of a file system volume */ |
| int FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) |
| { |
| int err; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of pointer parameters */ |
| if (info == NULL) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsGetVolInfo(sb, info); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsGetVolInfo */ |
| |
| /* FsSyncVol : synchronize a file system volume */ |
| int FsSyncVol(struct super_block *sb, int do_sync) |
| { |
| int err; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsSyncVol(sb, do_sync); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsSyncVol */ |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* File Operation Functions */ |
| /*----------------------------------------------------------------------*/ |
| |
| /* FsCreateFile : create a file */ |
| int FsLookupFile(struct inode *inode, char *path, FILE_ID_T *fid) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of pointer parameters */ |
| if ((fid == NULL) || (path == NULL) || (*path == '\0')) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsLookupFile(inode, path, fid); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsLookupFile */ |
| |
| /* FsCreateFile : create a file */ |
| int FsCreateFile(struct inode *inode, char *path, u8 mode, FILE_ID_T *fid) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of pointer parameters */ |
| if ((fid == NULL) || (path == NULL) || (*path == '\0')) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsCreateFile(inode, path, mode, fid); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsCreateFile */ |
| |
| int FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of the given file id */ |
| if (fid == NULL) |
| return FFS_INVALIDFID; |
| |
| /* check the validity of pointer parameters */ |
| if (buffer == NULL) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsReadFile(inode, fid, buffer, count, rcount); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsReadFile */ |
| |
| int FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of the given file id */ |
| if (fid == NULL) |
| return FFS_INVALIDFID; |
| |
| /* check the validity of pointer parameters */ |
| if (buffer == NULL) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsWriteFile(inode, fid, buffer, count, wcount); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsWriteFile */ |
| |
| /* FsTruncateFile : resize the file length */ |
| int FsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| DPRINTK("FsTruncateFile entered (inode %p size %llu)\n", inode, new_size); |
| |
| err = ffsTruncateFile(inode, old_size, new_size); |
| |
| DPRINTK("FsTruncateFile exitted (%d)\n", err); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsTruncateFile */ |
| |
| /* FsMoveFile : move(rename) a old file into a new file */ |
| int FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry) |
| { |
| int err; |
| struct super_block *sb = old_parent_inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of the given file id */ |
| if (fid == NULL) |
| return FFS_INVALIDFID; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsMoveFile(old_parent_inode, fid, new_parent_inode, new_dentry); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsMoveFile */ |
| |
| /* FsRemoveFile : remove a file */ |
| int FsRemoveFile(struct inode *inode, FILE_ID_T *fid) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of the given file id */ |
| if (fid == NULL) |
| return FFS_INVALIDFID; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsRemoveFile(inode, fid); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsRemoveFile */ |
| |
| /* FsSetAttr : set the attribute of a given file */ |
| int FsSetAttr(struct inode *inode, u32 attr) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsSetAttr(inode, attr); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsSetAttr */ |
| |
| /* FsReadStat : get the information of a given file */ |
| int FsReadStat(struct inode *inode, DIR_ENTRY_T *info) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsGetStat(inode, info); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsReadStat */ |
| |
| /* FsWriteStat : set the information of a given file */ |
| int FsWriteStat(struct inode *inode, DIR_ENTRY_T *info) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| DPRINTK("FsWriteStat entered (inode %p info %p\n", inode, info); |
| |
| err = ffsSetStat(inode, info); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| DPRINTK("FsWriteStat exited (%d)\n", err); |
| |
| return err; |
| } /* end of FsWriteStat */ |
| |
| /* FsMapCluster : return the cluster number in the given cluster offset */ |
| int FsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of pointer parameters */ |
| if (clu == NULL) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsMapCluster(inode, clu_offset, clu); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsMapCluster */ |
| |
| /*----------------------------------------------------------------------*/ |
| /* Directory Operation Functions */ |
| /*----------------------------------------------------------------------*/ |
| |
| /* FsCreateDir : create(make) a directory */ |
| int FsCreateDir(struct inode *inode, char *path, FILE_ID_T *fid) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of pointer parameters */ |
| if ((fid == NULL) || (path == NULL) || (*path == '\0')) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsCreateDir(inode, path, fid); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsCreateDir */ |
| |
| /* FsReadDir : read a directory entry from the opened directory */ |
| int FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of pointer parameters */ |
| if (dir_entry == NULL) |
| return FFS_ERROR; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsReadDir(inode, dir_entry); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsReadDir */ |
| |
| /* FsRemoveDir : remove a directory */ |
| int FsRemoveDir(struct inode *inode, FILE_ID_T *fid) |
| { |
| int err; |
| struct super_block *sb = inode->i_sb; |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* check the validity of the given file id */ |
| if (fid == NULL) |
| return FFS_INVALIDFID; |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| err = ffsRemoveDir(inode, fid); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return err; |
| } /* end of FsRemoveDir */ |
| |
| EXPORT_SYMBOL(FsMountVol); |
| EXPORT_SYMBOL(FsUmountVol); |
| EXPORT_SYMBOL(FsGetVolInfo); |
| EXPORT_SYMBOL(FsSyncVol); |
| EXPORT_SYMBOL(FsLookupFile); |
| EXPORT_SYMBOL(FsCreateFile); |
| EXPORT_SYMBOL(FsReadFile); |
| EXPORT_SYMBOL(FsWriteFile); |
| EXPORT_SYMBOL(FsTruncateFile); |
| EXPORT_SYMBOL(FsMoveFile); |
| EXPORT_SYMBOL(FsRemoveFile); |
| EXPORT_SYMBOL(FsSetAttr); |
| EXPORT_SYMBOL(FsReadStat); |
| EXPORT_SYMBOL(FsWriteStat); |
| EXPORT_SYMBOL(FsMapCluster); |
| EXPORT_SYMBOL(FsCreateDir); |
| EXPORT_SYMBOL(FsReadDir); |
| EXPORT_SYMBOL(FsRemoveDir); |
| |
| #ifdef CONFIG_EXFAT_KERNEL_DEBUG |
| /* FsReleaseCache: Release FAT & buf cache */ |
| int FsReleaseCache(struct super_block *sb) |
| { |
| FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); |
| |
| /* acquire the lock for file system critical section */ |
| sm_P(&p_fs->v_sem); |
| |
| FAT_release_all(sb); |
| buf_release_all(sb); |
| |
| /* release the lock for file system critical section */ |
| sm_V(&p_fs->v_sem); |
| |
| return 0; |
| } |
| /* FsReleaseCache */ |
| |
| EXPORT_SYMBOL(FsReleaseCache); |
| #endif /* CONFIG_EXFAT_KERNEL_DEBUG */ |
| |
| /*======================================================================*/ |
| /* Local Function Definitions */ |
| /*======================================================================*/ |