From 6c6c1d63c243025956f061e67fff3a615aa0f6be Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 25 Apr 2019 14:26:52 +0100 Subject: afs: Provide mount-time configurable byte-range file locking emulation Provide byte-range file locking emulation that can be configured at mount time to one of four modes: (1) flock=local. Locking is done locally only and no reference is made to the server. (2) flock=openafs. Byte-range locking is done locally only; whole-file locking is done with reference to the server. Whole-file locks cannot be upgraded unless the client holds an exclusive lock. (3) flock=strict. Byte-range and whole-file locking both require a sufficient whole-file lock on the server. (4) flock=write. As strict, but the client always gets an exclusive whole-file lock on the server. Signed-off-by: David Howells --- fs/afs/super.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'fs/afs/super.c') diff --git a/fs/afs/super.c b/fs/afs/super.c index ce85ae61f12d..18334fa1a0d2 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -67,19 +67,30 @@ static atomic_t afs_count_active_inodes; enum afs_param { Opt_autocell, Opt_dyn, + Opt_flock, Opt_source, }; static const struct fs_parameter_spec afs_param_specs[] = { fsparam_flag ("autocell", Opt_autocell), fsparam_flag ("dyn", Opt_dyn), + fsparam_enum ("flock", Opt_flock), fsparam_string("source", Opt_source), {} }; +static const struct fs_parameter_enum afs_param_enums[] = { + { Opt_flock, "local", afs_flock_mode_local }, + { Opt_flock, "openafs", afs_flock_mode_openafs }, + { Opt_flock, "strict", afs_flock_mode_strict }, + { Opt_flock, "write", afs_flock_mode_write }, + {} +}; + static const struct fs_parameter_description afs_fs_parameters = { .name = "kAFS", .specs = afs_param_specs, + .enums = afs_param_enums, }; /* @@ -182,11 +193,22 @@ static int afs_show_devname(struct seq_file *m, struct dentry *root) static int afs_show_options(struct seq_file *m, struct dentry *root) { struct afs_super_info *as = AFS_FS_S(root->d_sb); + const char *p = NULL; if (as->dyn_root) seq_puts(m, ",dyn"); if (test_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(d_inode(root))->flags)) seq_puts(m, ",autocell"); + switch (as->flock_mode) { + case afs_flock_mode_unset: break; + case afs_flock_mode_local: p = "local"; break; + case afs_flock_mode_openafs: p = "openafs"; break; + case afs_flock_mode_strict: p = "strict"; break; + case afs_flock_mode_write: p = "write"; break; + } + if (p) + seq_printf(m, ",flock=%s", p); + return 0; } @@ -315,6 +337,10 @@ static int afs_parse_param(struct fs_context *fc, struct fs_parameter *param) ctx->dyn_root = true; break; + case Opt_flock: + ctx->flock_mode = result.uint_32; + break; + default: return -EINVAL; } @@ -466,6 +492,7 @@ static struct afs_super_info *afs_alloc_sbi(struct fs_context *fc) as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); if (as) { as->net_ns = get_net(fc->net_ns); + as->flock_mode = ctx->flock_mode; if (ctx->dyn_root) { as->dyn_root = true; } else { -- cgit v1.2.3