123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- /*
- * 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, see <http://www.gnu.org/licenses/>.
- */
- /************************************************************************/
- /* */
- /* PROJECT : exFAT & FAT12/16/32 File System */
- /* FILE : sdfat_api.c */
- /* PURPOSE : sdFAT volume lock layer */
- /* */
- /************************************************************************/
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/mutex.h>
- #include "version.h"
- #include "config.h"
- #include "sdfat.h"
- #include "core.h"
- /*----------------------------------------------------------------------*/
- /* Internal structures */
- /*----------------------------------------------------------------------*/
- /*----------------------------------------------------------------------*/
- /* Constant & Macro Definitions */
- /*----------------------------------------------------------------------*/
- static DEFINE_MUTEX(_lock_core);
- /*----------------------------------------------------------------------*/
- /* Global Variable Definitions */
- /*----------------------------------------------------------------------*/
- /*----------------------------------------------------------------------*/
- /* Local Variable Definitions */
- /*----------------------------------------------------------------------*/
- /*----------------------------------------------------------------------*/
- /* Local Function Declarations */
- /*----------------------------------------------------------------------*/
- /*======================================================================*/
- /* Global Function Definitions */
- /* - All functions for global use have same return value format, */
- /* that is, 0 on success and minus error number on */
- /* various error condition. */
- /*======================================================================*/
- /*----------------------------------------------------------------------*/
- /* sdFAT Filesystem Init & Exit Functions */
- /*----------------------------------------------------------------------*/
- s32 fsapi_init(void)
- {
- return fscore_init();
- }
- s32 fsapi_shutdown(void)
- {
- return fscore_shutdown();
- }
- /*----------------------------------------------------------------------*/
- /* Volume Management Functions */
- /*----------------------------------------------------------------------*/
- /* mount the file system volume */
- s32 fsapi_mount(struct super_block *sb)
- {
- s32 err;
- /* acquire the core lock for file system ccritical section */
- mutex_lock(&_lock_core);
- err = meta_cache_init(sb);
- if (err)
- goto out;
- err = fscore_mount(sb);
- out:
- if (err)
- meta_cache_shutdown(sb);
- /* release the core lock for file system critical section */
- mutex_unlock(&_lock_core);
- return err;
- }
- EXPORT_SYMBOL(fsapi_mount);
- /* unmount the file system volume */
- s32 fsapi_umount(struct super_block *sb)
- {
- s32 err;
- /* acquire the core lock for file system ccritical section */
- mutex_lock(&_lock_core);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_umount(sb);
- meta_cache_shutdown(sb);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- /* release the core lock for file system critical section */
- mutex_unlock(&_lock_core);
- return err;
- }
- EXPORT_SYMBOL(fsapi_umount);
- /* get the information of a file system volume */
- s32 fsapi_statfs(struct super_block *sb, VOL_INFO_T *info)
- {
- FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- /* check the validity of pointer parameters */
- ASSERT(info);
- if (fsi->used_clusters == (u32) ~0) {
- s32 err;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_statfs(sb, info);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- info->FatType = fsi->vol_type;
- info->ClusterSize = fsi->cluster_size;
- info->NumClusters = fsi->num_clusters - 2; /* clu 0 & 1 */
- info->UsedClusters = fsi->used_clusters + fsi->reserved_clusters;
- info->FreeClusters = info->NumClusters - info->UsedClusters;
- return 0;
- }
- EXPORT_SYMBOL(fsapi_statfs);
- /* synchronize a file system volume */
- s32 fsapi_sync_fs(struct super_block *sb, s32 do_sync)
- {
- s32 err;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_sync_fs(sb, do_sync);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_sync_fs);
- s32 fsapi_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync)
- {
- s32 err;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_set_vol_flags(sb, new_flag, always_sync);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_set_vol_flags);
- /*----------------------------------------------------------------------*/
- /* File Operation Functions */
- /*----------------------------------------------------------------------*/
- /* lookup */
- s32 fsapi_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid && path);
- if (unlikely(!strlen(path)))
- return -EINVAL;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_lookup(inode, path, fid);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_lookup);
- /* create a file */
- s32 fsapi_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid && path);
- if (unlikely(!strlen(path)))
- return -EINVAL;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_create(inode, path, mode, fid);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_create);
- /* read the target string of symlink */
- s32 fsapi_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid && buffer);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_read_link(inode, fid, buffer, count, rcount);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_read_link);
- /* write the target string of symlink */
- s32 fsapi_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid && buffer);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_write_link(inode, fid, buffer, count, wcount);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_write_link);
- /* resize the file length */
- s32 fsapi_truncate(struct inode *inode, u64 old_size, u64 new_size)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- TMSG("%s entered (inode %p size %llu)\n", __func__, inode, new_size);
- err = fscore_truncate(inode, old_size, new_size);
- TMSG("%s exitted (%d)\n", __func__, err);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_truncate);
- /* rename or move a old file into a new file */
- s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid,
- struct inode *new_parent_inode, struct dentry *new_dentry)
- {
- s32 err;
- struct super_block *sb = old_parent_inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_rename(old_parent_inode, fid, new_parent_inode, new_dentry);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_rename);
- /* remove a file */
- s32 fsapi_remove(struct inode *inode, FILE_ID_T *fid)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_remove(inode, fid);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_remove);
- /* get the information of a given file */
- s32 fsapi_read_inode(struct inode *inode, DIR_ENTRY_T *info)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- TMSG("%s entered (inode %p info %p\n", __func__, inode, info);
- err = fscore_read_inode(inode, info);
- TMSG("%s exited (err:%d)\n", __func__, err);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_read_inode);
- /* set the information of a given file */
- s32 fsapi_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- TMSG("%s entered (inode %p info %p sync:%d\n",
- __func__, inode, info, sync);
- err = fscore_write_inode(inode, info, sync);
- TMSG("%s exited (err:%d)\n", __func__, err);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_write_inode);
- /* return the cluster number in the given cluster offset */
- s32 fsapi_map_clus(struct inode *inode, u32 clu_offset, u32 *clu, int dest)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(clu);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- TMSG("%s entered (inode:%p clus:%08x dest:%d\n",
- __func__, inode, *clu, dest);
- err = fscore_map_clus(inode, clu_offset, clu, dest);
- TMSG("%s exited (clu:%08x err:%d)\n", __func__, *clu, err);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_map_clus);
- /* reserve a cluster */
- s32 fsapi_reserve_clus(struct inode *inode)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- TMSG("%s entered (inode:%p)\n", __func__, inode);
- err = fscore_reserve_clus(inode);
- TMSG("%s exited (err:%d)\n", __func__, err);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_reserve_clus);
- /*----------------------------------------------------------------------*/
- /* Directory Operation Functions */
- /*----------------------------------------------------------------------*/
- /* create(make) a directory */
- s32 fsapi_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid && path);
- if (unlikely(!strlen(path)))
- return -EINVAL;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_mkdir(inode, path, fid);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_mkdir);
- /* read a directory entry from the opened directory */
- s32 fsapi_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(dir_entry);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_readdir(inode, dir_entry);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_readdir);
- /* remove a directory */
- s32 fsapi_rmdir(struct inode *inode, FILE_ID_T *fid)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_rmdir(inode, fid);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_rmdir);
- /* unlink a file.
- * that is, remove an entry from a directory. BUT don't truncate
- */
- s32 fsapi_unlink(struct inode *inode, FILE_ID_T *fid)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(fid);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = fscore_unlink(inode, fid);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_unlink);
- /* reflect the internal dirty flags to VFS bh dirty flags */
- s32 fsapi_cache_flush(struct super_block *sb, int do_sync)
- {
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- fcache_flush(sb, do_sync);
- dcache_flush(sb, do_sync);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return 0;
- }
- EXPORT_SYMBOL(fsapi_cache_flush);
- /* release FAT & buf cache */
- s32 fsapi_cache_release(struct super_block *sb)
- {
- #ifdef CONFIG_SDFAT_DEBUG
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- fcache_release_all(sb);
- dcache_release_all(sb);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- #endif /* CONFIG_SDFAT_DEBUG */
- return 0;
- }
- EXPORT_SYMBOL(fsapi_cache_release);
- u32 fsapi_get_au_stat(struct super_block *sb, s32 mode)
- {
- /* volume lock is not required */
- return fscore_get_au_stat(sb, mode);
- }
- EXPORT_SYMBOL(fsapi_get_au_stat);
- /* clear extent cache */
- void fsapi_invalidate_extent(struct inode *inode)
- {
- /* Volume lock is not required,
- * because it is only called by evict_inode.
- * If any other function can call it,
- * you should check whether volume lock is needed or not.
- */
- extent_cache_inval_inode(inode);
- }
- EXPORT_SYMBOL(fsapi_invalidate_extent);
- /* check device is ejected */
- s32 fsapi_check_bdi_valid(struct super_block *sb)
- {
- return fscore_check_bdi_valid(sb);
- }
- EXPORT_SYMBOL(fsapi_check_bdi_valid);
- #ifdef CONFIG_SDFAT_DFR
- /*----------------------------------------------------------------------*/
- /* Defragmentation related */
- /*----------------------------------------------------------------------*/
- s32 fsapi_dfr_get_info(struct super_block *sb, void *arg)
- {
- /* volume lock is not required */
- return defrag_get_info(sb, (struct defrag_info_arg *)arg);
- }
- EXPORT_SYMBOL(fsapi_dfr_get_info);
- s32 fsapi_dfr_scan_dir(struct super_block *sb, void *args)
- {
- s32 err;
- /* check the validity of pointer parameters */
- ASSERT(args);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = defrag_scan_dir(sb, (struct defrag_trav_arg *)args);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_dfr_scan_dir);
- s32 fsapi_dfr_validate_clus(struct inode *inode, void *chunk, int skip_prev)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = defrag_validate_cluster(inode,
- (struct defrag_chunk_info *)chunk, skip_prev);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_dfr_validate_clus);
- s32 fsapi_dfr_reserve_clus(struct super_block *sb, s32 nr_clus)
- {
- s32 err;
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = defrag_reserve_clusters(sb, nr_clus);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_dfr_reserve_clus);
- s32 fsapi_dfr_mark_ignore(struct super_block *sb, unsigned int clus)
- {
- /* volume lock is not required */
- return defrag_mark_ignore(sb, clus);
- }
- EXPORT_SYMBOL(fsapi_dfr_mark_ignore);
- void fsapi_dfr_unmark_ignore_all(struct super_block *sb)
- {
- /* volume lock is not required */
- defrag_unmark_ignore_all(sb);
- }
- EXPORT_SYMBOL(fsapi_dfr_unmark_ignore_all);
- s32 fsapi_dfr_map_clus(struct inode *inode, u32 clu_offset, u32 *clu)
- {
- s32 err;
- struct super_block *sb = inode->i_sb;
- /* check the validity of pointer parameters */
- ASSERT(clu);
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = defrag_map_cluster(inode, clu_offset, clu);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return err;
- }
- EXPORT_SYMBOL(fsapi_dfr_map_clus);
- void fsapi_dfr_writepage_endio(struct page *page)
- {
- /* volume lock is not required */
- defrag_writepage_end_io(page);
- }
- EXPORT_SYMBOL(fsapi_dfr_writepage_endio);
- void fsapi_dfr_update_fat_prev(struct super_block *sb, int force)
- {
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- defrag_update_fat_prev(sb, force);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- }
- EXPORT_SYMBOL(fsapi_dfr_update_fat_prev);
- void fsapi_dfr_update_fat_next(struct super_block *sb)
- {
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- defrag_update_fat_next(sb);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- }
- EXPORT_SYMBOL(fsapi_dfr_update_fat_next);
- void fsapi_dfr_check_discard(struct super_block *sb)
- {
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- defrag_check_discard(sb);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- }
- EXPORT_SYMBOL(fsapi_dfr_check_discard);
- void fsapi_dfr_free_clus(struct super_block *sb, u32 clus)
- {
- mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- defrag_free_cluster(sb, clus);
- mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- }
- EXPORT_SYMBOL(fsapi_dfr_free_clus);
- s32 fsapi_dfr_check_dfr_required(struct super_block *sb, int *totalau, int *cleanau, int *fullau)
- {
- /* volume lock is not required */
- return defrag_check_defrag_required(sb, totalau, cleanau, fullau);
- }
- EXPORT_SYMBOL(fsapi_dfr_check_dfr_required);
- s32 fsapi_dfr_check_dfr_on(struct inode *inode, loff_t start, loff_t end, s32 cancel, const char *caller)
- {
- /* volume lock is not required */
- return defrag_check_defrag_on(inode, start, end, cancel, caller);
- }
- EXPORT_SYMBOL(fsapi_dfr_check_dfr_on);
- #ifdef CONFIG_SDFAT_DFR_DEBUG
- void fsapi_dfr_spo_test(struct super_block *sb, int flag, const char *caller)
- {
- /* volume lock is not required */
- defrag_spo_test(sb, flag, caller);
- }
- EXPORT_SYMBOL(fsapi_dfr_spo_test);
- #endif
- #endif /* CONFIG_SDFAT_DFR */
- /* end of sdfat_api.c */
|