mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
f2fs: add remount_fs callback support
Add the f2fs_remount function call which will be used during the filesystem remounting. This function will help us to change the mount options specific to f2fs. Also modify the f2fs background_gc mount option, which will allow the user to dynamically trun on/off the garbage collection in f2fs based on the background_gc value. If background_gc=on, Garbage collection will be turned off & if background_gc=off, Garbage collection will be truned on. By default the garbage collection is on in f2fs. Change Log: v2: Incorporated the review comments by Gu Zheng. Removing the restore part for VFS flags Updating comments with proper flag conditions Display GC background option as ON/OFF Revised conditions to stop GC in case of remount v1: Initial changes for adding remount_fs callback support. Cc: Gu Zheng <guz.fnst@cn.fujitsu.com> Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Pankaj Kumar <pankaj.km@samsung.com> Reviewed-by: Gu Zheng <guz.fnst@cn.fujitsu.com> [Jaegeuk Kim: change /** with /* for the coding style] Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
This commit is contained in:
parent
354a3399dc
commit
696c018c77
@ -98,8 +98,13 @@ Cleaning Overhead
|
||||
MOUNT OPTIONS
|
||||
================================================================================
|
||||
|
||||
background_gc_off Turn off cleaning operations, namely garbage collection,
|
||||
triggered in background when I/O subsystem is idle.
|
||||
background_gc=%s Turn on/off cleaning operations, namely garbage
|
||||
collection, triggered in background when I/O subsystem is
|
||||
idle. If background_gc=on, it will turn on the garbage
|
||||
collection and if background_gc=off, garbage collection
|
||||
will be truned off.
|
||||
Default value for this option is on. So garbage
|
||||
collection is on by default.
|
||||
disable_roll_forward Disable the roll-forward recovery routine
|
||||
discard Issue discard/TRIM commands when a segment is cleaned.
|
||||
no_heap Disable heap-style segment allocation which finds free
|
||||
|
235
fs/f2fs/super.c
235
fs/f2fs/super.c
@ -34,7 +34,7 @@
|
||||
static struct kmem_cache *f2fs_inode_cachep;
|
||||
|
||||
enum {
|
||||
Opt_gc_background_off,
|
||||
Opt_gc_background,
|
||||
Opt_disable_roll_forward,
|
||||
Opt_discard,
|
||||
Opt_noheap,
|
||||
@ -46,7 +46,7 @@ enum {
|
||||
};
|
||||
|
||||
static match_table_t f2fs_tokens = {
|
||||
{Opt_gc_background_off, "background_gc_off"},
|
||||
{Opt_gc_background, "background_gc=%s"},
|
||||
{Opt_disable_roll_forward, "disable_roll_forward"},
|
||||
{Opt_discard, "discard"},
|
||||
{Opt_noheap, "no_heap"},
|
||||
@ -76,6 +76,91 @@ static void init_once(void *foo)
|
||||
inode_init_once(&fi->vfs_inode);
|
||||
}
|
||||
|
||||
static int parse_options(struct super_block *sb, char *options)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
char *p, *name;
|
||||
int arg = 0;
|
||||
|
||||
if (!options)
|
||||
return 0;
|
||||
|
||||
while ((p = strsep(&options, ",")) != NULL) {
|
||||
int token;
|
||||
if (!*p)
|
||||
continue;
|
||||
/*
|
||||
* Initialize args struct so we know whether arg was
|
||||
* found; some options take optional arguments.
|
||||
*/
|
||||
args[0].to = args[0].from = NULL;
|
||||
token = match_token(p, f2fs_tokens, args);
|
||||
|
||||
switch (token) {
|
||||
case Opt_gc_background:
|
||||
name = match_strdup(&args[0]);
|
||||
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
if (!strncmp(name, "on", 2))
|
||||
set_opt(sbi, BG_GC);
|
||||
else if (!strncmp(name, "off", 3))
|
||||
clear_opt(sbi, BG_GC);
|
||||
else {
|
||||
kfree(name);
|
||||
return -EINVAL;
|
||||
}
|
||||
kfree(name);
|
||||
break;
|
||||
case Opt_disable_roll_forward:
|
||||
set_opt(sbi, DISABLE_ROLL_FORWARD);
|
||||
break;
|
||||
case Opt_discard:
|
||||
set_opt(sbi, DISCARD);
|
||||
break;
|
||||
case Opt_noheap:
|
||||
set_opt(sbi, NOHEAP);
|
||||
break;
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
case Opt_nouser_xattr:
|
||||
clear_opt(sbi, XATTR_USER);
|
||||
break;
|
||||
#else
|
||||
case Opt_nouser_xattr:
|
||||
f2fs_msg(sb, KERN_INFO,
|
||||
"nouser_xattr options not supported");
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_F2FS_FS_POSIX_ACL
|
||||
case Opt_noacl:
|
||||
clear_opt(sbi, POSIX_ACL);
|
||||
break;
|
||||
#else
|
||||
case Opt_noacl:
|
||||
f2fs_msg(sb, KERN_INFO, "noacl options not supported");
|
||||
break;
|
||||
#endif
|
||||
case Opt_active_logs:
|
||||
if (args->from && match_int(args, &arg))
|
||||
return -EINVAL;
|
||||
if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE)
|
||||
return -EINVAL;
|
||||
sbi->active_logs = arg;
|
||||
break;
|
||||
case Opt_disable_ext_identify:
|
||||
set_opt(sbi, DISABLE_EXT_IDENTIFY);
|
||||
break;
|
||||
default:
|
||||
f2fs_msg(sb, KERN_ERR,
|
||||
"Unrecognized mount option \"%s\" or missing value",
|
||||
p);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct inode *f2fs_alloc_inode(struct super_block *sb)
|
||||
{
|
||||
struct f2fs_inode_info *fi;
|
||||
@ -225,10 +310,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb);
|
||||
|
||||
if (test_opt(sbi, BG_GC))
|
||||
seq_puts(seq, ",background_gc_on");
|
||||
if (!(root->d_sb->s_flags & MS_RDONLY) && test_opt(sbi, BG_GC))
|
||||
seq_printf(seq, ",background_gc=%s", "on");
|
||||
else
|
||||
seq_puts(seq, ",background_gc_off");
|
||||
seq_printf(seq, ",background_gc=%s", "off");
|
||||
if (test_opt(sbi, DISABLE_ROLL_FORWARD))
|
||||
seq_puts(seq, ",disable_roll_forward");
|
||||
if (test_opt(sbi, DISCARD))
|
||||
@ -255,6 +340,58 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int f2fs_remount(struct super_block *sb, int *flags, char *data)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||
struct f2fs_mount_info org_mount_opt;
|
||||
int err, active_logs;
|
||||
|
||||
/*
|
||||
* Save the old mount options in case we
|
||||
* need to restore them.
|
||||
*/
|
||||
org_mount_opt = sbi->mount_opt;
|
||||
active_logs = sbi->active_logs;
|
||||
|
||||
/* parse mount options */
|
||||
err = parse_options(sb, data);
|
||||
if (err)
|
||||
goto restore_opts;
|
||||
|
||||
/*
|
||||
* Previous and new state of filesystem is RO,
|
||||
* so no point in checking GC conditions.
|
||||
*/
|
||||
if ((sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY))
|
||||
goto skip;
|
||||
|
||||
/*
|
||||
* We stop the GC thread if FS is mounted as RO
|
||||
* or if background_gc = off is passed in mount
|
||||
* option. Also sync the filesystem.
|
||||
*/
|
||||
if ((*flags & MS_RDONLY) || !test_opt(sbi, BG_GC)) {
|
||||
if (sbi->gc_thread) {
|
||||
stop_gc_thread(sbi);
|
||||
f2fs_sync_fs(sb, 1);
|
||||
}
|
||||
} else if (test_opt(sbi, BG_GC) && !sbi->gc_thread) {
|
||||
err = start_gc_thread(sbi);
|
||||
if (err)
|
||||
goto restore_opts;
|
||||
}
|
||||
skip:
|
||||
/* Update the POSIXACL Flag */
|
||||
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
|
||||
(test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
|
||||
return 0;
|
||||
|
||||
restore_opts:
|
||||
sbi->mount_opt = org_mount_opt;
|
||||
sbi->active_logs = active_logs;
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct super_operations f2fs_sops = {
|
||||
.alloc_inode = f2fs_alloc_inode,
|
||||
.drop_inode = f2fs_drop_inode,
|
||||
@ -268,6 +405,7 @@ static struct super_operations f2fs_sops = {
|
||||
.freeze_fs = f2fs_freeze,
|
||||
.unfreeze_fs = f2fs_unfreeze,
|
||||
.statfs = f2fs_statfs,
|
||||
.remount_fs = f2fs_remount,
|
||||
};
|
||||
|
||||
static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
|
||||
@ -315,79 +453,6 @@ static const struct export_operations f2fs_export_ops = {
|
||||
.get_parent = f2fs_get_parent,
|
||||
};
|
||||
|
||||
static int parse_options(struct super_block *sb, char *options)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
char *p;
|
||||
int arg = 0;
|
||||
|
||||
if (!options)
|
||||
return 0;
|
||||
|
||||
while ((p = strsep(&options, ",")) != NULL) {
|
||||
int token;
|
||||
if (!*p)
|
||||
continue;
|
||||
/*
|
||||
* Initialize args struct so we know whether arg was
|
||||
* found; some options take optional arguments.
|
||||
*/
|
||||
args[0].to = args[0].from = NULL;
|
||||
token = match_token(p, f2fs_tokens, args);
|
||||
|
||||
switch (token) {
|
||||
case Opt_gc_background_off:
|
||||
clear_opt(sbi, BG_GC);
|
||||
break;
|
||||
case Opt_disable_roll_forward:
|
||||
set_opt(sbi, DISABLE_ROLL_FORWARD);
|
||||
break;
|
||||
case Opt_discard:
|
||||
set_opt(sbi, DISCARD);
|
||||
break;
|
||||
case Opt_noheap:
|
||||
set_opt(sbi, NOHEAP);
|
||||
break;
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
case Opt_nouser_xattr:
|
||||
clear_opt(sbi, XATTR_USER);
|
||||
break;
|
||||
#else
|
||||
case Opt_nouser_xattr:
|
||||
f2fs_msg(sb, KERN_INFO,
|
||||
"nouser_xattr options not supported");
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_F2FS_FS_POSIX_ACL
|
||||
case Opt_noacl:
|
||||
clear_opt(sbi, POSIX_ACL);
|
||||
break;
|
||||
#else
|
||||
case Opt_noacl:
|
||||
f2fs_msg(sb, KERN_INFO, "noacl options not supported");
|
||||
break;
|
||||
#endif
|
||||
case Opt_active_logs:
|
||||
if (args->from && match_int(args, &arg))
|
||||
return -EINVAL;
|
||||
if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE)
|
||||
return -EINVAL;
|
||||
sbi->active_logs = arg;
|
||||
break;
|
||||
case Opt_disable_ext_identify:
|
||||
set_opt(sbi, DISABLE_EXT_IDENTIFY);
|
||||
break;
|
||||
default:
|
||||
f2fs_msg(sb, KERN_ERR,
|
||||
"Unrecognized mount option \"%s\" or missing value",
|
||||
p);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static loff_t max_file_size(unsigned bits)
|
||||
{
|
||||
loff_t result = ADDRS_PER_INODE;
|
||||
@ -686,10 +751,16 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
"Cannot recover all fsync data errno=%ld", err);
|
||||
}
|
||||
|
||||
/* After POR, we can run background GC thread */
|
||||
err = start_gc_thread(sbi);
|
||||
if (err)
|
||||
goto fail;
|
||||
/*
|
||||
* If filesystem is not mounted as read-only then
|
||||
* do start the gc_thread.
|
||||
*/
|
||||
if (!(sb->s_flags & MS_RDONLY)) {
|
||||
/* After POR, we can run background GC thread.*/
|
||||
err = start_gc_thread(sbi);
|
||||
if (err)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = f2fs_build_stats(sbi);
|
||||
if (err)
|
||||
|
Loading…
Reference in New Issue
Block a user