NFS: when we mount with the "nolock" flag we need to use local locking. Signed-off-by: Trond Myklebust --- file.c | 50 +++++++++++++++++++++++++++++--------------------- inode.c | 23 +++++++++++++++-------- 2 files changed, 44 insertions(+), 29 deletions(-) Index: linux-2.6.10-rc1/fs/nfs/file.c =================================================================== --- linux-2.6.10-rc1.orig/fs/nfs/file.c 2004-10-27 14:10:59.000000000 -0400 +++ linux-2.6.10-rc1/fs/nfs/file.c 2004-10-27 18:57:09.000000000 -0400 @@ -295,10 +295,19 @@ out_swapfile: static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) { struct inode *inode = filp->f_mapping->host; - int status; + int status = 0; lock_kernel(); - status = NFS_PROTO(inode)->lock(filp, cmd, fl); + /* Use local locking if mounted with "-onolock" */ + if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) + status = NFS_PROTO(inode)->lock(filp, cmd, fl); + else { + struct file_lock *cfl = posix_test_lock(filp, fl); + if (cfl != NULL) { + memcpy(fl, cfl, sizeof(*fl)); + fl->fl_type = F_UNLCK; + } + } unlock_kernel(); return status; } @@ -325,7 +334,11 @@ static int do_unlk(struct file *filp, in * still need to complete the unlock. */ lock_kernel(); - status = NFS_PROTO(inode)->lock(filp, cmd, fl); + /* Use local locking if mounted with "-onolock" */ + if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) + status = NFS_PROTO(inode)->lock(filp, cmd, fl); + else + status = posix_lock_file_wait(filp, fl); rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset); return status; } @@ -351,15 +364,19 @@ static int do_setlk(struct file *filp, i return status; lock_kernel(); - status = NFS_PROTO(inode)->lock(filp, cmd, fl); - /* If we were signalled we still need to ensure that - * we clean up any state on the server. We therefore - * record the lock call as having succeeded in order to - * ensure that locks_remove_posix() cleans it out when - * the process exits. - */ - if (status == -EINTR || status == -ERESTARTSYS) - posix_lock_file(filp, fl); + /* Use local locking if mounted with "-onolock" */ + if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) { + status = NFS_PROTO(inode)->lock(filp, cmd, fl); + /* If we were signalled we still need to ensure that + * we clean up any state on the server. We therefore + * record the lock call as having succeeded in order to + * ensure that locks_remove_posix() cleans it out when + * the process exits. + */ + if (status == -EINTR || status == -ERESTARTSYS) + posix_lock_file(filp, fl); + } else + status = posix_lock_file_wait(filp, fl); unlock_kernel(); if (status < 0) return status; @@ -396,15 +413,6 @@ nfs_lock(struct file *filp, int cmd, str if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return -ENOLCK; - if (NFS_PROTO(inode)->version != 4) { - /* Fake OK code if mounted without NLM support */ - if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) { - if (IS_GETLK(cmd)) - return LOCK_USE_CLNT; - return 0; - } - } - /* * No BSD flocks over NFS allowed. * Note: we could try to fake a POSIX lock request here by Index: linux-2.6.10-rc1/fs/nfs/inode.c =================================================================== --- linux-2.6.10-rc1.orig/fs/nfs/inode.c 2004-10-27 18:57:09.000000000 -0400 +++ linux-2.6.10-rc1/fs/nfs/inode.c 2004-10-27 19:07:37.242947814 -0400 @@ -1449,8 +1449,6 @@ static void nfs_kill_super(struct super_ kill_anon_super(s); - nfs4_renewd_prepare_shutdown(server); - if (server->client != NULL && !IS_ERR(server->client)) rpc_shutdown_client(server->client); if (server->client_sys != NULL && !IS_ERR(server->client_sys)) @@ -1461,8 +1459,6 @@ static void nfs_kill_super(struct super_ rpciod_down(); /* release rpciod */ - destroy_nfsv4_state(server); - if (server->hostname != NULL) kfree(server->hostname); kfree(server); @@ -1543,9 +1539,6 @@ static int nfs4_fill_super(struct super_ server->wsize = nfs_block_size(data->wsize, NULL); server->flags = data->flags & NFS_MOUNT_FLAGMASK; - /* NFSv4 doesn't use NLM locking */ - server->flags |= NFS_MOUNT_NONLM; - server->acregmin = data->acregmin*HZ; server->acregmax = data->acregmax*HZ; server->acdirmin = data->acdirmin*HZ; @@ -1790,8 +1783,22 @@ out_free: static void nfs4_kill_super(struct super_block *sb) { + struct nfs_server *server = NFS_SB(sb); + nfs_return_all_delegations(sb); - nfs_kill_super(sb); + kill_anon_super(sb); + + nfs4_renewd_prepare_shutdown(server); + + if (server->client != NULL && !IS_ERR(server->client)) + rpc_shutdown_client(server->client); + rpciod_down(); /* release rpciod */ + + destroy_nfsv4_state(server); + + if (server->hostname != NULL) + kfree(server->hostname); + kfree(server); } static struct file_system_type nfs4_fs_type = {