aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/super.c')
-rw-r--r--fs/f2fs/super.c253
1 files changed, 168 insertions, 85 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 8555f7df82c7..75c7dc363e92 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -34,7 +34,7 @@
34static struct kmem_cache *f2fs_inode_cachep; 34static struct kmem_cache *f2fs_inode_cachep;
35 35
36enum { 36enum {
37 Opt_gc_background_off, 37 Opt_gc_background,
38 Opt_disable_roll_forward, 38 Opt_disable_roll_forward,
39 Opt_discard, 39 Opt_discard,
40 Opt_noheap, 40 Opt_noheap,
@@ -46,7 +46,7 @@ enum {
46}; 46};
47 47
48static match_table_t f2fs_tokens = { 48static match_table_t f2fs_tokens = {
49 {Opt_gc_background_off, "background_gc_off"}, 49 {Opt_gc_background, "background_gc=%s"},
50 {Opt_disable_roll_forward, "disable_roll_forward"}, 50 {Opt_disable_roll_forward, "disable_roll_forward"},
51 {Opt_discard, "discard"}, 51 {Opt_discard, "discard"},
52 {Opt_noheap, "no_heap"}, 52 {Opt_noheap, "no_heap"},
@@ -76,6 +76,91 @@ static void init_once(void *foo)
76 inode_init_once(&fi->vfs_inode); 76 inode_init_once(&fi->vfs_inode);
77} 77}
78 78
79static int parse_options(struct super_block *sb, char *options)
80{
81 struct f2fs_sb_info *sbi = F2FS_SB(sb);
82 substring_t args[MAX_OPT_ARGS];
83 char *p, *name;
84 int arg = 0;
85
86 if (!options)
87 return 0;
88
89 while ((p = strsep(&options, ",")) != NULL) {
90 int token;
91 if (!*p)
92 continue;
93 /*
94 * Initialize args struct so we know whether arg was
95 * found; some options take optional arguments.
96 */
97 args[0].to = args[0].from = NULL;
98 token = match_token(p, f2fs_tokens, args);
99
100 switch (token) {
101 case Opt_gc_background:
102 name = match_strdup(&args[0]);
103
104 if (!name)
105 return -ENOMEM;
106 if (!strncmp(name, "on", 2))
107 set_opt(sbi, BG_GC);
108 else if (!strncmp(name, "off", 3))
109 clear_opt(sbi, BG_GC);
110 else {
111 kfree(name);
112 return -EINVAL;
113 }
114 kfree(name);
115 break;
116 case Opt_disable_roll_forward:
117 set_opt(sbi, DISABLE_ROLL_FORWARD);
118 break;
119 case Opt_discard:
120 set_opt(sbi, DISCARD);
121 break;
122 case Opt_noheap:
123 set_opt(sbi, NOHEAP);
124 break;
125#ifdef CONFIG_F2FS_FS_XATTR
126 case Opt_nouser_xattr:
127 clear_opt(sbi, XATTR_USER);
128 break;
129#else
130 case Opt_nouser_xattr:
131 f2fs_msg(sb, KERN_INFO,
132 "nouser_xattr options not supported");
133 break;
134#endif
135#ifdef CONFIG_F2FS_FS_POSIX_ACL
136 case Opt_noacl:
137 clear_opt(sbi, POSIX_ACL);
138 break;
139#else
140 case Opt_noacl:
141 f2fs_msg(sb, KERN_INFO, "noacl options not supported");
142 break;
143#endif
144 case Opt_active_logs:
145 if (args->from && match_int(args, &arg))
146 return -EINVAL;
147 if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE)
148 return -EINVAL;
149 sbi->active_logs = arg;
150 break;
151 case Opt_disable_ext_identify:
152 set_opt(sbi, DISABLE_EXT_IDENTIFY);
153 break;
154 default:
155 f2fs_msg(sb, KERN_ERR,
156 "Unrecognized mount option \"%s\" or missing value",
157 p);
158 return -EINVAL;
159 }
160 }
161 return 0;
162}
163
79static struct inode *f2fs_alloc_inode(struct super_block *sb) 164static struct inode *f2fs_alloc_inode(struct super_block *sb)
80{ 165{
81 struct f2fs_inode_info *fi; 166 struct f2fs_inode_info *fi;
@@ -112,6 +197,17 @@ static int f2fs_drop_inode(struct inode *inode)
112 return generic_drop_inode(inode); 197 return generic_drop_inode(inode);
113} 198}
114 199
200/*
201 * f2fs_dirty_inode() is called from __mark_inode_dirty()
202 *
203 * We should call set_dirty_inode to write the dirty inode through write_inode.
204 */
205static void f2fs_dirty_inode(struct inode *inode, int flags)
206{
207 set_inode_flag(F2FS_I(inode), FI_DIRTY_INODE);
208 return;
209}
210
115static void f2fs_i_callback(struct rcu_head *head) 211static void f2fs_i_callback(struct rcu_head *head)
116{ 212{
117 struct inode *inode = container_of(head, struct inode, i_rcu); 213 struct inode *inode = container_of(head, struct inode, i_rcu);
@@ -170,7 +266,7 @@ static int f2fs_freeze(struct super_block *sb)
170{ 266{
171 int err; 267 int err;
172 268
173 if (sb->s_flags & MS_RDONLY) 269 if (f2fs_readonly(sb))
174 return 0; 270 return 0;
175 271
176 err = f2fs_sync_fs(sb, 1); 272 err = f2fs_sync_fs(sb, 1);
@@ -214,10 +310,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
214{ 310{
215 struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb); 311 struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb);
216 312
217 if (test_opt(sbi, BG_GC)) 313 if (!(root->d_sb->s_flags & MS_RDONLY) && test_opt(sbi, BG_GC))
218 seq_puts(seq, ",background_gc_on"); 314 seq_printf(seq, ",background_gc=%s", "on");
219 else 315 else
220 seq_puts(seq, ",background_gc_off"); 316 seq_printf(seq, ",background_gc=%s", "off");
221 if (test_opt(sbi, DISABLE_ROLL_FORWARD)) 317 if (test_opt(sbi, DISABLE_ROLL_FORWARD))
222 seq_puts(seq, ",disable_roll_forward"); 318 seq_puts(seq, ",disable_roll_forward");
223 if (test_opt(sbi, DISCARD)) 319 if (test_opt(sbi, DISCARD))
@@ -244,11 +340,64 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
244 return 0; 340 return 0;
245} 341}
246 342
343static int f2fs_remount(struct super_block *sb, int *flags, char *data)
344{
345 struct f2fs_sb_info *sbi = F2FS_SB(sb);
346 struct f2fs_mount_info org_mount_opt;
347 int err, active_logs;
348
349 /*
350 * Save the old mount options in case we
351 * need to restore them.
352 */
353 org_mount_opt = sbi->mount_opt;
354 active_logs = sbi->active_logs;
355
356 /* parse mount options */
357 err = parse_options(sb, data);
358 if (err)
359 goto restore_opts;
360
361 /*
362 * Previous and new state of filesystem is RO,
363 * so no point in checking GC conditions.
364 */
365 if ((sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY))
366 goto skip;
367
368 /*
369 * We stop the GC thread if FS is mounted as RO
370 * or if background_gc = off is passed in mount
371 * option. Also sync the filesystem.
372 */
373 if ((*flags & MS_RDONLY) || !test_opt(sbi, BG_GC)) {
374 if (sbi->gc_thread) {
375 stop_gc_thread(sbi);
376 f2fs_sync_fs(sb, 1);
377 }
378 } else if (test_opt(sbi, BG_GC) && !sbi->gc_thread) {
379 err = start_gc_thread(sbi);
380 if (err)
381 goto restore_opts;
382 }
383skip:
384 /* Update the POSIXACL Flag */
385 sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
386 (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
387 return 0;
388
389restore_opts:
390 sbi->mount_opt = org_mount_opt;
391 sbi->active_logs = active_logs;
392 return err;
393}
394
247static struct super_operations f2fs_sops = { 395static struct super_operations f2fs_sops = {
248 .alloc_inode = f2fs_alloc_inode, 396 .alloc_inode = f2fs_alloc_inode,
249 .drop_inode = f2fs_drop_inode, 397 .drop_inode = f2fs_drop_inode,
250 .destroy_inode = f2fs_destroy_inode, 398 .destroy_inode = f2fs_destroy_inode,
251 .write_inode = f2fs_write_inode, 399 .write_inode = f2fs_write_inode,
400 .dirty_inode = f2fs_dirty_inode,
252 .show_options = f2fs_show_options, 401 .show_options = f2fs_show_options,
253 .evict_inode = f2fs_evict_inode, 402 .evict_inode = f2fs_evict_inode,
254 .put_super = f2fs_put_super, 403 .put_super = f2fs_put_super,
@@ -256,6 +405,7 @@ static struct super_operations f2fs_sops = {
256 .freeze_fs = f2fs_freeze, 405 .freeze_fs = f2fs_freeze,
257 .unfreeze_fs = f2fs_unfreeze, 406 .unfreeze_fs = f2fs_unfreeze,
258 .statfs = f2fs_statfs, 407 .statfs = f2fs_statfs,
408 .remount_fs = f2fs_remount,
259}; 409};
260 410
261static struct inode *f2fs_nfs_get_inode(struct super_block *sb, 411static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
@@ -303,79 +453,6 @@ static const struct export_operations f2fs_export_ops = {
303 .get_parent = f2fs_get_parent, 453 .get_parent = f2fs_get_parent,
304}; 454};
305 455
306static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi,
307 char *options)
308{
309 substring_t args[MAX_OPT_ARGS];
310 char *p;
311 int arg = 0;
312
313 if (!options)
314 return 0;
315
316 while ((p = strsep(&options, ",")) != NULL) {
317 int token;
318 if (!*p)
319 continue;
320 /*
321 * Initialize args struct so we know whether arg was
322 * found; some options take optional arguments.
323 */
324 args[0].to = args[0].from = NULL;
325 token = match_token(p, f2fs_tokens, args);
326
327 switch (token) {
328 case Opt_gc_background_off:
329 clear_opt(sbi, BG_GC);
330 break;
331 case Opt_disable_roll_forward:
332 set_opt(sbi, DISABLE_ROLL_FORWARD);
333 break;
334 case Opt_discard:
335 set_opt(sbi, DISCARD);
336 break;
337 case Opt_noheap:
338 set_opt(sbi, NOHEAP);
339 break;
340#ifdef CONFIG_F2FS_FS_XATTR
341 case Opt_nouser_xattr:
342 clear_opt(sbi, XATTR_USER);
343 break;
344#else
345 case Opt_nouser_xattr:
346 f2fs_msg(sb, KERN_INFO,
347 "nouser_xattr options not supported");
348 break;
349#endif
350#ifdef CONFIG_F2FS_FS_POSIX_ACL
351 case Opt_noacl:
352 clear_opt(sbi, POSIX_ACL);
353 break;
354#else
355 case Opt_noacl:
356 f2fs_msg(sb, KERN_INFO, "noacl options not supported");
357 break;
358#endif
359 case Opt_active_logs:
360 if (args->from && match_int(args, &arg))
361 return -EINVAL;
362 if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE)
363 return -EINVAL;
364 sbi->active_logs = arg;
365 break;
366 case Opt_disable_ext_identify:
367 set_opt(sbi, DISABLE_EXT_IDENTIFY);
368 break;
369 default:
370 f2fs_msg(sb, KERN_ERR,
371 "Unrecognized mount option \"%s\" or missing value",
372 p);
373 return -EINVAL;
374 }
375 }
376 return 0;
377}
378
379static loff_t max_file_size(unsigned bits) 456static loff_t max_file_size(unsigned bits)
380{ 457{
381 loff_t result = ADDRS_PER_INODE; 458 loff_t result = ADDRS_PER_INODE;
@@ -541,6 +618,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
541 if (err) 618 if (err)
542 goto free_sb_buf; 619 goto free_sb_buf;
543 } 620 }
621 sb->s_fs_info = sbi;
544 /* init some FS parameters */ 622 /* init some FS parameters */
545 sbi->active_logs = NR_CURSEG_TYPE; 623 sbi->active_logs = NR_CURSEG_TYPE;
546 624
@@ -553,7 +631,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
553 set_opt(sbi, POSIX_ACL); 631 set_opt(sbi, POSIX_ACL);
554#endif 632#endif
555 /* parse mount options */ 633 /* parse mount options */
556 err = parse_options(sb, sbi, (char *)data); 634 err = parse_options(sb, (char *)data);
557 if (err) 635 if (err)
558 goto free_sb_buf; 636 goto free_sb_buf;
559 637
@@ -565,7 +643,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
565 sb->s_xattr = f2fs_xattr_handlers; 643 sb->s_xattr = f2fs_xattr_handlers;
566 sb->s_export_op = &f2fs_export_ops; 644 sb->s_export_op = &f2fs_export_ops;
567 sb->s_magic = F2FS_SUPER_MAGIC; 645 sb->s_magic = F2FS_SUPER_MAGIC;
568 sb->s_fs_info = sbi;
569 sb->s_time_gran = 1; 646 sb->s_time_gran = 1;
570 sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | 647 sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
571 (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); 648 (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
@@ -674,10 +751,16 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
674 "Cannot recover all fsync data errno=%ld", err); 751 "Cannot recover all fsync data errno=%ld", err);
675 } 752 }
676 753
677 /* After POR, we can run background GC thread */ 754 /*
678 err = start_gc_thread(sbi); 755 * If filesystem is not mounted as read-only then
679 if (err) 756 * do start the gc_thread.
680 goto fail; 757 */
758 if (!(sb->s_flags & MS_RDONLY)) {
759 /* After POR, we can run background GC thread.*/
760 err = start_gc_thread(sbi);
761 if (err)
762 goto fail;
763 }
681 764
682 err = f2fs_build_stats(sbi); 765 err = f2fs_build_stats(sbi);
683 if (err) 766 if (err)