aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorSuresh Jayaraman <sjayaraman@suse.de>2010-09-23 08:55:58 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-09-23 08:55:58 -0400
commit5eebde23223aeb0ad2d9e3be6590ff8bbfab0fc2 (patch)
tree7cfabe0191855550292b0a0c9b317315dffb2a50 /fs/nfs/super.c
parent63185942c5f138c62de16b4cbc7eee494a58fea8 (diff)
nfs: introduce mount option '-olocal_lock' to make locks local
NFS clients since 2.6.12 support flock locks by emulating fcntl byte-range locks. Due to this, some windows applications which seem to use both flock (share mode lock mapped as flock by Samba) and fcntl locks sequentially on the same file, can't lock as they falsely assume the file is already locked. The problem was reported on a setup with windows clients accessing excel files on a Samba exported share which is originally a NFS mount from a NetApp filer. Older NFS clients (< 2.6.12) did not see this problem as flock locks were considered local. To support legacy flock behavior, this patch adds a mount option "-olocal_lock=" which can take the following values: 'none' - Neither flock locks nor POSIX locks are local 'flock' - flock locks are local 'posix' - fcntl/POSIX locks are local 'all' - Both flock locks and POSIX locks are local Testing: - This patch was tested by using -olocal_lock option with different values and the NLM calls were noted from the network packet captured. 'none' - NLM calls were seen during both flock() and fcntl(), flock lock was granted, fcntl was denied 'flock' - no NLM calls for flock(), NLM call was seen for fcntl(), granted 'posix' - NLM call was seen for flock() - granted, no NLM call for fcntl() 'all' - no NLM calls were seen during both flock() and fcntl() - No bugs were seen during NFSv4 locking/unlocking in general and NFSv4 reboot recovery. Cc: Neil Brown <neilb@suse.de> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ec3966e4706b..2e866d86c220 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -100,6 +100,7 @@ enum {
100 Opt_addr, Opt_mountaddr, Opt_clientaddr, 100 Opt_addr, Opt_mountaddr, Opt_clientaddr,
101 Opt_lookupcache, 101 Opt_lookupcache,
102 Opt_fscache_uniq, 102 Opt_fscache_uniq,
103 Opt_local_lock,
103 104
104 /* Special mount options */ 105 /* Special mount options */
105 Opt_userspace, Opt_deprecated, Opt_sloppy, 106 Opt_userspace, Opt_deprecated, Opt_sloppy,
@@ -171,6 +172,7 @@ static const match_table_t nfs_mount_option_tokens = {
171 172
172 { Opt_lookupcache, "lookupcache=%s" }, 173 { Opt_lookupcache, "lookupcache=%s" },
173 { Opt_fscache_uniq, "fsc=%s" }, 174 { Opt_fscache_uniq, "fsc=%s" },
175 { Opt_local_lock, "local_lock=%s" },
174 176
175 { Opt_err, NULL } 177 { Opt_err, NULL }
176}; 178};
@@ -236,6 +238,22 @@ static match_table_t nfs_lookupcache_tokens = {
236 { Opt_lookupcache_err, NULL } 238 { Opt_lookupcache_err, NULL }
237}; 239};
238 240
241enum {
242 Opt_local_lock_all, Opt_local_lock_flock, Opt_local_lock_posix,
243 Opt_local_lock_none,
244
245 Opt_local_lock_err
246};
247
248static match_table_t nfs_local_lock_tokens = {
249 { Opt_local_lock_all, "all" },
250 { Opt_local_lock_flock, "flock" },
251 { Opt_local_lock_posix, "posix" },
252 { Opt_local_lock_none, "none" },
253
254 { Opt_local_lock_err, NULL }
255};
256
239 257
240static void nfs_umount_begin(struct super_block *); 258static void nfs_umount_begin(struct super_block *);
241static int nfs_statfs(struct dentry *, struct kstatfs *); 259static int nfs_statfs(struct dentry *, struct kstatfs *);
@@ -1009,9 +1027,13 @@ static int nfs_parse_mount_options(char *raw,
1009 break; 1027 break;
1010 case Opt_lock: 1028 case Opt_lock:
1011 mnt->flags &= ~NFS_MOUNT_NONLM; 1029 mnt->flags &= ~NFS_MOUNT_NONLM;
1030 mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
1031 NFS_MOUNT_LOCAL_FCNTL);
1012 break; 1032 break;
1013 case Opt_nolock: 1033 case Opt_nolock:
1014 mnt->flags |= NFS_MOUNT_NONLM; 1034 mnt->flags |= NFS_MOUNT_NONLM;
1035 mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
1036 NFS_MOUNT_LOCAL_FCNTL);
1015 break; 1037 break;
1016 case Opt_v2: 1038 case Opt_v2:
1017 mnt->flags &= ~NFS_MOUNT_VER3; 1039 mnt->flags &= ~NFS_MOUNT_VER3;
@@ -1412,6 +1434,34 @@ static int nfs_parse_mount_options(char *raw,
1412 mnt->fscache_uniq = string; 1434 mnt->fscache_uniq = string;
1413 mnt->options |= NFS_OPTION_FSCACHE; 1435 mnt->options |= NFS_OPTION_FSCACHE;
1414 break; 1436 break;
1437 case Opt_local_lock:
1438 string = match_strdup(args);
1439 if (string == NULL)
1440 goto out_nomem;
1441 token = match_token(string, nfs_local_lock_tokens,
1442 args);
1443 kfree(string);
1444 switch (token) {
1445 case Opt_local_lock_all:
1446 mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
1447 NFS_MOUNT_LOCAL_FCNTL);
1448 break;
1449 case Opt_local_lock_flock:
1450 mnt->flags |= NFS_MOUNT_LOCAL_FLOCK;
1451 break;
1452 case Opt_local_lock_posix:
1453 mnt->flags |= NFS_MOUNT_LOCAL_FCNTL;
1454 break;
1455 case Opt_local_lock_none:
1456 mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
1457 NFS_MOUNT_LOCAL_FCNTL);
1458 break;
1459 default:
1460 dfprintk(MOUNT, "NFS: invalid "
1461 "local_lock argument\n");
1462 return 0;
1463 };
1464 break;
1415 1465
1416 /* 1466 /*
1417 * Special options 1467 * Special options
@@ -1817,6 +1867,12 @@ static int nfs_validate_mount_data(void *options,
1817 if (!args->nfs_server.hostname) 1867 if (!args->nfs_server.hostname)
1818 goto out_nomem; 1868 goto out_nomem;
1819 1869
1870 if (!(data->flags & NFS_MOUNT_NONLM))
1871 args->flags &= ~(NFS_MOUNT_LOCAL_FLOCK|
1872 NFS_MOUNT_LOCAL_FCNTL);
1873 else
1874 args->flags |= (NFS_MOUNT_LOCAL_FLOCK|
1875 NFS_MOUNT_LOCAL_FCNTL);
1820 /* 1876 /*
1821 * The legacy version 6 binary mount data from userspace has a 1877 * The legacy version 6 binary mount data from userspace has a
1822 * field used only to transport selinux information into the 1878 * field used only to transport selinux information into the
@@ -2433,7 +2489,8 @@ static void nfs4_fill_super(struct super_block *sb)
2433 2489
2434static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) 2490static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
2435{ 2491{
2436 args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3); 2492 args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
2493 NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
2437} 2494}
2438 2495
2439static int nfs4_validate_text_mount_data(void *options, 2496static int nfs4_validate_text_mount_data(void *options,