fs: Add sdfat
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / fs / sdfat / api.c
1 /*
2 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
3 *
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.
8 *
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.
13 *
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/>.
16 */
17
18 /************************************************************************/
19 /* */
20 /* PROJECT : exFAT & FAT12/16/32 File System */
21 /* FILE : sdfat_api.c */
22 /* PURPOSE : sdFAT volume lock layer */
23 /* */
24 /************************************************************************/
25
26 #include <linux/version.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/mutex.h>
30
31 #include "version.h"
32 #include "config.h"
33
34 #include "sdfat.h"
35 #include "core.h"
36
37 /*----------------------------------------------------------------------*/
38 /* Internal structures */
39 /*----------------------------------------------------------------------*/
40
41 /*----------------------------------------------------------------------*/
42 /* Constant & Macro Definitions */
43 /*----------------------------------------------------------------------*/
44 static DEFINE_MUTEX(_lock_core);
45
46 /*----------------------------------------------------------------------*/
47 /* Global Variable Definitions */
48 /*----------------------------------------------------------------------*/
49
50 /*----------------------------------------------------------------------*/
51 /* Local Variable Definitions */
52 /*----------------------------------------------------------------------*/
53
54 /*----------------------------------------------------------------------*/
55 /* Local Function Declarations */
56 /*----------------------------------------------------------------------*/
57
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 /*======================================================================*/
64
65 /*----------------------------------------------------------------------*/
66 /* sdFAT Filesystem Init & Exit Functions */
67 /*----------------------------------------------------------------------*/
68
69 s32 fsapi_init(void)
70 {
71 return fscore_init();
72 }
73
74 s32 fsapi_shutdown(void)
75 {
76 return fscore_shutdown();
77 }
78
79 /*----------------------------------------------------------------------*/
80 /* Volume Management Functions */
81 /*----------------------------------------------------------------------*/
82
83 /* mount the file system volume */
84 s32 fsapi_mount(struct super_block *sb)
85 {
86 s32 err;
87
88 /* acquire the core lock for file system ccritical section */
89 mutex_lock(&_lock_core);
90
91 err = meta_cache_init(sb);
92 if (err)
93 goto out;
94
95 err = fscore_mount(sb);
96 out:
97 if (err)
98 meta_cache_shutdown(sb);
99
100 /* release the core lock for file system critical section */
101 mutex_unlock(&_lock_core);
102
103 return err;
104 }
105 EXPORT_SYMBOL(fsapi_mount);
106
107 /* unmount the file system volume */
108 s32 fsapi_umount(struct super_block *sb)
109 {
110 s32 err;
111
112 /* acquire the core lock for file system ccritical section */
113 mutex_lock(&_lock_core);
114
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));
119
120 /* release the core lock for file system critical section */
121 mutex_unlock(&_lock_core);
122
123 return err;
124 }
125 EXPORT_SYMBOL(fsapi_umount);
126
127 /* get the information of a file system volume */
128 s32 fsapi_statfs(struct super_block *sb, VOL_INFO_T *info)
129 {
130 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
131
132 /* check the validity of pointer parameters */
133 ASSERT(info);
134
135 if (fsi->used_clusters == (u32) ~0) {
136 s32 err;
137
138 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
139 err = fscore_statfs(sb, info);
140 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
141 return err;
142 }
143
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;
149
150 return 0;
151 }
152 EXPORT_SYMBOL(fsapi_statfs);
153
154 /* synchronize a file system volume */
155 s32 fsapi_sync_fs(struct super_block *sb, s32 do_sync)
156 {
157 s32 err;
158
159 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
160 err = fscore_sync_fs(sb, do_sync);
161 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
162 return err;
163 }
164 EXPORT_SYMBOL(fsapi_sync_fs);
165
166 s32 fsapi_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync)
167 {
168 s32 err;
169
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));
173 return err;
174 }
175 EXPORT_SYMBOL(fsapi_set_vol_flags);
176
177 /*----------------------------------------------------------------------*/
178 /* File Operation Functions */
179 /*----------------------------------------------------------------------*/
180
181 /* lookup */
182 s32 fsapi_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid)
183 {
184 s32 err;
185 struct super_block *sb = inode->i_sb;
186
187 /* check the validity of pointer parameters */
188 ASSERT(fid && path);
189
190 if (unlikely(!strlen(path)))
191 return -EINVAL;
192
193 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
194 err = fscore_lookup(inode, path, fid);
195 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
196 return err;
197 }
198 EXPORT_SYMBOL(fsapi_lookup);
199
200 /* create a file */
201 s32 fsapi_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid)
202 {
203 s32 err;
204 struct super_block *sb = inode->i_sb;
205
206 /* check the validity of pointer parameters */
207 ASSERT(fid && path);
208
209 if (unlikely(!strlen(path)))
210 return -EINVAL;
211
212 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
213 err = fscore_create(inode, path, mode, fid);
214 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
215 return err;
216 }
217 EXPORT_SYMBOL(fsapi_create);
218
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)
221 {
222 s32 err;
223 struct super_block *sb = inode->i_sb;
224
225 /* check the validity of pointer parameters */
226 ASSERT(fid && buffer);
227
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));
231 return err;
232 }
233 EXPORT_SYMBOL(fsapi_read_link);
234
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)
237 {
238 s32 err;
239 struct super_block *sb = inode->i_sb;
240
241 /* check the validity of pointer parameters */
242 ASSERT(fid && buffer);
243
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));
247 return err;
248 }
249 EXPORT_SYMBOL(fsapi_write_link);
250
251 /* resize the file length */
252 s32 fsapi_truncate(struct inode *inode, u64 old_size, u64 new_size)
253 {
254 s32 err;
255 struct super_block *sb = inode->i_sb;
256
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));
262 return err;
263 }
264 EXPORT_SYMBOL(fsapi_truncate);
265
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)
269 {
270 s32 err;
271 struct super_block *sb = old_parent_inode->i_sb;
272
273 /* check the validity of pointer parameters */
274 ASSERT(fid);
275
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));
279 return err;
280 }
281 EXPORT_SYMBOL(fsapi_rename);
282
283 /* remove a file */
284 s32 fsapi_remove(struct inode *inode, FILE_ID_T *fid)
285 {
286 s32 err;
287 struct super_block *sb = inode->i_sb;
288
289 /* check the validity of pointer parameters */
290 ASSERT(fid);
291
292 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
293 err = fscore_remove(inode, fid);
294 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
295 return err;
296 }
297 EXPORT_SYMBOL(fsapi_remove);
298
299 /* get the information of a given file */
300 s32 fsapi_read_inode(struct inode *inode, DIR_ENTRY_T *info)
301 {
302 s32 err;
303 struct super_block *sb = inode->i_sb;
304
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));
310 return err;
311 }
312 EXPORT_SYMBOL(fsapi_read_inode);
313
314 /* set the information of a given file */
315 s32 fsapi_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync)
316 {
317 s32 err;
318 struct super_block *sb = inode->i_sb;
319
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));
326 return err;
327 }
328 EXPORT_SYMBOL(fsapi_write_inode);
329
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)
332 {
333 s32 err;
334 struct super_block *sb = inode->i_sb;
335
336 /* check the validity of pointer parameters */
337 ASSERT(clu);
338
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));
345 return err;
346 }
347 EXPORT_SYMBOL(fsapi_map_clus);
348
349 /* reserve a cluster */
350 s32 fsapi_reserve_clus(struct inode *inode)
351 {
352 s32 err;
353 struct super_block *sb = inode->i_sb;
354
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));
360 return err;
361 }
362 EXPORT_SYMBOL(fsapi_reserve_clus);
363
364 /*----------------------------------------------------------------------*/
365 /* Directory Operation Functions */
366 /*----------------------------------------------------------------------*/
367
368 /* create(make) a directory */
369 s32 fsapi_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid)
370 {
371 s32 err;
372 struct super_block *sb = inode->i_sb;
373
374 /* check the validity of pointer parameters */
375 ASSERT(fid && path);
376
377 if (unlikely(!strlen(path)))
378 return -EINVAL;
379
380 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
381 err = fscore_mkdir(inode, path, fid);
382 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
383 return err;
384 }
385 EXPORT_SYMBOL(fsapi_mkdir);
386
387 /* read a directory entry from the opened directory */
388 s32 fsapi_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry)
389 {
390 s32 err;
391 struct super_block *sb = inode->i_sb;
392
393 /* check the validity of pointer parameters */
394 ASSERT(dir_entry);
395
396 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
397 err = fscore_readdir(inode, dir_entry);
398 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
399 return err;
400 }
401 EXPORT_SYMBOL(fsapi_readdir);
402
403 /* remove a directory */
404 s32 fsapi_rmdir(struct inode *inode, FILE_ID_T *fid)
405 {
406 s32 err;
407 struct super_block *sb = inode->i_sb;
408
409 /* check the validity of pointer parameters */
410 ASSERT(fid);
411
412 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
413 err = fscore_rmdir(inode, fid);
414 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
415 return err;
416 }
417 EXPORT_SYMBOL(fsapi_rmdir);
418
419 /* unlink a file.
420 * that is, remove an entry from a directory. BUT don't truncate
421 */
422 s32 fsapi_unlink(struct inode *inode, FILE_ID_T *fid)
423 {
424 s32 err;
425 struct super_block *sb = inode->i_sb;
426
427 /* check the validity of pointer parameters */
428 ASSERT(fid);
429 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
430 err = fscore_unlink(inode, fid);
431 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
432 return err;
433 }
434 EXPORT_SYMBOL(fsapi_unlink);
435
436 /* reflect the internal dirty flags to VFS bh dirty flags */
437 s32 fsapi_cache_flush(struct super_block *sb, int do_sync)
438 {
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));
443 return 0;
444 }
445 EXPORT_SYMBOL(fsapi_cache_flush);
446
447 /* release FAT & buf cache */
448 s32 fsapi_cache_release(struct super_block *sb)
449 {
450 #ifdef CONFIG_SDFAT_DEBUG
451 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
452
453 fcache_release_all(sb);
454 dcache_release_all(sb);
455
456 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
457 #endif /* CONFIG_SDFAT_DEBUG */
458 return 0;
459 }
460 EXPORT_SYMBOL(fsapi_cache_release);
461
462 u32 fsapi_get_au_stat(struct super_block *sb, s32 mode)
463 {
464 /* volume lock is not required */
465 return fscore_get_au_stat(sb, mode);
466 }
467 EXPORT_SYMBOL(fsapi_get_au_stat);
468
469 /* clear extent cache */
470 void fsapi_invalidate_extent(struct inode *inode)
471 {
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.
476 */
477 extent_cache_inval_inode(inode);
478 }
479 EXPORT_SYMBOL(fsapi_invalidate_extent);
480
481
482
483 #ifdef CONFIG_SDFAT_DFR
484 /*----------------------------------------------------------------------*/
485 /* Defragmentation related */
486 /*----------------------------------------------------------------------*/
487 s32 fsapi_dfr_get_info(struct super_block *sb, void *arg)
488 {
489 /* volume lock is not required */
490 return defrag_get_info(sb, (struct defrag_info_arg *)arg);
491 }
492 EXPORT_SYMBOL(fsapi_dfr_get_info);
493
494 s32 fsapi_dfr_scan_dir(struct super_block *sb, void *args)
495 {
496 s32 err;
497
498 /* check the validity of pointer parameters */
499 ASSERT(args);
500
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));
504 return err;
505 }
506 EXPORT_SYMBOL(fsapi_dfr_scan_dir);
507
508 s32 fsapi_dfr_validate_clus(struct inode *inode, void *chunk, int skip_prev)
509 {
510 s32 err;
511 struct super_block *sb = inode->i_sb;
512
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));
517 return err;
518 }
519 EXPORT_SYMBOL(fsapi_dfr_validate_clus);
520
521 s32 fsapi_dfr_reserve_clus(struct super_block *sb, s32 nr_clus)
522 {
523 s32 err;
524
525 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
526 err = defrag_reserve_clusters(sb, nr_clus);
527 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
528 return err;
529 }
530 EXPORT_SYMBOL(fsapi_dfr_reserve_clus);
531
532 s32 fsapi_dfr_mark_ignore(struct super_block *sb, unsigned int clus)
533 {
534 /* volume lock is not required */
535 return defrag_mark_ignore(sb, clus);
536 }
537 EXPORT_SYMBOL(fsapi_dfr_mark_ignore);
538
539 void fsapi_dfr_unmark_ignore_all(struct super_block *sb)
540 {
541 /* volume lock is not required */
542 defrag_unmark_ignore_all(sb);
543 }
544 EXPORT_SYMBOL(fsapi_dfr_unmark_ignore_all);
545
546 s32 fsapi_dfr_map_clus(struct inode *inode, u32 clu_offset, u32 *clu)
547 {
548 s32 err;
549 struct super_block *sb = inode->i_sb;
550
551 /* check the validity of pointer parameters */
552 ASSERT(clu);
553
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));
557
558 return err;
559 }
560 EXPORT_SYMBOL(fsapi_dfr_map_clus);
561
562 void fsapi_dfr_writepage_endio(struct page *page)
563 {
564 /* volume lock is not required */
565 defrag_writepage_end_io(page);
566 }
567 EXPORT_SYMBOL(fsapi_dfr_writepage_endio);
568
569 void fsapi_dfr_update_fat_prev(struct super_block *sb, int force)
570 {
571 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
572 defrag_update_fat_prev(sb, force);
573 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
574 }
575 EXPORT_SYMBOL(fsapi_dfr_update_fat_prev);
576
577 void fsapi_dfr_update_fat_next(struct super_block *sb)
578 {
579 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
580 defrag_update_fat_next(sb);
581 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
582 }
583 EXPORT_SYMBOL(fsapi_dfr_update_fat_next);
584
585 void fsapi_dfr_check_discard(struct super_block *sb)
586 {
587 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
588 defrag_check_discard(sb);
589 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
590 }
591 EXPORT_SYMBOL(fsapi_dfr_check_discard);
592
593 void fsapi_dfr_free_clus(struct super_block *sb, u32 clus)
594 {
595 mutex_lock(&(SDFAT_SB(sb)->s_vlock));
596 defrag_free_cluster(sb, clus);
597 mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
598 }
599 EXPORT_SYMBOL(fsapi_dfr_free_clus);
600
601 s32 fsapi_dfr_check_dfr_required(struct super_block *sb, int *totalau, int *cleanau, int *fullau)
602 {
603 /* volume lock is not required */
604 return defrag_check_defrag_required(sb, totalau, cleanau, fullau);
605 }
606 EXPORT_SYMBOL(fsapi_dfr_check_dfr_required);
607
608 s32 fsapi_dfr_check_dfr_on(struct inode *inode, loff_t start, loff_t end, s32 cancel, const char *caller)
609 {
610 /* volume lock is not required */
611 return defrag_check_defrag_on(inode, start, end, cancel, caller);
612 }
613 EXPORT_SYMBOL(fsapi_dfr_check_dfr_on);
614
615
616
617 #ifdef CONFIG_SDFAT_DFR_DEBUG
618 void fsapi_dfr_spo_test(struct super_block *sb, int flag, const char *caller)
619 {
620 /* volume lock is not required */
621 defrag_spo_test(sb, flag, caller);
622 }
623 EXPORT_SYMBOL(fsapi_dfr_spo_test);
624 #endif
625
626
627 #endif /* CONFIG_SDFAT_DFR */
628
629 /* end of sdfat_api.c */