2 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 /************************************************************************/
20 /* PROJECT : exFAT & FAT12/16/32 File System */
21 /* FILE : sdfat_api.c */
22 /* PURPOSE : sdFAT volume lock layer */
24 /************************************************************************/
26 #include <linux/version.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/mutex.h>
37 /*----------------------------------------------------------------------*/
38 /* Internal structures */
39 /*----------------------------------------------------------------------*/
41 /*----------------------------------------------------------------------*/
42 /* Constant & Macro Definitions */
43 /*----------------------------------------------------------------------*/
44 static DEFINE_MUTEX(_lock_core
);
46 /*----------------------------------------------------------------------*/
47 /* Global Variable Definitions */
48 /*----------------------------------------------------------------------*/
50 /*----------------------------------------------------------------------*/
51 /* Local Variable Definitions */
52 /*----------------------------------------------------------------------*/
54 /*----------------------------------------------------------------------*/
55 /* Local Function Declarations */
56 /*----------------------------------------------------------------------*/
58 /*======================================================================*/
59 /* Global Function Definitions */
60 /* - All functions for global use have same return value format, */
61 /* that is, 0 on success and minus error number on */
62 /* various error condition. */
63 /*======================================================================*/
65 /*----------------------------------------------------------------------*/
66 /* sdFAT Filesystem Init & Exit Functions */
67 /*----------------------------------------------------------------------*/
74 s32
fsapi_shutdown(void)
76 return fscore_shutdown();
79 /*----------------------------------------------------------------------*/
80 /* Volume Management Functions */
81 /*----------------------------------------------------------------------*/
83 /* mount the file system volume */
84 s32
fsapi_mount(struct super_block
*sb
)
88 /* acquire the core lock for file system ccritical section */
89 mutex_lock(&_lock_core
);
91 err
= meta_cache_init(sb
);
95 err
= fscore_mount(sb
);
98 meta_cache_shutdown(sb
);
100 /* release the core lock for file system critical section */
101 mutex_unlock(&_lock_core
);
105 EXPORT_SYMBOL(fsapi_mount
);
107 /* unmount the file system volume */
108 s32
fsapi_umount(struct super_block
*sb
)
112 /* acquire the core lock for file system ccritical section */
113 mutex_lock(&_lock_core
);
115 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
116 err
= fscore_umount(sb
);
117 meta_cache_shutdown(sb
);
118 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
120 /* release the core lock for file system critical section */
121 mutex_unlock(&_lock_core
);
125 EXPORT_SYMBOL(fsapi_umount
);
127 /* get the information of a file system volume */
128 s32
fsapi_statfs(struct super_block
*sb
, VOL_INFO_T
*info
)
130 FS_INFO_T
*fsi
= &(SDFAT_SB(sb
)->fsi
);
132 /* check the validity of pointer parameters */
135 if (fsi
->used_clusters
== (u32
) ~0) {
138 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
139 err
= fscore_statfs(sb
, info
);
140 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
144 info
->FatType
= fsi
->vol_type
;
145 info
->ClusterSize
= fsi
->cluster_size
;
146 info
->NumClusters
= fsi
->num_clusters
- 2; /* clu 0 & 1 */
147 info
->UsedClusters
= fsi
->used_clusters
+ fsi
->reserved_clusters
;
148 info
->FreeClusters
= info
->NumClusters
- info
->UsedClusters
;
152 EXPORT_SYMBOL(fsapi_statfs
);
154 /* synchronize a file system volume */
155 s32
fsapi_sync_fs(struct super_block
*sb
, s32 do_sync
)
159 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
160 err
= fscore_sync_fs(sb
, do_sync
);
161 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
164 EXPORT_SYMBOL(fsapi_sync_fs
);
166 s32
fsapi_set_vol_flags(struct super_block
*sb
, u16 new_flag
, s32 always_sync
)
170 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
171 err
= fscore_set_vol_flags(sb
, new_flag
, always_sync
);
172 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
175 EXPORT_SYMBOL(fsapi_set_vol_flags
);
177 /*----------------------------------------------------------------------*/
178 /* File Operation Functions */
179 /*----------------------------------------------------------------------*/
182 s32
fsapi_lookup(struct inode
*inode
, u8
*path
, FILE_ID_T
*fid
)
185 struct super_block
*sb
= inode
->i_sb
;
187 /* check the validity of pointer parameters */
190 if (unlikely(!strlen(path
)))
193 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
194 err
= fscore_lookup(inode
, path
, fid
);
195 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
198 EXPORT_SYMBOL(fsapi_lookup
);
201 s32
fsapi_create(struct inode
*inode
, u8
*path
, u8 mode
, FILE_ID_T
*fid
)
204 struct super_block
*sb
= inode
->i_sb
;
206 /* check the validity of pointer parameters */
209 if (unlikely(!strlen(path
)))
212 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
213 err
= fscore_create(inode
, path
, mode
, fid
);
214 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
217 EXPORT_SYMBOL(fsapi_create
);
219 /* read the target string of symlink */
220 s32
fsapi_read_link(struct inode
*inode
, FILE_ID_T
*fid
, void *buffer
, u64 count
, u64
*rcount
)
223 struct super_block
*sb
= inode
->i_sb
;
225 /* check the validity of pointer parameters */
226 ASSERT(fid
&& buffer
);
228 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
229 err
= fscore_read_link(inode
, fid
, buffer
, count
, rcount
);
230 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
233 EXPORT_SYMBOL(fsapi_read_link
);
235 /* write the target string of symlink */
236 s32
fsapi_write_link(struct inode
*inode
, FILE_ID_T
*fid
, void *buffer
, u64 count
, u64
*wcount
)
239 struct super_block
*sb
= inode
->i_sb
;
241 /* check the validity of pointer parameters */
242 ASSERT(fid
&& buffer
);
244 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
245 err
= fscore_write_link(inode
, fid
, buffer
, count
, wcount
);
246 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
249 EXPORT_SYMBOL(fsapi_write_link
);
251 /* resize the file length */
252 s32
fsapi_truncate(struct inode
*inode
, u64 old_size
, u64 new_size
)
255 struct super_block
*sb
= inode
->i_sb
;
257 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
258 TMSG("%s entered (inode %p size %llu)\n", __func__
, inode
, new_size
);
259 err
= fscore_truncate(inode
, old_size
, new_size
);
260 TMSG("%s exitted (%d)\n", __func__
, err
);
261 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
264 EXPORT_SYMBOL(fsapi_truncate
);
266 /* rename or move a old file into a new file */
267 s32
fsapi_rename(struct inode
*old_parent_inode
, FILE_ID_T
*fid
,
268 struct inode
*new_parent_inode
, struct dentry
*new_dentry
)
271 struct super_block
*sb
= old_parent_inode
->i_sb
;
273 /* check the validity of pointer parameters */
276 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
277 err
= fscore_rename(old_parent_inode
, fid
, new_parent_inode
, new_dentry
);
278 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
281 EXPORT_SYMBOL(fsapi_rename
);
284 s32
fsapi_remove(struct inode
*inode
, FILE_ID_T
*fid
)
287 struct super_block
*sb
= inode
->i_sb
;
289 /* check the validity of pointer parameters */
292 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
293 err
= fscore_remove(inode
, fid
);
294 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
297 EXPORT_SYMBOL(fsapi_remove
);
299 /* get the information of a given file */
300 s32
fsapi_read_inode(struct inode
*inode
, DIR_ENTRY_T
*info
)
303 struct super_block
*sb
= inode
->i_sb
;
305 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
306 TMSG("%s entered (inode %p info %p\n", __func__
, inode
, info
);
307 err
= fscore_read_inode(inode
, info
);
308 TMSG("%s exited (err:%d)\n", __func__
, err
);
309 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
312 EXPORT_SYMBOL(fsapi_read_inode
);
314 /* set the information of a given file */
315 s32
fsapi_write_inode(struct inode
*inode
, DIR_ENTRY_T
*info
, int sync
)
318 struct super_block
*sb
= inode
->i_sb
;
320 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
321 TMSG("%s entered (inode %p info %p sync:%d\n",
322 __func__
, inode
, info
, sync
);
323 err
= fscore_write_inode(inode
, info
, sync
);
324 TMSG("%s exited (err:%d)\n", __func__
, err
);
325 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
328 EXPORT_SYMBOL(fsapi_write_inode
);
330 /* return the cluster number in the given cluster offset */
331 s32
fsapi_map_clus(struct inode
*inode
, s32 clu_offset
, u32
*clu
, int dest
)
334 struct super_block
*sb
= inode
->i_sb
;
336 /* check the validity of pointer parameters */
339 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
340 TMSG("%s entered (inode:%p clus:%08x dest:%d\n",
341 __func__
, inode
, *clu
, dest
);
342 err
= fscore_map_clus(inode
, clu_offset
, clu
, dest
);
343 TMSG("%s exited (clu:%08x err:%d)\n", __func__
, *clu
, err
);
344 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
347 EXPORT_SYMBOL(fsapi_map_clus
);
349 /* reserve a cluster */
350 s32
fsapi_reserve_clus(struct inode
*inode
)
353 struct super_block
*sb
= inode
->i_sb
;
355 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
356 TMSG("%s entered (inode:%p)\n", __func__
, inode
);
357 err
= fscore_reserve_clus(inode
);
358 TMSG("%s exited (err:%d)\n", __func__
, err
);
359 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
362 EXPORT_SYMBOL(fsapi_reserve_clus
);
364 /*----------------------------------------------------------------------*/
365 /* Directory Operation Functions */
366 /*----------------------------------------------------------------------*/
368 /* create(make) a directory */
369 s32
fsapi_mkdir(struct inode
*inode
, u8
*path
, FILE_ID_T
*fid
)
372 struct super_block
*sb
= inode
->i_sb
;
374 /* check the validity of pointer parameters */
377 if (unlikely(!strlen(path
)))
380 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
381 err
= fscore_mkdir(inode
, path
, fid
);
382 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
385 EXPORT_SYMBOL(fsapi_mkdir
);
387 /* read a directory entry from the opened directory */
388 s32
fsapi_readdir(struct inode
*inode
, DIR_ENTRY_T
*dir_entry
)
391 struct super_block
*sb
= inode
->i_sb
;
393 /* check the validity of pointer parameters */
396 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
397 err
= fscore_readdir(inode
, dir_entry
);
398 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
401 EXPORT_SYMBOL(fsapi_readdir
);
403 /* remove a directory */
404 s32
fsapi_rmdir(struct inode
*inode
, FILE_ID_T
*fid
)
407 struct super_block
*sb
= inode
->i_sb
;
409 /* check the validity of pointer parameters */
412 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
413 err
= fscore_rmdir(inode
, fid
);
414 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
417 EXPORT_SYMBOL(fsapi_rmdir
);
420 * that is, remove an entry from a directory. BUT don't truncate
422 s32
fsapi_unlink(struct inode
*inode
, FILE_ID_T
*fid
)
425 struct super_block
*sb
= inode
->i_sb
;
427 /* check the validity of pointer parameters */
429 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
430 err
= fscore_unlink(inode
, fid
);
431 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
434 EXPORT_SYMBOL(fsapi_unlink
);
436 /* reflect the internal dirty flags to VFS bh dirty flags */
437 s32
fsapi_cache_flush(struct super_block
*sb
, int do_sync
)
439 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
440 fcache_flush(sb
, do_sync
);
441 dcache_flush(sb
, do_sync
);
442 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
445 EXPORT_SYMBOL(fsapi_cache_flush
);
447 /* release FAT & buf cache */
448 s32
fsapi_cache_release(struct super_block
*sb
)
450 #ifdef CONFIG_SDFAT_DEBUG
451 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
453 fcache_release_all(sb
);
454 dcache_release_all(sb
);
456 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
457 #endif /* CONFIG_SDFAT_DEBUG */
460 EXPORT_SYMBOL(fsapi_cache_release
);
462 u32
fsapi_get_au_stat(struct super_block
*sb
, s32 mode
)
464 /* volume lock is not required */
465 return fscore_get_au_stat(sb
, mode
);
467 EXPORT_SYMBOL(fsapi_get_au_stat
);
469 /* clear extent cache */
470 void fsapi_invalidate_extent(struct inode
*inode
)
472 /* Volume lock is not required,
473 * because it is only called by evict_inode.
474 * If any other function can call it,
475 * you should check whether volume lock is needed or not.
477 extent_cache_inval_inode(inode
);
479 EXPORT_SYMBOL(fsapi_invalidate_extent
);
483 #ifdef CONFIG_SDFAT_DFR
484 /*----------------------------------------------------------------------*/
485 /* Defragmentation related */
486 /*----------------------------------------------------------------------*/
487 s32
fsapi_dfr_get_info(struct super_block
*sb
, void *arg
)
489 /* volume lock is not required */
490 return defrag_get_info(sb
, (struct defrag_info_arg
*)arg
);
492 EXPORT_SYMBOL(fsapi_dfr_get_info
);
494 s32
fsapi_dfr_scan_dir(struct super_block
*sb
, void *args
)
498 /* check the validity of pointer parameters */
501 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
502 err
= defrag_scan_dir(sb
, (struct defrag_trav_arg
*)args
);
503 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
506 EXPORT_SYMBOL(fsapi_dfr_scan_dir
);
508 s32
fsapi_dfr_validate_clus(struct inode
*inode
, void *chunk
, int skip_prev
)
511 struct super_block
*sb
= inode
->i_sb
;
513 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
514 err
= defrag_validate_cluster(inode
,
515 (struct defrag_chunk_info
*)chunk
, skip_prev
);
516 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
519 EXPORT_SYMBOL(fsapi_dfr_validate_clus
);
521 s32
fsapi_dfr_reserve_clus(struct super_block
*sb
, s32 nr_clus
)
525 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
526 err
= defrag_reserve_clusters(sb
, nr_clus
);
527 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
530 EXPORT_SYMBOL(fsapi_dfr_reserve_clus
);
532 s32
fsapi_dfr_mark_ignore(struct super_block
*sb
, unsigned int clus
)
534 /* volume lock is not required */
535 return defrag_mark_ignore(sb
, clus
);
537 EXPORT_SYMBOL(fsapi_dfr_mark_ignore
);
539 void fsapi_dfr_unmark_ignore_all(struct super_block
*sb
)
541 /* volume lock is not required */
542 defrag_unmark_ignore_all(sb
);
544 EXPORT_SYMBOL(fsapi_dfr_unmark_ignore_all
);
546 s32
fsapi_dfr_map_clus(struct inode
*inode
, u32 clu_offset
, u32
*clu
)
549 struct super_block
*sb
= inode
->i_sb
;
551 /* check the validity of pointer parameters */
554 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
555 err
= defrag_map_cluster(inode
, clu_offset
, clu
);
556 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
560 EXPORT_SYMBOL(fsapi_dfr_map_clus
);
562 void fsapi_dfr_writepage_endio(struct page
*page
)
564 /* volume lock is not required */
565 defrag_writepage_end_io(page
);
567 EXPORT_SYMBOL(fsapi_dfr_writepage_endio
);
569 void fsapi_dfr_update_fat_prev(struct super_block
*sb
, int force
)
571 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
572 defrag_update_fat_prev(sb
, force
);
573 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
575 EXPORT_SYMBOL(fsapi_dfr_update_fat_prev
);
577 void fsapi_dfr_update_fat_next(struct super_block
*sb
)
579 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
580 defrag_update_fat_next(sb
);
581 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
583 EXPORT_SYMBOL(fsapi_dfr_update_fat_next
);
585 void fsapi_dfr_check_discard(struct super_block
*sb
)
587 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
588 defrag_check_discard(sb
);
589 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
591 EXPORT_SYMBOL(fsapi_dfr_check_discard
);
593 void fsapi_dfr_free_clus(struct super_block
*sb
, u32 clus
)
595 mutex_lock(&(SDFAT_SB(sb
)->s_vlock
));
596 defrag_free_cluster(sb
, clus
);
597 mutex_unlock(&(SDFAT_SB(sb
)->s_vlock
));
599 EXPORT_SYMBOL(fsapi_dfr_free_clus
);
601 s32
fsapi_dfr_check_dfr_required(struct super_block
*sb
, int *totalau
, int *cleanau
, int *fullau
)
603 /* volume lock is not required */
604 return defrag_check_defrag_required(sb
, totalau
, cleanau
, fullau
);
606 EXPORT_SYMBOL(fsapi_dfr_check_dfr_required
);
608 s32
fsapi_dfr_check_dfr_on(struct inode
*inode
, loff_t start
, loff_t end
, s32 cancel
, const char *caller
)
610 /* volume lock is not required */
611 return defrag_check_defrag_on(inode
, start
, end
, cancel
, caller
);
613 EXPORT_SYMBOL(fsapi_dfr_check_dfr_on
);
617 #ifdef CONFIG_SDFAT_DFR_DEBUG
618 void fsapi_dfr_spo_test(struct super_block
*sb
, int flag
, const char *caller
)
620 /* volume lock is not required */
621 defrag_spo_test(sb
, flag
, caller
);
623 EXPORT_SYMBOL(fsapi_dfr_spo_test
);
627 #endif /* CONFIG_SDFAT_DFR */
629 /* end of sdfat_api.c */