fs: sdfat: Update to version 2.3.0
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / fs / sdfat / sdfat.h
CommitLineData
45e430a1
PK
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#ifndef _SDFAT_H
19#define _SDFAT_H
20
21#include <linux/buffer_head.h>
22#include <linux/string.h>
23#include <linux/types.h>
24#include <linux/nls.h>
25#include <linux/fs.h>
26#include <linux/mutex.h>
27#include <linux/ratelimit.h>
28#include <linux/version.h>
29#include <linux/kobject.h>
30#include "api.h"
31
32#ifdef CONFIG_SDFAT_DFR
33#include "dfr.h"
34#endif
35
36/*
37 * sdfat error flags
38 */
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 */
42
43/*
44 * sdfat allocator flags
45 */
46#define SDFAT_ALLOC_DELAY (1) /* Delayed allocation */
47#define SDFAT_ALLOC_SMART (2) /* Smart allocation */
48
49/*
50 * sdfat allocator destination for smart allocation
51 */
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)
58
59/*
60 * sdfat nls lossy flag
61 */
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 */
65
66/*
67 * sdfat common MACRO
68 */
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)
73#define CLUS_FREE (0)
74#define CLUS_BASE (2)
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)
81
82#define CLUS_TO_SECT(fsi, x) \
e9692b33 83 ((((unsigned long long)(x) - CLUS_BASE) << (fsi)->sect_per_clus_bits) + (fsi)->data_start_sector)
45e430a1
PK
84
85#define SECT_TO_CLUS(fsi, sec) \
e9692b33 86 ((u32)((((sec) - (fsi)->data_start_sector) >> (fsi)->sect_per_clus_bits) + CLUS_BASE))
45e430a1
PK
87
88/* variables defined at sdfat.c */
89extern const char *FS_TYPE_STR[];
90
91enum {
92 FS_TYPE_AUTO,
93 FS_TYPE_EXFAT,
94 FS_TYPE_VFAT,
95 FS_TYPE_MAX
96};
97
98/*
99 * sdfat mount in-memory data
100 */
101struct sdfat_mount_options {
102#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
103 kuid_t fs_uid;
104 kgid_t fs_gid;
105#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) */
106 uid_t fs_uid;
107 gid_t fs_gid;
108#endif
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 */
114 struct {
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) */
119
120 unsigned char utf8;
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 */
cd50e37c 130 unsigned short adj_req; /* support aligned mpage write */
45e430a1
PK
131};
132
133#define SDFAT_HASH_BITS 8
134#define SDFAT_HASH_SIZE (1UL << SDFAT_HASH_BITS)
135
136/*
137 * SDFAT file system superblock in-memory data
138 */
139struct sdfat_sb_info {
140 FS_INFO_T fsi; /* private filesystem info */
141
142 struct mutex s_vlock; /* volume lock */
143 int use_vmalloc;
144
145#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
146 int s_dirt;
147 struct mutex s_lock; /* superblock lock */
148 int write_super_queued; /* Write_super work is pending? */
149 struct delayed_work write_super_work; /* Work_queue data structrue for write_super() */
150 spinlock_t work_lock; /* Lock for WQ */
151#endif
152 struct super_block *host_sb; /* sb pointer */
153 struct sdfat_mount_options options;
154 struct nls_table *nls_disk; /* Codepage used on disk */
155 struct nls_table *nls_io; /* Charset used for input and display */
156 struct ratelimit_state ratelimit;
157
158 spinlock_t inode_hash_lock;
159 struct hlist_head inode_hashtable[SDFAT_HASH_SIZE];
160 struct kobject sb_kobj;
161#ifdef CONFIG_SDFAT_DBG_IOCTL
162 long debug_flags;
163#endif /* CONFIG_SDFAT_DBG_IOCTL */
164
165#ifdef CONFIG_SDFAT_DFR
166 struct defrag_info dfr_info;
167 struct completion dfr_complete;
168 unsigned int *dfr_new_clus;
169 int dfr_new_idx;
170 unsigned int *dfr_page_wb;
171 void **dfr_pagep;
172 unsigned int dfr_hint_clus;
173 unsigned int dfr_hint_idx;
174 int dfr_reserved_clus;
175
176#ifdef CONFIG_SDFAT_DFR_DEBUG
177 int dfr_spo_flag;
178#endif /* CONFIG_SDFAT_DFR_DEBUG */
179
180#endif /* CONFIG_SDFAT_DFR */
181
182#ifdef CONFIG_SDFAT_TRACE_IO
183 /* Statistics for allocator */
184 unsigned int stat_n_pages_written; /* # of written pages in total */
185 unsigned int stat_n_pages_added; /* # of added blocks in total */
186 unsigned int stat_n_bdev_pages_written; /* # of written pages owned by bdev inode */
187 unsigned int stat_n_pages_confused;
188#endif
189 atomic_t stat_n_pages_queued; /* # of pages in the request queue (approx.) */
190};
191
192/*
193 * SDFAT file system inode in-memory data
194 */
195struct sdfat_inode_info {
196 FILE_ID_T fid;
197 char *target;
198 /* NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access */
199 loff_t i_size_ondisk; /* physically allocated size */
200 loff_t i_size_aligned; /* block-aligned i_size (used in cont_write_begin) */
201 loff_t i_pos; /* on-disk position of directory entry or 0 */
202 struct hlist_node i_hash_fat; /* hash by i_location */
203#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
204 struct rw_semaphore truncate_lock; /* protect bmap against truncate */
205#endif
206#ifdef CONFIG_SDFAT_DFR
207 struct defrag_info dfr_info;
208#endif
209 struct inode vfs_inode;
210};
211
ed48c1cb
KH
212#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
213typedef struct timespec64 sdfat_timespec_t;
214#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) */
215typedef struct timespec sdfat_timespec_t;
216#endif
217
45e430a1
PK
218/*
219 * FIXME : needs on-disk-slot in-memory data
220 */
221
222/* static inline functons */
223static inline const char *sdfat_get_vol_type_str(unsigned int type)
224{
225 if (type == EXFAT)
226 return "exfat";
227 else if (type == FAT32)
228 return "vfat:32";
229 else if (type == FAT16)
230 return "vfat:16";
231 else if (type == FAT12)
232 return "vfat:12";
233
234 return "unknown";
235}
236
237static inline struct sdfat_sb_info *SDFAT_SB(struct super_block *sb)
238{
239 return (struct sdfat_sb_info *)sb->s_fs_info;
240}
241
242static inline struct sdfat_inode_info *SDFAT_I(struct inode *inode)
243{
244 return container_of(inode, struct sdfat_inode_info, vfs_inode);
245}
246
247/*
248 * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to
249 * save ATTR_RO instead of ->i_mode.
250 *
251 * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only
252 * bit, it's just used as flag for app.
253 */
254static inline int sdfat_mode_can_hold_ro(struct inode *inode)
255{
256 struct sdfat_sb_info *sbi = SDFAT_SB(inode->i_sb);
257
258 if (S_ISDIR(inode->i_mode))
259 return 0;
260
261 if ((~sbi->options.fs_fmask) & S_IWUGO)
262 return 1;
263 return 0;
264}
265
266/*
267 * FIXME : needs to check symlink option.
268 */
269/* Convert attribute bits and a mask to the UNIX mode. */
270static inline mode_t sdfat_make_mode(struct sdfat_sb_info *sbi,
271 u32 attr, mode_t mode)
272{
273 if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR))
274 mode &= ~S_IWUGO;
275
276 if (attr & ATTR_SUBDIR)
277 return (mode & ~sbi->options.fs_dmask) | S_IFDIR;
278 else if (attr & ATTR_SYMLINK)
279 return (mode & ~sbi->options.fs_dmask) | S_IFLNK;
280 else
281 return (mode & ~sbi->options.fs_fmask) | S_IFREG;
282}
283
284/* Return the FAT attribute byte for this inode */
285static inline u32 sdfat_make_attr(struct inode *inode)
286{
287 u32 attrs = SDFAT_I(inode)->fid.attr;
288
289 if (S_ISDIR(inode->i_mode))
290 attrs |= ATTR_SUBDIR;
291 if (sdfat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO))
292 attrs |= ATTR_READONLY;
293 return attrs;
294}
295
296static inline void sdfat_save_attr(struct inode *inode, u32 attr)
297{
298 if (sdfat_mode_can_hold_ro(inode))
299 SDFAT_I(inode)->fid.attr = attr & ATTR_RWMASK;
300 else
301 SDFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY);
302}
303
304/* sdfat/statistics.c */
305/* bigdata function */
306#ifdef CONFIG_SDFAT_STATISTICS
307extern int sdfat_statistics_init(struct kset *sdfat_kset);
308extern void sdfat_statistics_uninit(void);
309extern void sdfat_statistics_set_mnt(FS_INFO_T *fsi);
cd50e37c 310extern void sdfat_statistics_set_mnt_ro(void);
45e430a1
PK
311extern void sdfat_statistics_set_mkdir(u8 flags);
312extern void sdfat_statistics_set_create(u8 flags);
313extern void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create);
314extern void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu);
315extern void sdfat_statistics_set_vol_size(struct super_block *sb);
316#else
317static inline int sdfat_statistics_init(struct kset *sdfat_kset)
318{
319 return 0;
320}
321static inline void sdfat_statistics_uninit(void) {};
322static inline void sdfat_statistics_set_mnt(FS_INFO_T *fsi) {};
cd50e37c 323static inline void sdfat_statistics_set_mnt_ro(void) {};
45e430a1
PK
324static inline void sdfat_statistics_set_mkdir(u8 flags) {};
325static inline void sdfat_statistics_set_create(u8 flags) {};
326static inline void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create) {};
327static inline void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu) {};
328static inline void sdfat_statistics_set_vol_size(struct super_block *sb) {};
329#endif
330
331/* sdfat/nls.c */
332/* NLS management function */
333s32 nls_cmp_sfn(struct super_block *sb, u8 *a, u8 *b);
334s32 nls_cmp_uniname(struct super_block *sb, u16 *a, u16 *b);
335s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname, s32 *p_lossy);
336s32 nls_sfn_to_uni16s(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname);
337s32 nls_uni16s_to_vfsname(struct super_block *sb, UNI_NAME_T *uniname, u8 *p_cstring, s32 len);
338s32 nls_vfsname_to_uni16s(struct super_block *sb, const u8 *p_cstring,
339 const s32 len, UNI_NAME_T *uniname, s32 *p_lossy);
340
341/* sdfat/mpage.c */
342#ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE
343int sdfat_mpage_writepages(struct address_space *mapping,
344 struct writeback_control *wbc, get_block_t *get_block);
345#endif
346
347/* sdfat/xattr.c */
348#ifdef CONFIG_SDFAT_VIRTUAL_XATTR
349void setup_sdfat_xattr_handler(struct super_block *sb);
350extern int sdfat_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
351extern ssize_t sdfat_getxattr(struct dentry *dentry, const char *name, void *value, size_t size);
352extern ssize_t sdfat_listxattr(struct dentry *dentry, char *list, size_t size);
353extern int sdfat_removexattr(struct dentry *dentry, const char *name);
354#else
355static inline void setup_sdfat_xattr_handler(struct super_block *sb) {};
356#endif
357
358/* sdfat/misc.c */
ed48c1cb
KH
359#ifdef CONFIG_SDFAT_UEVENT
360extern int sdfat_uevent_init(struct kset *sdfat_kset);
361extern void sdfat_uevent_uninit(void);
362extern void sdfat_uevent_ro_remount(struct super_block *sb);
363#else
364static inline int sdfat_uevent_init(struct kset *sdfat_kset)
365{
366 return 0;
367}
368static inline void sdfat_uevent_uninit(void) {};
369static inline void sdfat_uevent_ro_remount(struct super_block *sb) {};
370#endif
45e430a1
PK
371extern void
372__sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
373 __printf(3, 4) __cold;
374#define sdfat_fs_error(sb, fmt, args...) \
375 __sdfat_fs_error(sb, 1, fmt, ## args)
376#define sdfat_fs_error_ratelimit(sb, fmt, args...) \
377 __sdfat_fs_error(sb, __ratelimit(&SDFAT_SB(sb)->ratelimit), fmt, ## args)
378extern void
379__sdfat_msg(struct super_block *sb, const char *lv, int st, const char *fmt, ...)
380 __printf(4, 5) __cold;
381#define sdfat_msg(sb, lv, fmt, args...) \
382 __sdfat_msg(sb, lv, 0, fmt, ## args)
383#define sdfat_log_msg(sb, lv, fmt, args...) \
384 __sdfat_msg(sb, lv, 1, fmt, ## args)
385extern void sdfat_log_version(void);
ed48c1cb 386extern void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, sdfat_timespec_t *ts,
45e430a1 387 DATE_TIME_T *tp);
ed48c1cb 388extern void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, sdfat_timespec_t *ts,
45e430a1
PK
389 DATE_TIME_T *tp);
390extern TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tm);
391
392#ifdef CONFIG_SDFAT_DEBUG
393
394#ifdef CONFIG_SDFAT_DBG_CAREFUL
395void sdfat_debug_check_clusters(struct inode *inode);
396#else
397#define sdfat_debug_check_clusters(inode)
398#endif /* CONFIG_SDFAT_DBG_CAREFUL */
399
400#ifdef CONFIG_SDFAT_DBG_BUGON
401#define sdfat_debug_bug_on(expr) BUG_ON(expr)
402#else
403#define sdfat_debug_bug_on(expr)
404#endif
405
406#ifdef CONFIG_SDFAT_DBG_WARNON
407#define sdfat_debug_warn_on(expr) WARN_ON(expr)
408#else
409#define sdfat_debug_warn_on(expr)
410#endif
411
412#else /* CONFIG_SDFAT_DEBUG */
413
414#define sdfat_debug_check_clusters(inode)
415#define sdfat_debug_bug_on(expr)
3c36ffa4 416#define sdfat_debug_warn_on(expr)
45e430a1
PK
417
418#endif /* CONFIG_SDFAT_DEBUG */
419
420#ifdef CONFIG_SDFAT_TRACE_ELAPSED_TIME
421u32 sdfat_time_current_usec(struct timeval *tv);
422extern struct timeval __t1;
423extern struct timeval __t2;
424
425#define TIME_GET(tv) sdfat_time_current_usec(tv)
426#define TIME_START(s) sdfat_time_current_usec(s)
427#define TIME_END(e) sdfat_time_current_usec(e)
428#define TIME_ELAPSED(s, e) ((u32)(((e)->tv_sec - (s)->tv_sec) * 1000000 + \
429 ((e)->tv_usec - (s)->tv_usec)))
430#define PRINT_TIME(n) pr_info("[SDFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1))
431#else /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */
432#define TIME_GET(tv) (0)
433#define TIME_START(s)
434#define TIME_END(e)
435#define TIME_ELAPSED(s, e) (0)
436#define PRINT_TIME(n)
437#endif /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */
438
439#define SDFAT_MSG_LV_NONE (0x00000000)
440#define SDFAT_MSG_LV_ERR (0x00000001)
441#define SDFAT_MSG_LV_INFO (0x00000002)
442#define SDFAT_MSG_LV_DBG (0x00000003)
443#define SDFAT_MSG_LV_MORE (0x00000004)
444#define SDFAT_MSG_LV_TRACE (0x00000005)
445#define SDFAT_MSG_LV_ALL (0x00000006)
446
447#define SDFAT_MSG_LEVEL SDFAT_MSG_LV_INFO
448
449#define SDFAT_TAG_NAME "SDFAT"
450#define __S(x) #x
451#define _S(x) __S(x)
452
453extern void __sdfat_dmsg(int level, const char *fmt, ...) __printf(2, 3) __cold;
454
455#define SDFAT_EMSG_T(level, ...) \
456 __sdfat_dmsg(level, KERN_ERR "[" SDFAT_TAG_NAME "] [" _S(__FILE__) "(" _S(__LINE__) ")] " __VA_ARGS__)
457#define SDFAT_DMSG_T(level, ...) \
458 __sdfat_dmsg(level, KERN_INFO "[" SDFAT_TAG_NAME "] " __VA_ARGS__)
459
460#define SDFAT_EMSG(...) SDFAT_EMSG_T(SDFAT_MSG_LV_ERR, __VA_ARGS__)
461#define SDFAT_IMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_INFO, __VA_ARGS__)
462#define SDFAT_DMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_DBG, __VA_ARGS__)
463#define SDFAT_MMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_MORE, __VA_ARGS__)
464#define SDFAT_TMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_TRACE, __VA_ARGS__)
465
466#define EMSG(...)
467#define IMSG(...)
468#define DMSG(...)
469#define MMSG(...)
470#define TMSG(...)
471
472#define EMSG_VAR(exp)
473#define IMSG_VAR(exp)
474#define DMSG_VAR(exp)
475#define MMSG_VAR(exp)
476#define TMSG_VAR(exp)
477
478#ifdef CONFIG_SDFAT_DBG_MSG
479
480
481#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_ERR)
482#undef EMSG
483#undef EMSG_VAR
484#define EMSG(...) SDFAT_EMSG(__VA_ARGS__)
485#define EMSG_VAR(exp) exp
486#endif
487
488#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_INFO)
489#undef IMSG
490#undef IMSG_VAR
491#define IMSG(...) SDFAT_IMSG(__VA_ARGS__)
492#define IMSG_VAR(exp) exp
493#endif
494
495#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_DBG)
496#undef DMSG
497#undef DMSG_VAR
498#define DMSG(...) SDFAT_DMSG(__VA_ARGS__)
499#define DMSG_VAR(exp) exp
500#endif
501
502#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_MORE)
503#undef MMSG
504#undef MMSG_VAR
505#define MMSG(...) SDFAT_MMSG(__VA_ARGS__)
506#define MMSG_VAR(exp) exp
507#endif
508
509/* should replace with trace function */
510#if (SDFAT_MSG_LEVEL >= SDFAT_MSG_LV_TRACE)
511#undef TMSG
512#undef TMSG_VAR
513#define TMSG(...) SDFAT_TMSG(__VA_ARGS__)
514#define TMSG_VAR(exp) exp
515#endif
516
517#endif /* CONFIG_SDFAT_DBG_MSG */
518
519
520#define ASSERT(expr) { \
521 if (!(expr)) { \
522 pr_err("Assertion failed! %s\n", #expr); \
523 BUG_ON(1); \
524 } \
525}
526
527#endif /* !_SDFAT_H */
528