tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / fs / exfat / exfat_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, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #include <linux/version.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22
23 #include "exfat_version.h"
24 #include "exfat_config.h"
25 #include "exfat_global.h"
26 #include "exfat_data.h"
27 #include "exfat_oal.h"
28
29 #include "exfat_part.h"
30 #include "exfat_nls.h"
31 #include "exfat_api.h"
32 #include "exfat_super.h"
33 #include "exfat.h"
34
35 extern FS_STRUCT_T      fs_struct[];
36
37 extern struct semaphore z_sem;
38
39 INT32 FsInit(void)
40 {
41         INT32 i;
42
43         for (i = 0; i < MAX_DRIVE; i++) {
44                 fs_struct[i].mounted = FALSE;
45                 fs_struct[i].sb = NULL;
46                 sm_init(&(fs_struct[i].v_sem));
47         }
48
49         return(ffsInit());
50 }
51
52 INT32 FsShutdown(void)
53 {
54         INT32 i;
55
56         for (i = 0; i < MAX_DRIVE; i++) {
57                 if (!fs_struct[i].mounted) continue;
58
59                 ffsUmountVol(fs_struct[i].sb);
60         }
61
62         return(ffsShutdown());
63 }
64
65 INT32 FsMountVol(struct super_block *sb)
66 {
67         INT32 err, drv;
68
69         sm_P(&z_sem);
70
71         for (drv = 0; drv < MAX_DRIVE; drv++) {
72                 if (!fs_struct[drv].mounted) break;
73         }
74
75         if (drv >= MAX_DRIVE) return(FFS_ERROR);
76
77         sm_P(&(fs_struct[drv].v_sem));
78
79         err = buf_init(sb);
80         if (!err) {
81                 err = ffsMountVol(sb, drv);
82         }
83
84         sm_V(&(fs_struct[drv].v_sem));
85
86         if (!err) {
87                 fs_struct[drv].mounted = TRUE;
88                 fs_struct[drv].sb = sb;
89         } else {
90                 buf_shutdown(sb);
91         }
92
93         sm_V(&z_sem);
94
95         return(err);
96 }
97
98 INT32 FsUmountVol(struct super_block *sb)
99 {
100         INT32 err;
101         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
102
103         sm_P(&z_sem);
104
105         sm_P(&(fs_struct[p_fs->drv].v_sem));
106
107         err = ffsUmountVol(sb);
108         buf_shutdown(sb);
109
110         sm_V(&(fs_struct[p_fs->drv].v_sem));
111
112         fs_struct[p_fs->drv].mounted = FALSE;
113         fs_struct[p_fs->drv].sb = NULL;
114
115         sm_V(&z_sem);
116
117         return(err);
118 }
119
120 INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info)
121 {
122         INT32 err;
123         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
124
125         if (info == NULL) return(FFS_ERROR);
126
127         sm_P(&(fs_struct[p_fs->drv].v_sem));
128
129         err = ffsGetVolInfo(sb, info);
130
131         sm_V(&(fs_struct[p_fs->drv].v_sem));
132
133         return(err);
134 }
135
136 INT32 FsSyncVol(struct super_block *sb, INT32 do_sync)
137 {
138         INT32 err;
139         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
140
141         sm_P(&(fs_struct[p_fs->drv].v_sem));
142
143         err = ffsSyncVol(sb, do_sync);
144
145         sm_V(&(fs_struct[p_fs->drv].v_sem));
146
147         return(err);
148 }
149
150 INT32 FsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid)
151 {
152         INT32 err;
153         struct super_block *sb = inode->i_sb;
154         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
155
156         if ((fid == NULL) || (path == NULL) || (STRLEN(path) == 0))
157                 return(FFS_ERROR);
158
159         sm_P(&(fs_struct[p_fs->drv].v_sem));
160
161         err = ffsLookupFile(inode, path, fid);
162
163         sm_V(&(fs_struct[p_fs->drv].v_sem));
164
165         return(err);
166 }
167
168 INT32 FsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid)
169 {
170         INT32 err;
171         struct super_block *sb = inode->i_sb;
172         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
173
174         if ((fid == NULL) || (path == NULL) || (STRLEN(path) == 0))
175                 return(FFS_ERROR);
176
177         sm_P(&(fs_struct[p_fs->drv].v_sem));
178
179         err = ffsCreateFile(inode, path, mode, fid);
180
181         sm_V(&(fs_struct[p_fs->drv].v_sem));
182
183         return(err);
184 }
185
186 INT32 FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount)
187 {
188         INT32 err;
189         struct super_block *sb = inode->i_sb;
190         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
191
192         if (fid == NULL) return(FFS_INVALIDFID);
193
194         if (buffer == NULL) return(FFS_ERROR);
195
196         sm_P(&(fs_struct[p_fs->drv].v_sem));
197
198         err = ffsReadFile(inode, fid, buffer, count, rcount);
199
200         sm_V(&(fs_struct[p_fs->drv].v_sem));
201
202         return(err);
203 }
204
205 INT32 FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount)
206 {
207         INT32 err;
208         struct super_block *sb = inode->i_sb;
209         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
210
211         if (fid == NULL) return(FFS_INVALIDFID);
212
213         if (buffer == NULL) return(FFS_ERROR);
214
215         sm_P(&(fs_struct[p_fs->drv].v_sem));
216
217         err = ffsWriteFile(inode, fid, buffer, count, wcount);
218
219         sm_V(&(fs_struct[p_fs->drv].v_sem));
220
221         return(err);
222 }
223
224 INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size)
225 {
226         INT32 err;
227         struct super_block *sb = inode->i_sb;
228         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
229
230         sm_P(&(fs_struct[p_fs->drv].v_sem));
231
232         PRINTK("FsTruncateFile entered (inode %p size %llu)\n", inode, new_size);
233
234         err = ffsTruncateFile(inode, old_size, new_size);
235
236         PRINTK("FsTruncateFile exitted (%d)\n", err);
237
238         sm_V(&(fs_struct[p_fs->drv].v_sem));
239
240         return(err);
241 }
242
243 INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry)
244 {
245         INT32 err;
246         struct super_block *sb = old_parent_inode->i_sb;
247         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
248
249         if (fid == NULL) return(FFS_INVALIDFID);
250
251         sm_P(&(fs_struct[p_fs->drv].v_sem));
252
253         err = ffsMoveFile(old_parent_inode, fid, new_parent_inode, new_dentry);
254
255         sm_V(&(fs_struct[p_fs->drv].v_sem));
256
257         return(err);
258 }
259
260 INT32 FsRemoveFile(struct inode *inode, FILE_ID_T *fid)
261 {
262         INT32 err;
263         struct super_block *sb = inode->i_sb;
264         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
265
266         if (fid == NULL) return(FFS_INVALIDFID);
267
268         sm_P(&(fs_struct[p_fs->drv].v_sem));
269
270         err = ffsRemoveFile(inode, fid);
271
272         sm_V(&(fs_struct[p_fs->drv].v_sem));
273
274         return(err);
275 }
276
277 INT32 FsSetAttr(struct inode *inode, UINT32 attr)
278 {
279         INT32 err;
280         struct super_block *sb = inode->i_sb;
281         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
282
283         sm_P(&(fs_struct[p_fs->drv].v_sem));
284
285         err = ffsSetAttr(inode, attr);
286
287         sm_V(&(fs_struct[p_fs->drv].v_sem));
288
289         return(err);
290 }
291
292 INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info)
293 {
294         INT32 err;
295         struct super_block *sb = inode->i_sb;
296         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
297
298         sm_P(&(fs_struct[p_fs->drv].v_sem));
299
300         err = ffsGetStat(inode, info);
301
302         sm_V(&(fs_struct[p_fs->drv].v_sem));
303
304         return(err);
305 }
306
307 INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info)
308 {
309         INT32 err;
310         struct super_block *sb = inode->i_sb;
311         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
312
313         sm_P(&(fs_struct[p_fs->drv].v_sem));
314
315         PRINTK("FsWriteStat entered (inode %p info %p\n", inode, info);
316
317         err = ffsSetStat(inode, info);
318
319         sm_V(&(fs_struct[p_fs->drv].v_sem));
320
321         PRINTK("FsWriteStat exited (%d)\n", err);
322
323         return(err);
324 }
325
326 INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu)
327 {
328         INT32 err;
329         struct super_block *sb = inode->i_sb;
330         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
331
332         if (clu == NULL) return(FFS_ERROR);
333
334         sm_P(&(fs_struct[p_fs->drv].v_sem));
335
336         err = ffsMapCluster(inode, clu_offset, clu);
337
338         sm_V(&(fs_struct[p_fs->drv].v_sem));
339
340         return(err);
341 }
342
343 INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid)
344 {
345         INT32 err;
346         struct super_block *sb = inode->i_sb;
347         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
348
349         if ((fid == NULL) || (path == NULL) || (STRLEN(path) == 0))
350                 return(FFS_ERROR);
351
352         sm_P(&(fs_struct[p_fs->drv].v_sem));
353
354         err = ffsCreateDir(inode, path, fid);
355
356         sm_V(&(fs_struct[p_fs->drv].v_sem));
357
358         return(err);
359 }
360
361 INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry)
362 {
363         INT32 err;
364         struct super_block *sb = inode->i_sb;
365         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
366
367         if (dir_entry == NULL) return(FFS_ERROR);
368
369         sm_P(&(fs_struct[p_fs->drv].v_sem));
370
371         err = ffsReadDir(inode, dir_entry);
372
373         sm_V(&(fs_struct[p_fs->drv].v_sem));
374
375         return(err);
376 }
377
378 INT32 FsRemoveDir(struct inode *inode, FILE_ID_T *fid)
379 {
380         INT32 err;
381         struct super_block *sb = inode->i_sb;
382         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
383
384         if (fid == NULL) return(FFS_INVALIDFID);
385
386         sm_P(&(fs_struct[p_fs->drv].v_sem));
387
388         err = ffsRemoveDir(inode, fid);
389
390         sm_V(&(fs_struct[p_fs->drv].v_sem));
391
392         return(err);
393 }
394
395 INT32 FsRemoveEntry(struct inode *inode, FILE_ID_T *fid)
396 {
397         INT32 err;
398         struct super_block *sb = inode->i_sb;
399         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
400
401         if (fid == NULL) return(FFS_INVALIDFID);
402
403         sm_P(&(fs_struct[p_fs->drv].v_sem));
404
405         err = ffsRemoveEntry(inode, fid);
406
407         sm_V(&(fs_struct[p_fs->drv].v_sem));
408
409         return(err);
410 }
411
412
413
414 EXPORT_SYMBOL(FsMountVol);
415 EXPORT_SYMBOL(FsUmountVol);
416 EXPORT_SYMBOL(FsGetVolInfo);
417 EXPORT_SYMBOL(FsSyncVol);
418 EXPORT_SYMBOL(FsLookupFile);
419 EXPORT_SYMBOL(FsCreateFile);
420 EXPORT_SYMBOL(FsReadFile);
421 EXPORT_SYMBOL(FsWriteFile);
422 EXPORT_SYMBOL(FsTruncateFile);
423 EXPORT_SYMBOL(FsMoveFile);
424 EXPORT_SYMBOL(FsRemoveFile);
425 EXPORT_SYMBOL(FsSetAttr);
426 EXPORT_SYMBOL(FsReadStat);
427 EXPORT_SYMBOL(FsWriteStat);
428 EXPORT_SYMBOL(FsMapCluster);
429 EXPORT_SYMBOL(FsCreateDir);
430 EXPORT_SYMBOL(FsReadDir);
431 EXPORT_SYMBOL(FsRemoveDir);
432 EXPORT_SYMBOL(FsRemoveEntry);
433
434 #if EXFAT_CONFIG_KERNEL_DEBUG
435 INT32 FsReleaseCache(struct super_block *sb)
436 {
437         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
438
439         sm_P(&(fs_struct[p_fs->drv].v_sem));
440
441         FAT_release_all(sb);
442         buf_release_all(sb);
443
444         sm_V(&(fs_struct[p_fs->drv].v_sem));
445
446         return 0;
447 }
448
449 EXPORT_SYMBOL(FsReleaseCache);
450 #endif
451
452 static int __init init_exfat_core(void)
453 {
454         int err;
455
456         printk(KERN_INFO "exFAT: Core Version %s\n", EXFAT_VERSION);
457
458         err = FsInit();
459         if (err) {
460                 if (err == FFS_MEMORYERR)
461                         return -ENOMEM;
462                 else
463                         return -EIO;
464         }
465
466         return 0;
467 }
468
469 static void __exit exit_exfat_core(void)
470 {
471         FsShutdown();
472 }
473
474 module_init(init_exfat_core);
475 module_exit(exit_exfat_core);
476
477 MODULE_LICENSE("GPL");