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/>.
21 #include <linux/buffer_head.h>
22 #include <linux/string.h>
23 #include <linux/types.h>
24 #include <linux/nls.h>
26 #include <linux/mutex.h>
27 #include <linux/ratelimit.h>
28 #include <linux/version.h>
29 #include <linux/kobject.h>
32 #ifdef CONFIG_SDFAT_DFR
39 #define SDFAT_ERRORS_CONT (1) /* ignore error and continue */
40 #define SDFAT_ERRORS_PANIC (2) /* panic on error */
41 #define SDFAT_ERRORS_RO (3) /* remount r/o on error */
44 * sdfat allocator flags
46 #define SDFAT_ALLOC_DELAY (1) /* Delayed allocation */
47 #define SDFAT_ALLOC_SMART (2) /* Smart allocation */
50 * sdfat allocator destination for smart allocation
52 #define ALLOC_NOWHERE (0)
53 #define ALLOC_COLD (1)
54 #define ALLOC_HOT (16)
55 #define ALLOC_COLD_ALIGNED (1)
56 #define ALLOC_COLD_PACKING (2)
57 #define ALLOC_COLD_SEQ (4)
60 * sdfat nls lossy flag
62 #define NLS_NAME_NO_LOSSY (0x00) /* no lossy */
63 #define NLS_NAME_LOSSY (0x01) /* just detected incorrect filename(s) */
64 #define NLS_NAME_OVERLEN (0x02) /* the length is over than its limit */
69 #define CLUSTER_16(x) ((u16)((x) & 0xFFFFU))
70 #define CLUSTER_32(x) ((u32)((x) & 0xFFFFFFFFU))
71 #define CLUS_EOF CLUSTER_32(~0)
72 #define CLUS_BAD (0xFFFFFFF7U)
75 #define IS_CLUS_EOF(x) ((x) == CLUS_EOF)
76 #define IS_CLUS_BAD(x) ((x) == CLUS_BAD)
77 #define IS_CLUS_FREE(x) ((x) == CLUS_FREE)
78 #define IS_LAST_SECT_IN_CLUS(fsi, sec) \
79 ((((sec) - (fsi)->data_start_sector + 1) \
80 & ((1 << (fsi)->sect_per_clus_bits) - 1)) == 0)
82 #define CLUS_TO_SECT(fsi, x) \
83 ((((unsigned long long)(x) - CLUS_BASE) << (fsi)->sect_per_clus_bits) + (fsi)->data_start_sector)
85 #define SECT_TO_CLUS(fsi, sec) \
86 ((u32)((((sec) - (fsi)->data_start_sector) >> (fsi)->sect_per_clus_bits) + CLUS_BASE))
88 /* variables defined at sdfat.c */
89 extern const char *FS_TYPE_STR
[];
99 * sdfat mount in-memory data
101 struct sdfat_mount_options
{
102 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
105 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) */
109 unsigned short fs_fmask
;
110 unsigned short fs_dmask
;
111 unsigned short allow_utime
; /* permission for setting the [am]time */
112 unsigned short codepage
; /* codepage for shortname conversions */
113 char *iocharset
; /* charset for filename input/display */
115 unsigned int pack_ratio
;
116 unsigned int sect_per_au
;
117 unsigned int misaligned_sect
;
118 } amap_opt
; /* AMAP-related options (see amap.c) */
121 unsigned char casesensitive
;
122 unsigned char adj_hidsect
;
123 unsigned char tz_utc
;
124 unsigned char improved_allocation
;
125 unsigned char defrag
;
126 unsigned char symlink
; /* support symlink operation */
127 unsigned char errors
; /* on error: continue, panic, remount-ro */
128 unsigned char discard
; /* flag on if -o dicard specified and device support discard() */
129 unsigned char fs_type
; /* fs_type that user specified */
130 unsigned short adj_req
; /* support aligned mpage write */
133 #define SDFAT_HASH_BITS 8
134 #define SDFAT_HASH_SIZE (1UL << SDFAT_HASH_BITS)
137 * SDFAT file system superblock in-memory data
139 struct sdfat_sb_info
{
140 FS_INFO_T fsi
; /* private filesystem info */
142 struct mutex s_vlock
; /* volume lock */
145 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
148 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
150 struct mutex s_lock
; /* superblock lock */
151 int write_super_queued
; /* Write_super work is pending? */
152 struct delayed_work write_super_work
; /* Work_queue data structrue for write_super() */
153 spinlock_t work_lock
; /* Lock for WQ */
155 struct super_block
*host_sb
; /* sb pointer */
156 struct sdfat_mount_options options
;
157 struct nls_table
*nls_disk
; /* Codepage used on disk */
158 struct nls_table
*nls_io
; /* Charset used for input and display */
159 struct ratelimit_state ratelimit
;
161 spinlock_t inode_hash_lock
;
162 struct hlist_head inode_hashtable
[SDFAT_HASH_SIZE
];
163 struct kobject sb_kobj
;
164 #ifdef CONFIG_SDFAT_DBG_IOCTL
166 #endif /* CONFIG_SDFAT_DBG_IOCTL */
168 #ifdef CONFIG_SDFAT_DFR
169 struct defrag_info dfr_info
;
170 struct completion dfr_complete
;
171 unsigned int *dfr_new_clus
;
173 unsigned int *dfr_page_wb
;
175 unsigned int dfr_hint_clus
;
176 unsigned int dfr_hint_idx
;
177 int dfr_reserved_clus
;
179 #ifdef CONFIG_SDFAT_DFR_DEBUG
181 #endif /* CONFIG_SDFAT_DFR_DEBUG */
183 #endif /* CONFIG_SDFAT_DFR */
185 #ifdef CONFIG_SDFAT_TRACE_IO
186 /* Statistics for allocator */
187 unsigned int stat_n_pages_written
; /* # of written pages in total */
188 unsigned int stat_n_pages_added
; /* # of added blocks in total */
189 unsigned int stat_n_bdev_pages_written
; /* # of written pages owned by bdev inode */
190 unsigned int stat_n_pages_confused
;
192 atomic_t stat_n_pages_queued
; /* # of pages in the request queue (approx.) */
196 * SDFAT file system inode in-memory data
198 struct sdfat_inode_info
{
201 /* NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access */
202 loff_t i_size_ondisk
; /* physically allocated size */
203 loff_t i_size_aligned
; /* block-aligned i_size (used in cont_write_begin) */
204 loff_t i_pos
; /* on-disk position of directory entry or 0 */
205 struct hlist_node i_hash_fat
; /* hash by i_location */
206 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
207 struct rw_semaphore truncate_lock
; /* protect bmap against truncate */
209 #ifdef CONFIG_SDFAT_DFR
210 struct defrag_info dfr_info
;
212 struct inode vfs_inode
;
215 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
216 typedef struct timespec64 sdfat_timespec_t
;
217 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) */
218 typedef struct timespec sdfat_timespec_t
;
222 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
224 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) */
226 * sb->s_flags. Note that these mirror the equivalent MS_* flags where
227 * represented in both.
229 #define SB_RDONLY 1 /* Mount read-only */
230 #define SB_NODIRATIME 2048 /* Do not update directory access times */
231 static inline bool sb_rdonly(const struct super_block
*sb
)
233 return sb
->s_flags
& MS_RDONLY
;
237 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
240 static inline sdfat_timespec_t
current_time(struct inode
*inode
)
242 return CURRENT_TIME_SEC
;
246 * FIXME : needs on-disk-slot in-memory data
249 /* static inline functons */
250 static inline const char *sdfat_get_vol_type_str(unsigned int type
)
254 else if (type
== FAT32
)
256 else if (type
== FAT16
)
258 else if (type
== FAT12
)
264 static inline struct sdfat_sb_info
*SDFAT_SB(struct super_block
*sb
)
266 return (struct sdfat_sb_info
*)sb
->s_fs_info
;
269 static inline struct sdfat_inode_info
*SDFAT_I(struct inode
*inode
)
271 return container_of(inode
, struct sdfat_inode_info
, vfs_inode
);
275 * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to
276 * save ATTR_RO instead of ->i_mode.
278 * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only
279 * bit, it's just used as flag for app.
281 static inline int sdfat_mode_can_hold_ro(struct inode
*inode
)
283 struct sdfat_sb_info
*sbi
= SDFAT_SB(inode
->i_sb
);
285 if (S_ISDIR(inode
->i_mode
))
288 if ((~sbi
->options
.fs_fmask
) & S_IWUGO
)
294 * FIXME : needs to check symlink option.
296 /* Convert attribute bits and a mask to the UNIX mode. */
297 static inline mode_t
sdfat_make_mode(struct sdfat_sb_info
*sbi
,
298 u32 attr
, mode_t mode
)
300 if ((attr
& ATTR_READONLY
) && !(attr
& ATTR_SUBDIR
))
303 if (attr
& ATTR_SUBDIR
)
304 return (mode
& ~sbi
->options
.fs_dmask
) | S_IFDIR
;
305 else if (attr
& ATTR_SYMLINK
)
306 return (mode
& ~sbi
->options
.fs_dmask
) | S_IFLNK
;
308 return (mode
& ~sbi
->options
.fs_fmask
) | S_IFREG
;
311 /* Return the FAT attribute byte for this inode */
312 static inline u32
sdfat_make_attr(struct inode
*inode
)
314 u32 attrs
= SDFAT_I(inode
)->fid
.attr
;
316 if (S_ISDIR(inode
->i_mode
))
317 attrs
|= ATTR_SUBDIR
;
318 if (sdfat_mode_can_hold_ro(inode
) && !(inode
->i_mode
& S_IWUGO
))
319 attrs
|= ATTR_READONLY
;
323 static inline void sdfat_save_attr(struct inode
*inode
, u32 attr
)
325 if (sdfat_mode_can_hold_ro(inode
))
326 SDFAT_I(inode
)->fid
.attr
= attr
& ATTR_RWMASK
;
328 SDFAT_I(inode
)->fid
.attr
= attr
& (ATTR_RWMASK
| ATTR_READONLY
);
331 /* sdfat/statistics.c */
332 /* bigdata function */
333 #ifdef CONFIG_SDFAT_STATISTICS
334 extern int sdfat_statistics_init(struct kset
*sdfat_kset
);
335 extern void sdfat_statistics_uninit(void);
336 extern void sdfat_statistics_set_mnt(FS_INFO_T
*fsi
);
337 extern void sdfat_statistics_set_mnt_ro(void);
338 extern void sdfat_statistics_set_mkdir(u8 flags
);
339 extern void sdfat_statistics_set_create(u8 flags
);
340 extern void sdfat_statistics_set_rw(u8 flags
, u32 clu_offset
, s32 create
);
341 extern void sdfat_statistics_set_trunc(u8 flags
, CHAIN_T
*clu
);
342 extern void sdfat_statistics_set_vol_size(struct super_block
*sb
);
344 static inline int sdfat_statistics_init(struct kset
*sdfat_kset
)
348 static inline void sdfat_statistics_uninit(void) {};
349 static inline void sdfat_statistics_set_mnt(FS_INFO_T
*fsi
) {};
350 static inline void sdfat_statistics_set_mnt_ro(void) {};
351 static inline void sdfat_statistics_set_mkdir(u8 flags
) {};
352 static inline void sdfat_statistics_set_create(u8 flags
) {};
353 static inline void sdfat_statistics_set_rw(u8 flags
, u32 clu_offset
, s32 create
) {};
354 static inline void sdfat_statistics_set_trunc(u8 flags
, CHAIN_T
*clu
) {};
355 static inline void sdfat_statistics_set_vol_size(struct super_block
*sb
) {};
359 /* NLS management function */
360 s32
nls_cmp_sfn(struct super_block
*sb
, u8
*a
, u8
*b
);
361 s32
nls_cmp_uniname(struct super_block
*sb
, u16
*a
, u16
*b
);
362 s32
nls_uni16s_to_sfn(struct super_block
*sb
, UNI_NAME_T
*p_uniname
, DOS_NAME_T
*p_dosname
, s32
*p_lossy
);
363 s32
nls_sfn_to_uni16s(struct super_block
*sb
, DOS_NAME_T
*p_dosname
, UNI_NAME_T
*p_uniname
);
364 s32
nls_uni16s_to_vfsname(struct super_block
*sb
, UNI_NAME_T
*uniname
, u8
*p_cstring
, s32 len
);
365 s32
nls_vfsname_to_uni16s(struct super_block
*sb
, const u8
*p_cstring
,
366 const s32 len
, UNI_NAME_T
*uniname
, s32
*p_lossy
);
369 #ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE
370 int sdfat_mpage_writepages(struct address_space
*mapping
,
371 struct writeback_control
*wbc
, get_block_t
*get_block
);
375 #ifdef CONFIG_SDFAT_VIRTUAL_XATTR
376 void setup_sdfat_xattr_handler(struct super_block
*sb
);
377 extern int sdfat_setxattr(struct dentry
*dentry
, const char *name
, const void *value
, size_t size
, int flags
);
378 extern ssize_t
sdfat_getxattr(struct dentry
*dentry
, const char *name
, void *value
, size_t size
);
379 extern ssize_t
sdfat_listxattr(struct dentry
*dentry
, char *list
, size_t size
);
380 extern int sdfat_removexattr(struct dentry
*dentry
, const char *name
);
382 static inline void setup_sdfat_xattr_handler(struct super_block
*sb
) {};
386 #ifdef CONFIG_SDFAT_UEVENT
387 extern int sdfat_uevent_init(struct kset
*sdfat_kset
);
388 extern void sdfat_uevent_uninit(void);
389 extern void sdfat_uevent_ro_remount(struct super_block
*sb
);
391 static inline int sdfat_uevent_init(struct kset
*sdfat_kset
)
395 static inline void sdfat_uevent_uninit(void) {};
396 static inline void sdfat_uevent_ro_remount(struct super_block
*sb
) {};
399 __sdfat_fs_error(struct super_block
*sb
, int report
, const char *fmt
, ...)
400 __printf(3, 4) __cold
;
401 #define sdfat_fs_error(sb, fmt, args...) \
402 __sdfat_fs_error(sb, 1, fmt, ## args)
403 #define sdfat_fs_error_ratelimit(sb, fmt, args...) \
404 __sdfat_fs_error(sb, __ratelimit(&SDFAT_SB(sb)->ratelimit), fmt, ## args)
406 __sdfat_msg(struct super_block
*sb
, const char *lv
, int st
, const char *fmt
, ...)
407 __printf(4, 5) __cold
;
408 #define sdfat_msg(sb, lv, fmt, args...) \
409 __sdfat_msg(sb, lv, 0, fmt, ## args)
410 #define sdfat_log_msg(sb, lv, fmt, args...) \
411 __sdfat_msg(sb, lv, 1, fmt, ## args)
412 extern void sdfat_log_version(void);
413 extern void sdfat_time_fat2unix(struct sdfat_sb_info
*sbi
, sdfat_timespec_t
*ts
,
415 extern void sdfat_time_unix2fat(struct sdfat_sb_info
*sbi
, sdfat_timespec_t
*ts
,
417 extern TIMESTAMP_T
*tm_now(struct inode
*inode
, TIMESTAMP_T
*tm
);
418 static inline TIMESTAMP_T
*tm_now_sb(struct super_block
*sb
, TIMESTAMP_T
*tm
)
420 struct inode fake_inode
;
422 fake_inode
.i_sb
= sb
;
423 return tm_now(&fake_inode
, tm
);
426 #ifdef CONFIG_SDFAT_DEBUG
428 #ifdef CONFIG_SDFAT_DBG_CAREFUL
429 void sdfat_debug_check_clusters(struct inode
*inode
);
431 #define sdfat_debug_check_clusters(inode)
432 #endif /* CONFIG_SDFAT_DBG_CAREFUL */
434 #ifdef CONFIG_SDFAT_DBG_BUGON
435 #define sdfat_debug_bug_on(expr) BUG_ON(expr)
437 #define sdfat_debug_bug_on(expr)
440 #ifdef CONFIG_SDFAT_DBG_WARNON
441 #define sdfat_debug_warn_on(expr) WARN_ON(expr)
443 #define sdfat_debug_warn_on(expr)
446 #else /* CONFIG_SDFAT_DEBUG */
448 #define sdfat_debug_check_clusters(inode)
449 #define sdfat_debug_bug_on(expr)
451 #endif /* CONFIG_SDFAT_DEBUG */
453 #ifdef CONFIG_SDFAT_TRACE_ELAPSED_TIME
454 u32
sdfat_time_current_usec(struct timeval
*tv
);
455 extern struct timeval __t1
;
456 extern struct timeval __t2
;
458 #define TIME_GET(tv) sdfat_time_current_usec(tv)
459 #define TIME_START(s) sdfat_time_current_usec(s)
460 #define TIME_END(e) sdfat_time_current_usec(e)
461 #define TIME_ELAPSED(s, e) ((u32)(((e)->tv_sec - (s)->tv_sec) * 1000000 + \
462 ((e)->tv_usec - (s)->tv_usec)))
463 #define PRINT_TIME(n) pr_info("[SDFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1))
464 #else /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */
465 #define TIME_GET(tv) (0)
466 #define TIME_START(s)
468 #define TIME_ELAPSED(s, e) (0)
469 #define PRINT_TIME(n)
470 #endif /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */
472 #define SDFAT_MSG_LV_NONE (0x00000000)
473 #define SDFAT_MSG_LV_ERR (0x00000001)
474 #define SDFAT_MSG_LV_INFO (0x00000002)
475 #define SDFAT_MSG_LV_DBG (0x00000003)
476 #define SDFAT_MSG_LV_MORE (0x00000004)
477 #define SDFAT_MSG_LV_TRACE (0x00000005)
478 #define SDFAT_MSG_LV_ALL (0x00000006)
480 #define SDFAT_MSG_LEVEL SDFAT_MSG_LV_INFO
482 #define SDFAT_TAG_NAME "SDFAT"
486 extern void __sdfat_dmsg(int level
, const char *fmt
, ...) __printf(2, 3) __cold
;
488 #define SDFAT_EMSG_T(level, ...) \
489 __sdfat_dmsg(level, KERN_ERR "[" SDFAT_TAG_NAME "] [" _S(__FILE__) "(" _S(__LINE__) ")] " __VA_ARGS__)
490 #define SDFAT_DMSG_T(level, ...) \
491 __sdfat_dmsg(level, KERN_INFO "[" SDFAT_TAG_NAME "] " __VA_ARGS__)
493 #define SDFAT_EMSG(...) SDFAT_EMSG_T(SDFAT_MSG_LV_ERR, __VA_ARGS__)
494 #define SDFAT_IMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_INFO, __VA_ARGS__)
495 #define SDFAT_DMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_DBG, __VA_ARGS__)
496 #define SDFAT_MMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_MORE, __VA_ARGS__)
497 #define SDFAT_TMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_TRACE, __VA_ARGS__)
505 #define EMSG_VAR(exp)
506 #define IMSG_VAR(exp)
507 #define DMSG_VAR(exp)
508 #define MMSG_VAR(exp)
509 #define TMSG_VAR(exp)
511 #ifdef CONFIG_SDFAT_DBG_MSG
514 #if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_ERR)
517 #define EMSG(...) SDFAT_EMSG(__VA_ARGS__)
518 #define EMSG_VAR(exp) exp
521 #if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_INFO)
524 #define IMSG(...) SDFAT_IMSG(__VA_ARGS__)
525 #define IMSG_VAR(exp) exp
528 #if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_DBG)
531 #define DMSG(...) SDFAT_DMSG(__VA_ARGS__)
532 #define DMSG_VAR(exp) exp
535 #if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_MORE)
538 #define MMSG(...) SDFAT_MMSG(__VA_ARGS__)
539 #define MMSG_VAR(exp) exp
542 /* should replace with trace function */
543 #if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_TRACE)
546 #define TMSG(...) SDFAT_TMSG(__VA_ARGS__)
547 #define TMSG_VAR(exp) exp
550 #endif /* CONFIG_SDFAT_DBG_MSG */
553 #define ASSERT(expr) { \
555 pr_err("Assertion failed! %s\n", #expr); \
560 #endif /* !_SDFAT_H */