Blame view

fs/exfat/super.c 20.1 KB
719c1e182   Namjae Jeon   exfat: add super ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  // SPDX-License-Identifier: GPL-2.0-or-later
  /*
   *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
   */
  
  #include <linux/fs_context.h>
  #include <linux/fs_parser.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/time.h>
  #include <linux/mount.h>
  #include <linux/cred.h>
  #include <linux/statfs.h>
  #include <linux/seq_file.h>
  #include <linux/blkdev.h>
  #include <linux/fs_struct.h>
  #include <linux/iversion.h>
  #include <linux/nls.h>
  #include <linux/buffer_head.h>
  
  #include "exfat_raw.h"
  #include "exfat_fs.h"
  
  static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET;
  static struct kmem_cache *exfat_inode_cachep;
  
  static void exfat_free_iocharset(struct exfat_sb_info *sbi)
  {
  	if (sbi->options.iocharset != exfat_default_iocharset)
  		kfree(sbi->options.iocharset);
  }
  
  static void exfat_delayed_free(struct rcu_head *p)
  {
  	struct exfat_sb_info *sbi = container_of(p, struct exfat_sb_info, rcu);
  
  	unload_nls(sbi->nls_io);
  	exfat_free_iocharset(sbi);
  	exfat_free_upcase_table(sbi);
  	kfree(sbi);
  }
  
  static void exfat_put_super(struct super_block *sb)
  {
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  
  	mutex_lock(&sbi->s_lock);
719c1e182   Namjae Jeon   exfat: add super ...
48
  	exfat_free_bitmap(sbi);
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
49
  	brelse(sbi->boot_bh);
719c1e182   Namjae Jeon   exfat: add super ...
50
51
52
53
54
55
56
57
58
  	mutex_unlock(&sbi->s_lock);
  
  	call_rcu(&sbi->rcu, exfat_delayed_free);
  }
  
  static int exfat_sync_fs(struct super_block *sb, int wait)
  {
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  	int err = 0;
2c7f8937e   Tetsuhiro Kohada   exfat: remove EXF...
59
60
  	if (!wait)
  		return 0;
719c1e182   Namjae Jeon   exfat: add super ...
61
62
  	/* If there are some dirty buffers in the bdev inode */
  	mutex_lock(&sbi->s_lock);
2c7f8937e   Tetsuhiro Kohada   exfat: remove EXF...
63
  	sync_blockdev(sb->s_bdev);
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
64
  	if (exfat_clear_volume_dirty(sb))
2c7f8937e   Tetsuhiro Kohada   exfat: remove EXF...
65
  		err = -EIO;
719c1e182   Namjae Jeon   exfat: add super ...
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  	mutex_unlock(&sbi->s_lock);
  	return err;
  }
  
  static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
  {
  	struct super_block *sb = dentry->d_sb;
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  	unsigned long long id = huge_encode_dev(sb->s_bdev->bd_dev);
  
  	if (sbi->used_clusters == EXFAT_CLUSTERS_UNTRACKED) {
  		mutex_lock(&sbi->s_lock);
  		if (exfat_count_used_clusters(sb, &sbi->used_clusters)) {
  			mutex_unlock(&sbi->s_lock);
  			return -EIO;
  		}
  		mutex_unlock(&sbi->s_lock);
  	}
  
  	buf->f_type = sb->s_magic;
  	buf->f_bsize = sbi->cluster_size;
  	buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */
  	buf->f_bfree = buf->f_blocks - sbi->used_clusters;
  	buf->f_bavail = buf->f_bfree;
6d1349c76   Al Viro   [PATCH] reduce bo...
90
  	buf->f_fsid = u64_to_fsid(id);
719c1e182   Namjae Jeon   exfat: add super ...
91
92
93
94
  	/* Unicode utf16 255 characters */
  	buf->f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE;
  	return 0;
  }
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
95
  static int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flags)
719c1e182   Namjae Jeon   exfat: add super ...
96
97
  {
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
98
  	struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data;
cdc06129a   Jason Yan   exfat: remove the...
99
  	bool sync;
719c1e182   Namjae Jeon   exfat: add super ...
100

7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
101
102
  	/* retain persistent-flags */
  	new_flags |= sbi->vol_flags_persistent;
719c1e182   Namjae Jeon   exfat: add super ...
103
  	/* flags are not changed */
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
104
  	if (sbi->vol_flags == new_flags)
719c1e182   Namjae Jeon   exfat: add super ...
105
  		return 0;
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
106
  	sbi->vol_flags = new_flags;
719c1e182   Namjae Jeon   exfat: add super ...
107
108
109
110
111
112
  
  	/* skip updating volume dirty flag,
  	 * if this volume has been mounted with read-only
  	 */
  	if (sb_rdonly(sb))
  		return 0;
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
113
  	p_boot->vol_flags = cpu_to_le16(new_flags);
719c1e182   Namjae Jeon   exfat: add super ...
114

7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
115
  	if ((new_flags & VOLUME_DIRTY) && !buffer_dirty(sbi->boot_bh))
719c1e182   Namjae Jeon   exfat: add super ...
116
117
118
  		sync = true;
  	else
  		sync = false;
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
119
120
  	set_buffer_uptodate(sbi->boot_bh);
  	mark_buffer_dirty(sbi->boot_bh);
719c1e182   Namjae Jeon   exfat: add super ...
121
122
  
  	if (sync)
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
123
  		sync_dirty_buffer(sbi->boot_bh);
719c1e182   Namjae Jeon   exfat: add super ...
124
125
  	return 0;
  }
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
126
127
128
129
130
131
132
133
134
135
136
137
138
  int exfat_set_volume_dirty(struct super_block *sb)
  {
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  
  	return exfat_set_vol_flags(sb, sbi->vol_flags | VOLUME_DIRTY);
  }
  
  int exfat_clear_volume_dirty(struct super_block *sb)
  {
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  
  	return exfat_set_vol_flags(sb, sbi->vol_flags & ~VOLUME_DIRTY);
  }
719c1e182   Namjae Jeon   exfat: add super ...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  static int exfat_show_options(struct seq_file *m, struct dentry *root)
  {
  	struct super_block *sb = root->d_sb;
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  	struct exfat_mount_options *opts = &sbi->options;
  
  	/* Show partition info */
  	if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID))
  		seq_printf(m, ",uid=%u",
  				from_kuid_munged(&init_user_ns, opts->fs_uid));
  	if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID))
  		seq_printf(m, ",gid=%u",
  				from_kgid_munged(&init_user_ns, opts->fs_gid));
  	seq_printf(m, ",fmask=%04o,dmask=%04o", opts->fs_fmask, opts->fs_dmask);
  	if (opts->allow_utime)
  		seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
  	if (opts->utf8)
  		seq_puts(m, ",iocharset=utf8");
  	else if (sbi->nls_io)
  		seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
719c1e182   Namjae Jeon   exfat: add super ...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  	if (opts->errors == EXFAT_ERRORS_CONT)
  		seq_puts(m, ",errors=continue");
  	else if (opts->errors == EXFAT_ERRORS_PANIC)
  		seq_puts(m, ",errors=panic");
  	else
  		seq_puts(m, ",errors=remount-ro");
  	if (opts->discard)
  		seq_puts(m, ",discard");
  	if (opts->time_offset)
  		seq_printf(m, ",time_offset=%d", opts->time_offset);
  	return 0;
  }
  
  static struct inode *exfat_alloc_inode(struct super_block *sb)
  {
  	struct exfat_inode_info *ei;
  
  	ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS);
  	if (!ei)
  		return NULL;
  
  	init_rwsem(&ei->truncate_lock);
  	return &ei->vfs_inode;
  }
  
  static void exfat_free_inode(struct inode *inode)
  {
  	kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode));
  }
  
  static const struct super_operations exfat_sops = {
  	.alloc_inode	= exfat_alloc_inode,
  	.free_inode	= exfat_free_inode,
  	.write_inode	= exfat_write_inode,
  	.evict_inode	= exfat_evict_inode,
  	.put_super	= exfat_put_super,
  	.sync_fs	= exfat_sync_fs,
  	.statfs		= exfat_statfs,
  	.show_options	= exfat_show_options,
  };
  
  enum {
  	Opt_uid,
  	Opt_gid,
  	Opt_umask,
  	Opt_dmask,
  	Opt_fmask,
  	Opt_allow_utime,
  	Opt_charset,
  	Opt_errors,
  	Opt_discard,
  	Opt_time_offset,
907fa8932   Namjae Jeon   exfat: add the du...
211
212
213
214
215
216
  
  	/* Deprecated options */
  	Opt_utf8,
  	Opt_debug,
  	Opt_namecase,
  	Opt_codepage,
719c1e182   Namjae Jeon   exfat: add super ...
217
  };
9acd0d538   Valdis Kletnieks   exfat: update fil...
218
219
220
221
222
223
224
225
  static const struct constant_table exfat_param_enums[] = {
  	{ "continue",		EXFAT_ERRORS_CONT },
  	{ "panic",		EXFAT_ERRORS_PANIC },
  	{ "remount-ro",		EXFAT_ERRORS_RO },
  	{}
  };
  
  static const struct fs_parameter_spec exfat_parameters[] = {
719c1e182   Namjae Jeon   exfat: add super ...
226
227
228
229
230
231
232
  	fsparam_u32("uid",			Opt_uid),
  	fsparam_u32("gid",			Opt_gid),
  	fsparam_u32oct("umask",			Opt_umask),
  	fsparam_u32oct("dmask",			Opt_dmask),
  	fsparam_u32oct("fmask",			Opt_fmask),
  	fsparam_u32oct("allow_utime",		Opt_allow_utime),
  	fsparam_string("iocharset",		Opt_charset),
9acd0d538   Valdis Kletnieks   exfat: update fil...
233
  	fsparam_enum("errors",			Opt_errors, exfat_param_enums),
719c1e182   Namjae Jeon   exfat: add super ...
234
235
  	fsparam_flag("discard",			Opt_discard),
  	fsparam_s32("time_offset",		Opt_time_offset),
907fa8932   Namjae Jeon   exfat: add the du...
236
237
238
239
240
241
242
243
  	__fsparam(NULL, "utf8",			Opt_utf8, fs_param_deprecated,
  		  NULL),
  	__fsparam(NULL, "debug",		Opt_debug, fs_param_deprecated,
  		  NULL),
  	__fsparam(fs_param_is_u32, "namecase",	Opt_namecase,
  		  fs_param_deprecated, NULL),
  	__fsparam(fs_param_is_u32, "codepage",	Opt_codepage,
  		  fs_param_deprecated, NULL),
719c1e182   Namjae Jeon   exfat: add super ...
244
245
  	{}
  };
719c1e182   Namjae Jeon   exfat: add super ...
246
247
248
249
250
251
  static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
  {
  	struct exfat_sb_info *sbi = fc->s_fs_info;
  	struct exfat_mount_options *opts = &sbi->options;
  	struct fs_parse_result result;
  	int opt;
9acd0d538   Valdis Kletnieks   exfat: update fil...
252
  	opt = fs_parse(fc, exfat_parameters, param, &result);
719c1e182   Namjae Jeon   exfat: add super ...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  	if (opt < 0)
  		return opt;
  
  	switch (opt) {
  	case Opt_uid:
  		opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
  		break;
  	case Opt_gid:
  		opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
  		break;
  	case Opt_umask:
  		opts->fs_fmask = result.uint_32;
  		opts->fs_dmask = result.uint_32;
  		break;
  	case Opt_dmask:
  		opts->fs_dmask = result.uint_32;
  		break;
  	case Opt_fmask:
  		opts->fs_fmask = result.uint_32;
  		break;
  	case Opt_allow_utime:
  		opts->allow_utime = result.uint_32 & 0022;
  		break;
  	case Opt_charset:
  		exfat_free_iocharset(sbi);
f341a7d8d   Al Viro   exfat: fix memory...
278
279
  		opts->iocharset = param->string;
  		param->string = NULL;
719c1e182   Namjae Jeon   exfat: add super ...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  		break;
  	case Opt_errors:
  		opts->errors = result.uint_32;
  		break;
  	case Opt_discard:
  		opts->discard = 1;
  		break;
  	case Opt_time_offset:
  		/*
  		 * Make the limit 24 just in case someone invents something
  		 * unusual.
  		 */
  		if (result.int_32 < -24 * 60 || result.int_32 > 24 * 60)
  			return -EINVAL;
  		opts->time_offset = result.int_32;
  		break;
907fa8932   Namjae Jeon   exfat: add the du...
296
297
298
299
300
  	case Opt_utf8:
  	case Opt_debug:
  	case Opt_namecase:
  	case Opt_codepage:
  		break;
719c1e182   Namjae Jeon   exfat: add super ...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
  
  static void exfat_hash_init(struct super_block *sb)
  {
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  	int i;
  
  	spin_lock_init(&sbi->inode_hash_lock);
  	for (i = 0; i < EXFAT_HASH_SIZE; i++)
  		INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
  }
  
  static int exfat_read_root(struct inode *inode)
  {
  	struct super_block *sb = inode->i_sb;
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  	struct exfat_inode_info *ei = EXFAT_I(inode);
  	struct exfat_chain cdir;
  	int num_subdirs, num_clu = 0;
  
  	exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
  	ei->entry = -1;
  	ei->start_clu = sbi->root_dir;
  	ei->flags = ALLOC_FAT_CHAIN;
  	ei->type = TYPE_DIR;
  	ei->version = 0;
719c1e182   Namjae Jeon   exfat: add super ...
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  	ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
  	ei->hint_stat.eidx = 0;
  	ei->hint_stat.clu = sbi->root_dir;
  	ei->hint_femp.eidx = EXFAT_HINT_NONE;
  
  	exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
  	if (exfat_count_num_clusters(sb, &cdir, &num_clu))
  		return -EIO;
  	i_size_write(inode, num_clu << sbi->cluster_size_bits);
  
  	num_subdirs = exfat_count_dir_entries(sb, &cdir);
  	if (num_subdirs < 0)
  		return -EIO;
  	set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR);
  
  	inode->i_uid = sbi->options.fs_uid;
  	inode->i_gid = sbi->options.fs_gid;
  	inode_inc_iversion(inode);
  	inode->i_generation = 0;
  	inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777);
  	inode->i_op = &exfat_dir_inode_operations;
  	inode->i_fop = &exfat_dir_operations;
  
  	inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1))
  			& ~(sbi->cluster_size - 1)) >> inode->i_blkbits;
  	EXFAT_I(inode)->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff;
  	EXFAT_I(inode)->i_size_aligned = i_size_read(inode);
  	EXFAT_I(inode)->i_size_ondisk = i_size_read(inode);
  
  	exfat_save_attr(inode, ATTR_SUBDIR);
  	inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
  		current_time(inode);
81df1ad40   Eric Sandeen   exfat: truncate a...
364
  	exfat_truncate_atime(&inode->i_atime);
719c1e182   Namjae Jeon   exfat: add super ...
365
366
  	return 0;
  }
33404a159   Tetsuhiro Kohada   exfat: separate t...
367
  static int exfat_calibrate_blocksize(struct super_block *sb, int logical_sect)
719c1e182   Namjae Jeon   exfat: add super ...
368
  {
b0516833d   Tetsuhiro Kohada   exfat: Unify acce...
369
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
719c1e182   Namjae Jeon   exfat: add super ...
370
371
372
  
  	if (!is_power_of_2(logical_sect) ||
  	    logical_sect < 512 || logical_sect > 4096) {
d1727d55c   Joe Perches   exfat: Use a more...
373
  		exfat_err(sb, "bogus logical sector size %u", logical_sect);
33404a159   Tetsuhiro Kohada   exfat: separate t...
374
  		return -EIO;
719c1e182   Namjae Jeon   exfat: add super ...
375
376
377
  	}
  
  	if (logical_sect < sb->s_blocksize) {
d1727d55c   Joe Perches   exfat: Use a more...
378
379
  		exfat_err(sb, "logical sector size too small for device (logical sector size = %u)",
  			  logical_sect);
33404a159   Tetsuhiro Kohada   exfat: separate t...
380
  		return -EIO;
719c1e182   Namjae Jeon   exfat: add super ...
381
382
383
  	}
  
  	if (logical_sect > sb->s_blocksize) {
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
384
385
  		brelse(sbi->boot_bh);
  		sbi->boot_bh = NULL;
719c1e182   Namjae Jeon   exfat: add super ...
386
387
  
  		if (!sb_set_blocksize(sb, logical_sect)) {
d1727d55c   Joe Perches   exfat: Use a more...
388
389
  			exfat_err(sb, "unable to set blocksize %u",
  				  logical_sect);
33404a159   Tetsuhiro Kohada   exfat: separate t...
390
  			return -EIO;
719c1e182   Namjae Jeon   exfat: add super ...
391
  		}
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
392
393
  		sbi->boot_bh = sb_bread(sb, 0);
  		if (!sbi->boot_bh) {
d1727d55c   Joe Perches   exfat: Use a more...
394
395
  			exfat_err(sb, "unable to read boot sector (logical sector size = %lu)",
  				  sb->s_blocksize);
33404a159   Tetsuhiro Kohada   exfat: separate t...
396
  			return -EIO;
719c1e182   Namjae Jeon   exfat: add super ...
397
  		}
719c1e182   Namjae Jeon   exfat: add super ...
398
  	}
33404a159   Tetsuhiro Kohada   exfat: separate t...
399
  	return 0;
719c1e182   Namjae Jeon   exfat: add super ...
400
  }
33404a159   Tetsuhiro Kohada   exfat: separate t...
401
  static int exfat_read_boot_sector(struct super_block *sb)
719c1e182   Namjae Jeon   exfat: add super ...
402
  {
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
403
  	struct boot_sector *p_boot;
719c1e182   Namjae Jeon   exfat: add super ...
404
405
406
407
408
409
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  
  	/* set block size to read super block */
  	sb_min_blocksize(sb, 512);
  
  	/* read boot sector */
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
410
411
  	sbi->boot_bh = sb_bread(sb, 0);
  	if (!sbi->boot_bh) {
d1727d55c   Joe Perches   exfat: Use a more...
412
  		exfat_err(sb, "unable to read boot sector");
719c1e182   Namjae Jeon   exfat: add super ...
413
414
  		return -EIO;
  	}
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
415
  	p_boot = (struct boot_sector *)sbi->boot_bh->b_data;
719c1e182   Namjae Jeon   exfat: add super ...
416

181a9e800   Tetsuhiro Kohada   exfat: redefine P...
417
418
  	/* check the validity of BOOT */
  	if (le16_to_cpu((p_boot->signature)) != BOOT_SIGNATURE) {
d1727d55c   Joe Perches   exfat: Use a more...
419
  		exfat_err(sb, "invalid boot record signature");
33404a159   Tetsuhiro Kohada   exfat: separate t...
420
  		return -EINVAL;
719c1e182   Namjae Jeon   exfat: add super ...
421
  	}
33404a159   Tetsuhiro Kohada   exfat: separate t...
422
423
424
  	if (memcmp(p_boot->fs_name, STR_EXFAT, BOOTSEC_FS_NAME_LEN)) {
  		exfat_err(sb, "invalid fs_name"); /* fs_name may unprintable */
  		return -EINVAL;
719c1e182   Namjae Jeon   exfat: add super ...
425
426
427
  	}
  
  	/*
33404a159   Tetsuhiro Kohada   exfat: separate t...
428
  	 * must_be_zero field must be filled with zero to prevent mounting
719c1e182   Namjae Jeon   exfat: add super ...
429
430
  	 * from FAT volume.
  	 */
33404a159   Tetsuhiro Kohada   exfat: separate t...
431
432
  	if (memchr_inv(p_boot->must_be_zero, 0, sizeof(p_boot->must_be_zero)))
  		return -EINVAL;
719c1e182   Namjae Jeon   exfat: add super ...
433

33404a159   Tetsuhiro Kohada   exfat: separate t...
434
  	if (p_boot->num_fats != 1 && p_boot->num_fats != 2) {
d1727d55c   Joe Perches   exfat: Use a more...
435
  		exfat_err(sb, "bogus number of FAT structure");
33404a159   Tetsuhiro Kohada   exfat: separate t...
436
  		return -EINVAL;
719c1e182   Namjae Jeon   exfat: add super ...
437
  	}
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
438
439
  	sbi->sect_per_clus = 1 << p_boot->sect_per_clus_bits;
  	sbi->sect_per_clus_bits = p_boot->sect_per_clus_bits;
33404a159   Tetsuhiro Kohada   exfat: separate t...
440
441
  	sbi->cluster_size_bits = p_boot->sect_per_clus_bits +
  		p_boot->sect_size_bits;
719c1e182   Namjae Jeon   exfat: add super ...
442
  	sbi->cluster_size = 1 << sbi->cluster_size_bits;
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
443
444
  	sbi->num_FAT_sectors = le32_to_cpu(p_boot->fat_length);
  	sbi->FAT1_start_sector = le32_to_cpu(p_boot->fat_offset);
33404a159   Tetsuhiro Kohada   exfat: separate t...
445
446
447
  	sbi->FAT2_start_sector = le32_to_cpu(p_boot->fat_offset);
  	if (p_boot->num_fats == 2)
  		sbi->FAT2_start_sector += sbi->num_FAT_sectors;
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
448
449
  	sbi->data_start_sector = le32_to_cpu(p_boot->clu_offset);
  	sbi->num_sectors = le64_to_cpu(p_boot->vol_length);
719c1e182   Namjae Jeon   exfat: add super ...
450
  	/* because the cluster index starts with 2 */
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
451
  	sbi->num_clusters = le32_to_cpu(p_boot->clu_count) +
719c1e182   Namjae Jeon   exfat: add super ...
452
  		EXFAT_RESERVED_CLUSTERS;
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
453
  	sbi->root_dir = le32_to_cpu(p_boot->root_cluster);
719c1e182   Namjae Jeon   exfat: add super ...
454
455
  	sbi->dentries_per_clu = 1 <<
  		(sbi->cluster_size_bits - DENTRY_SIZE_BITS);
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
456
457
  	sbi->vol_flags = le16_to_cpu(p_boot->vol_flags);
  	sbi->vol_flags_persistent = sbi->vol_flags & (VOLUME_DIRTY | MEDIA_FAILURE);
719c1e182   Namjae Jeon   exfat: add super ...
458
459
  	sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
  	sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED;
33404a159   Tetsuhiro Kohada   exfat: separate t...
460
461
462
463
464
465
466
467
468
469
  	/* check consistencies */
  	if (sbi->num_FAT_sectors << p_boot->sect_size_bits <
  	    sbi->num_clusters * 4) {
  		exfat_err(sb, "bogus fat length");
  		return -EINVAL;
  	}
  	if (sbi->data_start_sector <
  	    sbi->FAT1_start_sector + sbi->num_FAT_sectors * p_boot->num_fats) {
  		exfat_err(sb, "bogus data start sector");
  		return -EINVAL;
719c1e182   Namjae Jeon   exfat: add super ...
470
  	}
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
471
  	if (sbi->vol_flags & VOLUME_DIRTY)
33404a159   Tetsuhiro Kohada   exfat: separate t...
472
  		exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck.");
7018ec68f   Tetsuhiro Kohada   exfat: retain 'Vo...
473
  	if (sbi->vol_flags & MEDIA_FAILURE)
33404a159   Tetsuhiro Kohada   exfat: separate t...
474
  		exfat_warn(sb, "Medium has reported failures. Some data may be lost.");
719c1e182   Namjae Jeon   exfat: add super ...
475
476
477
478
  
  	/* exFAT file size is limited by a disk volume size */
  	sb->s_maxbytes = (u64)(sbi->num_clusters - EXFAT_RESERVED_CLUSTERS) <<
  		sbi->cluster_size_bits;
33404a159   Tetsuhiro Kohada   exfat: separate t...
479
480
481
482
483
484
  	/* check logical sector size */
  	if (exfat_calibrate_blocksize(sb, 1 << p_boot->sect_size_bits))
  		return -EIO;
  
  	return 0;
  }
476189c0e   Tetsuhiro Kohada   exfat: add boot r...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  static int exfat_verify_boot_region(struct super_block *sb)
  {
  	struct buffer_head *bh = NULL;
  	u32 chksum = 0;
  	__le32 *p_sig, *p_chksum;
  	int sn, i;
  
  	/* read boot sector sub-regions */
  	for (sn = 0; sn < 11; sn++) {
  		bh = sb_bread(sb, sn);
  		if (!bh)
  			return -EIO;
  
  		if (sn != 0 && sn <= 8) {
  			/* extended boot sector sub-regions */
  			p_sig = (__le32 *)&bh->b_data[sb->s_blocksize - 4];
  			if (le32_to_cpu(*p_sig) != EXBOOT_SIGNATURE)
  				exfat_warn(sb, "Invalid exboot-signature(sector = %d): 0x%08x",
  					   sn, le32_to_cpu(*p_sig));
  		}
  
  		chksum = exfat_calc_chksum32(bh->b_data, sb->s_blocksize,
  			chksum, sn ? CS_DEFAULT : CS_BOOT_SECTOR);
  		brelse(bh);
  	}
  
  	/* boot checksum sub-regions */
  	bh = sb_bread(sb, sn);
  	if (!bh)
  		return -EIO;
  
  	for (i = 0; i < sb->s_blocksize; i += sizeof(u32)) {
  		p_chksum = (__le32 *)&bh->b_data[i];
  		if (le32_to_cpu(*p_chksum) != chksum) {
  			exfat_err(sb, "Invalid boot checksum (boot checksum : 0x%08x, checksum : 0x%08x)",
  				  le32_to_cpu(*p_chksum), chksum);
  			brelse(bh);
  			return -EINVAL;
  		}
  	}
  	brelse(bh);
  	return 0;
  }
33404a159   Tetsuhiro Kohada   exfat: separate t...
528
529
530
531
532
533
534
535
536
537
  /* mount the file system volume */
  static int __exfat_fill_super(struct super_block *sb)
  {
  	int ret;
  	struct exfat_sb_info *sbi = EXFAT_SB(sb);
  
  	ret = exfat_read_boot_sector(sb);
  	if (ret) {
  		exfat_err(sb, "failed to read boot sector");
  		goto free_bh;
476189c0e   Tetsuhiro Kohada   exfat: add boot r...
538
539
540
541
542
543
  	}
  
  	ret = exfat_verify_boot_region(sb);
  	if (ret) {
  		exfat_err(sb, "invalid boot region");
  		goto free_bh;
33404a159   Tetsuhiro Kohada   exfat: separate t...
544
  	}
719c1e182   Namjae Jeon   exfat: add super ...
545
546
  	ret = exfat_create_upcase_table(sb);
  	if (ret) {
d1727d55c   Joe Perches   exfat: Use a more...
547
  		exfat_err(sb, "failed to load upcase table");
719c1e182   Namjae Jeon   exfat: add super ...
548
549
550
551
552
  		goto free_bh;
  	}
  
  	ret = exfat_load_bitmap(sb);
  	if (ret) {
d1727d55c   Joe Perches   exfat: Use a more...
553
  		exfat_err(sb, "failed to load alloc-bitmap");
719c1e182   Namjae Jeon   exfat: add super ...
554
555
556
557
558
  		goto free_upcase_table;
  	}
  
  	ret = exfat_count_used_clusters(sb, &sbi->used_clusters);
  	if (ret) {
d1727d55c   Joe Perches   exfat: Use a more...
559
  		exfat_err(sb, "failed to scan clusters");
719c1e182   Namjae Jeon   exfat: add super ...
560
561
562
563
564
565
566
567
568
569
  		goto free_alloc_bitmap;
  	}
  
  	return 0;
  
  free_alloc_bitmap:
  	exfat_free_bitmap(sbi);
  free_upcase_table:
  	exfat_free_upcase_table(sbi);
  free_bh:
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
570
  	brelse(sbi->boot_bh);
719c1e182   Namjae Jeon   exfat: add super ...
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
  	return ret;
  }
  
  static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
  {
  	struct exfat_sb_info *sbi = sb->s_fs_info;
  	struct exfat_mount_options *opts = &sbi->options;
  	struct inode *root_inode;
  	int err;
  
  	if (opts->allow_utime == (unsigned short)-1)
  		opts->allow_utime = ~opts->fs_dmask & 0022;
  
  	if (opts->discard) {
  		struct request_queue *q = bdev_get_queue(sb->s_bdev);
b7e038a92   Pali Rohár   exfat: Fix discar...
586
  		if (!blk_queue_discard(q)) {
d1727d55c   Joe Perches   exfat: Use a more...
587
  			exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard");
b7e038a92   Pali Rohár   exfat: Fix discar...
588
589
  			opts->discard = 0;
  		}
719c1e182   Namjae Jeon   exfat: add super ...
590
591
592
593
594
  	}
  
  	sb->s_flags |= SB_NODIRATIME;
  	sb->s_magic = EXFAT_SUPER_MAGIC;
  	sb->s_op = &exfat_sops;
674a9985b   Eric Sandeen   exfat: properly s...
595
  	sb->s_time_gran = 10 * NSEC_PER_MSEC;
719c1e182   Namjae Jeon   exfat: add super ...
596
597
598
599
600
  	sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS;
  	sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS;
  
  	err = __exfat_fill_super(sb);
  	if (err) {
d1727d55c   Joe Perches   exfat: Use a more...
601
  		exfat_err(sb, "failed to recognize exfat type");
719c1e182   Namjae Jeon   exfat: add super ...
602
603
604
605
606
607
608
609
610
611
612
  		goto check_nls_io;
  	}
  
  	/* set up enough so that it can read an inode */
  	exfat_hash_init(sb);
  
  	if (!strcmp(sbi->options.iocharset, "utf8"))
  		opts->utf8 = 1;
  	else {
  		sbi->nls_io = load_nls(sbi->options.iocharset);
  		if (!sbi->nls_io) {
d1727d55c   Joe Perches   exfat: Use a more...
613
614
  			exfat_err(sb, "IO charset %s not found",
  				  sbi->options.iocharset);
719c1e182   Namjae Jeon   exfat: add super ...
615
616
617
618
619
620
621
622
623
624
625
626
  			err = -EINVAL;
  			goto free_table;
  		}
  	}
  
  	if (sbi->options.utf8)
  		sb->s_d_op = &exfat_utf8_dentry_ops;
  	else
  		sb->s_d_op = &exfat_dentry_ops;
  
  	root_inode = new_inode(sb);
  	if (!root_inode) {
d1727d55c   Joe Perches   exfat: Use a more...
627
  		exfat_err(sb, "failed to allocate root inode");
719c1e182   Namjae Jeon   exfat: add super ...
628
629
630
631
632
633
634
635
  		err = -ENOMEM;
  		goto free_table;
  	}
  
  	root_inode->i_ino = EXFAT_ROOT_INO;
  	inode_set_iversion(root_inode, 1);
  	err = exfat_read_root(root_inode);
  	if (err) {
d1727d55c   Joe Perches   exfat: Use a more...
636
  		exfat_err(sb, "failed to initialize root inode");
719c1e182   Namjae Jeon   exfat: add super ...
637
638
639
640
641
642
643
644
  		goto put_inode;
  	}
  
  	exfat_hash_inode(root_inode, EXFAT_I(root_inode)->i_pos);
  	insert_inode_hash(root_inode);
  
  	sb->s_root = d_make_root(root_inode);
  	if (!sb->s_root) {
d1727d55c   Joe Perches   exfat: Use a more...
645
  		exfat_err(sb, "failed to get the root dentry");
719c1e182   Namjae Jeon   exfat: add super ...
646
647
648
649
650
651
652
653
654
655
656
657
658
  		err = -ENOMEM;
  		goto put_inode;
  	}
  
  	return 0;
  
  put_inode:
  	iput(root_inode);
  	sb->s_root = NULL;
  
  free_table:
  	exfat_free_upcase_table(sbi);
  	exfat_free_bitmap(sbi);
181a9e800   Tetsuhiro Kohada   exfat: redefine P...
659
  	brelse(sbi->boot_bh);
719c1e182   Namjae Jeon   exfat: add super ...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  
  check_nls_io:
  	unload_nls(sbi->nls_io);
  	exfat_free_iocharset(sbi);
  	sb->s_fs_info = NULL;
  	kfree(sbi);
  	return err;
  }
  
  static int exfat_get_tree(struct fs_context *fc)
  {
  	return get_tree_bdev(fc, exfat_fill_super);
  }
  
  static void exfat_free(struct fs_context *fc)
  {
f341a7d8d   Al Viro   exfat: fix memory...
676
677
678
679
680
681
  	struct exfat_sb_info *sbi = fc->s_fs_info;
  
  	if (sbi) {
  		exfat_free_iocharset(sbi);
  		kfree(sbi);
  	}
719c1e182   Namjae Jeon   exfat: add super ...
682
  }
a0271a15c   Hyunchul Lee   exfat: call sync_...
683
684
685
686
687
688
689
690
  static int exfat_reconfigure(struct fs_context *fc)
  {
  	fc->sb_flags |= SB_NODIRATIME;
  
  	/* volume flag will be updated in exfat_sync_fs */
  	sync_filesystem(fc->root->d_sb);
  	return 0;
  }
719c1e182   Namjae Jeon   exfat: add super ...
691
692
693
694
  static const struct fs_context_operations exfat_context_ops = {
  	.parse_param	= exfat_parse_param,
  	.get_tree	= exfat_get_tree,
  	.free		= exfat_free,
a0271a15c   Hyunchul Lee   exfat: call sync_...
695
  	.reconfigure	= exfat_reconfigure,
719c1e182   Namjae Jeon   exfat: add super ...
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
  };
  
  static int exfat_init_fs_context(struct fs_context *fc)
  {
  	struct exfat_sb_info *sbi;
  
  	sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL);
  	if (!sbi)
  		return -ENOMEM;
  
  	mutex_init(&sbi->s_lock);
  	ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
  			DEFAULT_RATELIMIT_BURST);
  
  	sbi->options.fs_uid = current_uid();
  	sbi->options.fs_gid = current_gid();
  	sbi->options.fs_fmask = current->fs->umask;
  	sbi->options.fs_dmask = current->fs->umask;
  	sbi->options.allow_utime = -1;
  	sbi->options.iocharset = exfat_default_iocharset;
  	sbi->options.errors = EXFAT_ERRORS_RO;
  
  	fc->s_fs_info = sbi;
  	fc->ops = &exfat_context_ops;
  	return 0;
  }
  
  static struct file_system_type exfat_fs_type = {
  	.owner			= THIS_MODULE,
  	.name			= "exfat",
  	.init_fs_context	= exfat_init_fs_context,
9acd0d538   Valdis Kletnieks   exfat: update fil...
727
  	.parameters		= exfat_parameters,
719c1e182   Namjae Jeon   exfat: add super ...
728
729
730
731
732
733
734
  	.kill_sb		= kill_block_super,
  	.fs_flags		= FS_REQUIRES_DEV,
  };
  
  static void exfat_inode_init_once(void *foo)
  {
  	struct exfat_inode_info *ei = (struct exfat_inode_info *)foo;
8ff006e57   Namjae Jeon   exfat: fix use of...
735
736
737
738
  	spin_lock_init(&ei->cache_lru_lock);
  	ei->nr_caches = 0;
  	ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
  	INIT_LIST_HEAD(&ei->cache_lru);
719c1e182   Namjae Jeon   exfat: add super ...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
  	INIT_HLIST_NODE(&ei->i_hash_fat);
  	inode_init_once(&ei->vfs_inode);
  }
  
  static int __init init_exfat_fs(void)
  {
  	int err;
  
  	err = exfat_cache_init();
  	if (err)
  		return err;
  
  	exfat_inode_cachep = kmem_cache_create("exfat_inode_cache",
  			sizeof(struct exfat_inode_info),
  			0, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
  			exfat_inode_init_once);
  	if (!exfat_inode_cachep) {
  		err = -ENOMEM;
  		goto shutdown_cache;
  	}
  
  	err = register_filesystem(&exfat_fs_type);
  	if (err)
  		goto destroy_cache;
  
  	return 0;
  
  destroy_cache:
  	kmem_cache_destroy(exfat_inode_cachep);
  shutdown_cache:
  	exfat_cache_shutdown();
  	return err;
  }
  
  static void __exit exit_exfat_fs(void)
  {
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
  	kmem_cache_destroy(exfat_inode_cachep);
  	unregister_filesystem(&exfat_fs_type);
  	exfat_cache_shutdown();
  }
  
  module_init(init_exfat_fs);
  module_exit(exit_exfat_fs);
cd76ac258   Thomas Backlund   exfat: add missin...
787
  MODULE_ALIAS_FS("exfat");
719c1e182   Namjae Jeon   exfat: add super ...
788
789
790
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("exFAT filesystem support");
  MODULE_AUTHOR("Samsung Electronics Co., Ltd.");