aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/delegation.c41
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/dir.c3
-rw-r--r--fs/nfs/direct.c10
-rw-r--r--fs/nfs/inode.c22
-rw-r--r--fs/nfs/nfs4_fs.h4
-rw-r--r--fs/nfs/nfs4proc.c120
-rw-r--r--fs/nfs/nfs4state.c94
-rw-r--r--fs/nfs/read.c4
-rw-r--r--fs/nfs/unlink.c3
-rw-r--r--fs/nfs/write.c14
11 files changed, 174 insertions, 142 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 44135af9894c..618a327027b3 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -31,11 +31,42 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
31 kfree(delegation); 31 kfree(delegation);
32} 32}
33 33
34static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
35{
36 struct inode *inode = state->inode;
37 struct file_lock *fl;
38 int status;
39
40 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
41 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
42 continue;
43 if ((struct nfs_open_context *)fl->fl_file->private_data != ctx)
44 continue;
45 status = nfs4_lock_delegation_recall(state, fl);
46 if (status >= 0)
47 continue;
48 switch (status) {
49 default:
50 printk(KERN_ERR "%s: unhandled error %d.\n",
51 __FUNCTION__, status);
52 case -NFS4ERR_EXPIRED:
53 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
54 case -NFS4ERR_STALE_CLIENTID:
55 nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs4_state);
56 goto out_err;
57 }
58 }
59 return 0;
60out_err:
61 return status;
62}
63
34static void nfs_delegation_claim_opens(struct inode *inode) 64static void nfs_delegation_claim_opens(struct inode *inode)
35{ 65{
36 struct nfs_inode *nfsi = NFS_I(inode); 66 struct nfs_inode *nfsi = NFS_I(inode);
37 struct nfs_open_context *ctx; 67 struct nfs_open_context *ctx;
38 struct nfs4_state *state; 68 struct nfs4_state *state;
69 int err;
39 70
40again: 71again:
41 spin_lock(&inode->i_lock); 72 spin_lock(&inode->i_lock);
@@ -47,9 +78,12 @@ again:
47 continue; 78 continue;
48 get_nfs_open_context(ctx); 79 get_nfs_open_context(ctx);
49 spin_unlock(&inode->i_lock); 80 spin_unlock(&inode->i_lock);
50 if (nfs4_open_delegation_recall(ctx->dentry, state) < 0) 81 err = nfs4_open_delegation_recall(ctx->dentry, state);
51 return; 82 if (err >= 0)
83 err = nfs_delegation_claim_locks(ctx, state);
52 put_nfs_open_context(ctx); 84 put_nfs_open_context(ctx);
85 if (err != 0)
86 return;
53 goto again; 87 goto again;
54 } 88 }
55 spin_unlock(&inode->i_lock); 89 spin_unlock(&inode->i_lock);
@@ -115,8 +149,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
115 } 149 }
116 } 150 }
117 spin_unlock(&clp->cl_lock); 151 spin_unlock(&clp->cl_lock);
118 if (delegation != NULL) 152 kfree(delegation);
119 kfree(delegation);
120 return status; 153 return status;
121} 154}
122 155
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 8017846b561f..2fcc30de924b 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -38,6 +38,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
38/* NFSv4 delegation-related procedures */ 38/* NFSv4 delegation-related procedures */
39int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); 39int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
40int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state); 40int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
41int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
41 42
42static inline int nfs_have_delegation(struct inode *inode, int flags) 43static inline int nfs_have_delegation(struct inode *inode, int flags)
43{ 44{
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8272ed3fc707..7370583b61e5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1257,6 +1257,9 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
1257 sprintf(silly, ".nfs%*.*lx", 1257 sprintf(silly, ".nfs%*.*lx",
1258 i_inosize, i_inosize, dentry->d_inode->i_ino); 1258 i_inosize, i_inosize, dentry->d_inode->i_ino);
1259 1259
1260 /* Return delegation in anticipation of the rename */
1261 nfs_inode_return_delegation(dentry->d_inode);
1262
1260 sdentry = NULL; 1263 sdentry = NULL;
1261 do { 1264 do {
1262 char *suffix = silly + slen - countersize; 1265 char *suffix = silly + slen - countersize;
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 6537f2c4ae44..b497c71384e8 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -655,7 +655,6 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
655 struct file *file = iocb->ki_filp; 655 struct file *file = iocb->ki_filp;
656 struct nfs_open_context *ctx = 656 struct nfs_open_context *ctx =
657 (struct nfs_open_context *) file->private_data; 657 (struct nfs_open_context *) file->private_data;
658 struct dentry *dentry = file->f_dentry;
659 struct address_space *mapping = file->f_mapping; 658 struct address_space *mapping = file->f_mapping;
660 struct inode *inode = mapping->host; 659 struct inode *inode = mapping->host;
661 struct iovec iov = { 660 struct iovec iov = {
@@ -664,7 +663,8 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
664 }; 663 };
665 664
666 dprintk("nfs: direct read(%s/%s, %lu@%lu)\n", 665 dprintk("nfs: direct read(%s/%s, %lu@%lu)\n",
667 dentry->d_parent->d_name.name, dentry->d_name.name, 666 file->f_dentry->d_parent->d_name.name,
667 file->f_dentry->d_name.name,
668 (unsigned long) count, (unsigned long) pos); 668 (unsigned long) count, (unsigned long) pos);
669 669
670 if (!is_sync_kiocb(iocb)) 670 if (!is_sync_kiocb(iocb))
@@ -730,7 +730,6 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
730 struct file *file = iocb->ki_filp; 730 struct file *file = iocb->ki_filp;
731 struct nfs_open_context *ctx = 731 struct nfs_open_context *ctx =
732 (struct nfs_open_context *) file->private_data; 732 (struct nfs_open_context *) file->private_data;
733 struct dentry *dentry = file->f_dentry;
734 struct address_space *mapping = file->f_mapping; 733 struct address_space *mapping = file->f_mapping;
735 struct inode *inode = mapping->host; 734 struct inode *inode = mapping->host;
736 struct iovec iov = { 735 struct iovec iov = {
@@ -739,8 +738,9 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
739 }; 738 };
740 739
741 dfprintk(VFS, "nfs: direct write(%s/%s(%ld), %lu@%lu)\n", 740 dfprintk(VFS, "nfs: direct write(%s/%s(%ld), %lu@%lu)\n",
742 dentry->d_parent->d_name.name, dentry->d_name.name, 741 file->f_dentry->d_parent->d_name.name,
743 inode->i_ino, (unsigned long) count, (unsigned long) pos); 742 file->f_dentry->d_name.name, inode->i_ino,
743 (unsigned long) count, (unsigned long) pos);
744 744
745 if (!is_sync_kiocb(iocb)) 745 if (!is_sync_kiocb(iocb))
746 goto out; 746 goto out;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index fc0f12ba89cc..6391d8964214 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1009,13 +1009,18 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
1009 spin_unlock(&inode->i_lock); 1009 spin_unlock(&inode->i_lock);
1010} 1010}
1011 1011
1012struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode) 1012/*
1013 * Given an inode, search for an open context with the desired characteristics
1014 */
1015struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode)
1013{ 1016{
1014 struct nfs_inode *nfsi = NFS_I(inode); 1017 struct nfs_inode *nfsi = NFS_I(inode);
1015 struct nfs_open_context *pos, *ctx = NULL; 1018 struct nfs_open_context *pos, *ctx = NULL;
1016 1019
1017 spin_lock(&inode->i_lock); 1020 spin_lock(&inode->i_lock);
1018 list_for_each_entry(pos, &nfsi->open_files, list) { 1021 list_for_each_entry(pos, &nfsi->open_files, list) {
1022 if (cred != NULL && pos->cred != cred)
1023 continue;
1019 if ((pos->mode & mode) == mode) { 1024 if ((pos->mode & mode) == mode) {
1020 ctx = get_nfs_open_context(pos); 1025 ctx = get_nfs_open_context(pos);
1021 break; 1026 break;
@@ -1683,8 +1688,7 @@ static void nfs_kill_super(struct super_block *s)
1683 1688
1684 rpciod_down(); /* release rpciod */ 1689 rpciod_down(); /* release rpciod */
1685 1690
1686 if (server->hostname != NULL) 1691 kfree(server->hostname);
1687 kfree(server->hostname);
1688 kfree(server); 1692 kfree(server);
1689} 1693}
1690 1694
@@ -1903,8 +1907,7 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1903 return ERR_PTR(-ENOMEM); 1907 return ERR_PTR(-ENOMEM);
1904 } 1908 }
1905 if (copy_from_user(dst, src->data, maxlen)) { 1909 if (copy_from_user(dst, src->data, maxlen)) {
1906 if (p != NULL) 1910 kfree(p);
1907 kfree(p);
1908 return ERR_PTR(-EFAULT); 1911 return ERR_PTR(-EFAULT);
1909 } 1912 }
1910 dst[maxlen] = '\0'; 1913 dst[maxlen] = '\0';
@@ -1995,10 +1998,8 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1995out_err: 1998out_err:
1996 s = (struct super_block *)p; 1999 s = (struct super_block *)p;
1997out_free: 2000out_free:
1998 if (server->mnt_path) 2001 kfree(server->mnt_path);
1999 kfree(server->mnt_path); 2002 kfree(server->hostname);
2000 if (server->hostname)
2001 kfree(server->hostname);
2002 kfree(server); 2003 kfree(server);
2003 return s; 2004 return s;
2004} 2005}
@@ -2018,8 +2019,7 @@ static void nfs4_kill_super(struct super_block *sb)
2018 2019
2019 destroy_nfsv4_state(server); 2020 destroy_nfsv4_state(server);
2020 2021
2021 if (server->hostname != NULL) 2022 kfree(server->hostname);
2022 kfree(server->hostname);
2023 kfree(server); 2023 kfree(server);
2024} 2024}
2025 2025
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 78a53f5a9f18..b7f262dcb6e3 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -214,7 +214,7 @@ extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
214extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); 214extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
215extern int nfs4_proc_async_renew(struct nfs4_client *); 215extern int nfs4_proc_async_renew(struct nfs4_client *);
216extern int nfs4_proc_renew(struct nfs4_client *); 216extern int nfs4_proc_renew(struct nfs4_client *);
217extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode); 217extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
218extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); 218extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
219extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); 219extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
220 220
@@ -247,7 +247,7 @@ extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
247extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); 247extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
248extern void nfs4_put_open_state(struct nfs4_state *); 248extern void nfs4_put_open_state(struct nfs4_state *);
249extern void nfs4_close_state(struct nfs4_state *, mode_t); 249extern void nfs4_close_state(struct nfs4_state *, mode_t);
250extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); 250extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
251extern void nfs4_schedule_state_recovery(struct nfs4_client *); 251extern void nfs4_schedule_state_recovery(struct nfs4_client *);
252extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 252extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
253extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); 253extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 933e13b383f8..21482b2518f6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -214,16 +214,15 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
214 struct inode *inode = state->inode; 214 struct inode *inode = state->inode;
215 215
216 open_flags &= (FMODE_READ|FMODE_WRITE); 216 open_flags &= (FMODE_READ|FMODE_WRITE);
217 /* Protect against nfs4_find_state() */ 217 /* Protect against nfs4_find_state_byowner() */
218 spin_lock(&state->owner->so_lock); 218 spin_lock(&state->owner->so_lock);
219 spin_lock(&inode->i_lock); 219 spin_lock(&inode->i_lock);
220 state->state |= open_flags; 220 memcpy(&state->stateid, stateid, sizeof(state->stateid));
221 /* NB! List reordering - see the reclaim code for why. */ 221 if ((open_flags & FMODE_WRITE))
222 if ((open_flags & FMODE_WRITE) && 0 == state->nwriters++) 222 state->nwriters++;
223 list_move(&state->open_states, &state->owner->so_states);
224 if (open_flags & FMODE_READ) 223 if (open_flags & FMODE_READ)
225 state->nreaders++; 224 state->nreaders++;
226 memcpy(&state->stateid, stateid, sizeof(state->stateid)); 225 nfs4_state_set_mode_locked(state, state->state | open_flags);
227 spin_unlock(&inode->i_lock); 226 spin_unlock(&inode->i_lock);
228 spin_unlock(&state->owner->so_lock); 227 spin_unlock(&state->owner->so_lock);
229} 228}
@@ -896,7 +895,6 @@ static void nfs4_close_done(struct rpc_task *task)
896 break; 895 break;
897 case -NFS4ERR_STALE_STATEID: 896 case -NFS4ERR_STALE_STATEID:
898 case -NFS4ERR_EXPIRED: 897 case -NFS4ERR_EXPIRED:
899 state->state = calldata->arg.open_flags;
900 nfs4_schedule_state_recovery(server->nfs4_state); 898 nfs4_schedule_state_recovery(server->nfs4_state);
901 break; 899 break;
902 default: 900 default:
@@ -906,7 +904,6 @@ static void nfs4_close_done(struct rpc_task *task)
906 } 904 }
907 } 905 }
908 nfs_refresh_inode(calldata->inode, calldata->res.fattr); 906 nfs_refresh_inode(calldata->inode, calldata->res.fattr);
909 state->state = calldata->arg.open_flags;
910 nfs4_free_closedata(calldata); 907 nfs4_free_closedata(calldata);
911} 908}
912 909
@@ -920,24 +917,26 @@ static void nfs4_close_begin(struct rpc_task *task)
920 .rpc_resp = &calldata->res, 917 .rpc_resp = &calldata->res,
921 .rpc_cred = state->owner->so_cred, 918 .rpc_cred = state->owner->so_cred,
922 }; 919 };
923 int mode = 0; 920 int mode = 0, old_mode;
924 int status; 921 int status;
925 922
926 status = nfs_wait_on_sequence(calldata->arg.seqid, task); 923 status = nfs_wait_on_sequence(calldata->arg.seqid, task);
927 if (status != 0) 924 if (status != 0)
928 return; 925 return;
929 /* Don't reorder reads */
930 smp_rmb();
931 /* Recalculate the new open mode in case someone reopened the file 926 /* Recalculate the new open mode in case someone reopened the file
932 * while we were waiting in line to be scheduled. 927 * while we were waiting in line to be scheduled.
933 */ 928 */
934 if (state->nreaders != 0) 929 spin_lock(&state->owner->so_lock);
935 mode |= FMODE_READ; 930 spin_lock(&calldata->inode->i_lock);
936 if (state->nwriters != 0) 931 mode = old_mode = state->state;
937 mode |= FMODE_WRITE; 932 if (state->nreaders == 0)
938 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) 933 mode &= ~FMODE_READ;
939 state->state = mode; 934 if (state->nwriters == 0)
940 if (mode == state->state) { 935 mode &= ~FMODE_WRITE;
936 nfs4_state_set_mode_locked(state, mode);
937 spin_unlock(&calldata->inode->i_lock);
938 spin_unlock(&state->owner->so_lock);
939 if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) {
941 nfs4_free_closedata(calldata); 940 nfs4_free_closedata(calldata);
942 task->tk_exit = NULL; 941 task->tk_exit = NULL;
943 rpc_exit(task, 0); 942 rpc_exit(task, 0);
@@ -961,7 +960,7 @@ static void nfs4_close_begin(struct rpc_task *task)
961 * 960 *
962 * NOTE: Caller must be holding the sp->so_owner semaphore! 961 * NOTE: Caller must be holding the sp->so_owner semaphore!
963 */ 962 */
964int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) 963int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
965{ 964{
966 struct nfs_server *server = NFS_SERVER(inode); 965 struct nfs_server *server = NFS_SERVER(inode);
967 struct nfs4_closedata *calldata; 966 struct nfs4_closedata *calldata;
@@ -1275,7 +1274,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1275{ 1274{
1276 struct rpc_cred *cred; 1275 struct rpc_cred *cred;
1277 struct inode *inode = dentry->d_inode; 1276 struct inode *inode = dentry->d_inode;
1278 struct nfs4_state *state; 1277 struct nfs_open_context *ctx;
1278 struct nfs4_state *state = NULL;
1279 int status; 1279 int status;
1280 1280
1281 nfs_fattr_init(fattr); 1281 nfs_fattr_init(fattr);
@@ -1283,22 +1283,18 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1283 cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); 1283 cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
1284 if (IS_ERR(cred)) 1284 if (IS_ERR(cred))
1285 return PTR_ERR(cred); 1285 return PTR_ERR(cred);
1286 /* Search for an existing WRITE delegation first */ 1286
1287 state = nfs4_open_delegated(inode, FMODE_WRITE, cred); 1287 /* Search for an existing open(O_WRITE) file */
1288 if (!IS_ERR(state)) { 1288 ctx = nfs_find_open_context(inode, cred, FMODE_WRITE);
1289 /* NB: nfs4_open_delegated() bumps the inode->i_count */ 1289 if (ctx != NULL)
1290 iput(inode); 1290 state = ctx->state;
1291 } else {
1292 /* Search for an existing open(O_WRITE) stateid */
1293 state = nfs4_find_state(inode, cred, FMODE_WRITE);
1294 }
1295 1291
1296 status = nfs4_do_setattr(NFS_SERVER(inode), fattr, 1292 status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
1297 NFS_FH(inode), sattr, state); 1293 NFS_FH(inode), sattr, state);
1298 if (status == 0) 1294 if (status == 0)
1299 nfs_setattr_update_inode(inode, sattr); 1295 nfs_setattr_update_inode(inode, sattr);
1300 if (state != NULL) 1296 if (ctx != NULL)
1301 nfs4_close_state(state, FMODE_WRITE); 1297 put_nfs_open_context(ctx);
1302 put_rpccred(cred); 1298 put_rpccred(cred);
1303 return status; 1299 return status;
1304} 1300}
@@ -2599,12 +2595,10 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct
2599 case -NFS4ERR_GRACE: 2595 case -NFS4ERR_GRACE:
2600 case -NFS4ERR_DELAY: 2596 case -NFS4ERR_DELAY:
2601 ret = nfs4_delay(server->client, &exception->timeout); 2597 ret = nfs4_delay(server->client, &exception->timeout);
2602 if (ret == 0) 2598 if (ret != 0)
2603 exception->retry = 1; 2599 break;
2604 break;
2605 case -NFS4ERR_OLD_STATEID: 2600 case -NFS4ERR_OLD_STATEID:
2606 if (ret == 0) 2601 exception->retry = 1;
2607 exception->retry = 1;
2608 } 2602 }
2609 /* We failed to handle the error */ 2603 /* We failed to handle the error */
2610 return nfs4_map_errors(ret); 2604 return nfs4_map_errors(ret);
@@ -2924,6 +2918,10 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
2924 struct nfs4_lock_state *lsp; 2918 struct nfs4_lock_state *lsp;
2925 int status; 2919 int status;
2926 2920
2921 /* Is this a delegated lock? */
2922 if (test_bit(NFS_DELEGATED_STATE, &state->flags))
2923 return do_vfs_lock(request->fl_file, request);
2924
2927 status = nfs4_set_lock_state(state, request); 2925 status = nfs4_set_lock_state(state, request);
2928 if (status != 0) 2926 if (status != 0)
2929 return status; 2927 return status;
@@ -3038,6 +3036,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
3038 struct nfs4_exception exception = { }; 3036 struct nfs4_exception exception = { };
3039 int err; 3037 int err;
3040 3038
3039 /* Cache the lock if possible... */
3040 if (test_bit(NFS_DELEGATED_STATE, &state->flags))
3041 return 0;
3041 do { 3042 do {
3042 err = _nfs4_do_setlk(state, F_SETLK, request, 1); 3043 err = _nfs4_do_setlk(state, F_SETLK, request, 1);
3043 if (err != -NFS4ERR_DELAY) 3044 if (err != -NFS4ERR_DELAY)
@@ -3053,6 +3054,9 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
3053 struct nfs4_exception exception = { }; 3054 struct nfs4_exception exception = { };
3054 int err; 3055 int err;
3055 3056
3057 err = nfs4_set_lock_state(state, request);
3058 if (err != 0)
3059 return err;
3056 do { 3060 do {
3057 err = _nfs4_do_setlk(state, F_SETLK, request, 0); 3061 err = _nfs4_do_setlk(state, F_SETLK, request, 0);
3058 if (err != -NFS4ERR_DELAY) 3062 if (err != -NFS4ERR_DELAY)
@@ -3068,15 +3072,25 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
3068 int status; 3072 int status;
3069 3073
3070 down_read(&clp->cl_sem); 3074 down_read(&clp->cl_sem);
3071 status = nfs4_set_lock_state(state, request); 3075 /* Is this a delegated open? */
3072 if (status == 0) 3076 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
3073 status = _nfs4_do_setlk(state, cmd, request, 0); 3077 /* Yes: cache locks! */
3074 if (status == 0) { 3078 status = do_vfs_lock(request->fl_file, request);
3075 /* Note: we always want to sleep here! */ 3079 /* ...but avoid races with delegation recall... */
3076 request->fl_flags |= FL_SLEEP; 3080 if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags))
3077 if (do_vfs_lock(request->fl_file, request) < 0) 3081 goto out;
3078 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
3079 } 3082 }
3083 status = nfs4_set_lock_state(state, request);
3084 if (status != 0)
3085 goto out;
3086 status = _nfs4_do_setlk(state, cmd, request, 0);
3087 if (status != 0)
3088 goto out;
3089 /* Note: we always want to sleep here! */
3090 request->fl_flags |= FL_SLEEP;
3091 if (do_vfs_lock(request->fl_file, request) < 0)
3092 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
3093out:
3080 up_read(&clp->cl_sem); 3094 up_read(&clp->cl_sem);
3081 return status; 3095 return status;
3082} 3096}
@@ -3130,6 +3144,24 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
3130 return status; 3144 return status;
3131} 3145}
3132 3146
3147int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
3148{
3149 struct nfs_server *server = NFS_SERVER(state->inode);
3150 struct nfs4_exception exception = { };
3151 int err;
3152
3153 err = nfs4_set_lock_state(state, fl);
3154 if (err != 0)
3155 goto out;
3156 do {
3157 err = _nfs4_do_setlk(state, F_SETLK, fl, 0);
3158 if (err != -NFS4ERR_DELAY)
3159 break;
3160 err = nfs4_handle_exception(server, err, &exception);
3161 } while (exception.retry);
3162out:
3163 return err;
3164}
3133 3165
3134#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" 3166#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
3135 3167
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 2d5a6a2b9dec..0675f3215e0a 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -69,10 +69,8 @@ init_nfsv4_state(struct nfs_server *server)
69void 69void
70destroy_nfsv4_state(struct nfs_server *server) 70destroy_nfsv4_state(struct nfs_server *server)
71{ 71{
72 if (server->mnt_path) { 72 kfree(server->mnt_path);
73 kfree(server->mnt_path); 73 server->mnt_path = NULL;
74 server->mnt_path = NULL;
75 }
76 if (server->nfs4_state) { 74 if (server->nfs4_state) {
77 nfs4_put_client(server->nfs4_state); 75 nfs4_put_client(server->nfs4_state);
78 server->nfs4_state = NULL; 76 server->nfs4_state = NULL;
@@ -311,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
311 new = NULL; 309 new = NULL;
312 } 310 }
313 spin_unlock(&clp->cl_lock); 311 spin_unlock(&clp->cl_lock);
314 if (new) 312 kfree(new);
315 kfree(new);
316 if (sp != NULL) 313 if (sp != NULL)
317 return sp; 314 return sp;
318 put_rpccred(cred); 315 put_rpccred(cred);
@@ -366,30 +363,21 @@ nfs4_alloc_open_state(void)
366 return state; 363 return state;
367} 364}
368 365
369static struct nfs4_state * 366void
370__nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) 367nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode)
371{ 368{
372 struct nfs_inode *nfsi = NFS_I(inode); 369 if (state->state == mode)
373 struct nfs4_state *state; 370 return;
374 371 /* NB! List reordering - see the reclaim code for why. */
375 mode &= (FMODE_READ|FMODE_WRITE); 372 if ((mode & FMODE_WRITE) != (state->state & FMODE_WRITE)) {
376 list_for_each_entry(state, &nfsi->open_states, inode_states) {
377 if (state->owner->so_cred != cred)
378 continue;
379 if ((mode & FMODE_READ) != 0 && state->nreaders == 0)
380 continue;
381 if ((mode & FMODE_WRITE) != 0 && state->nwriters == 0)
382 continue;
383 if ((state->state & mode) != mode)
384 continue;
385 atomic_inc(&state->count);
386 if (mode & FMODE_READ)
387 state->nreaders++;
388 if (mode & FMODE_WRITE) 373 if (mode & FMODE_WRITE)
389 state->nwriters++; 374 list_move(&state->open_states, &state->owner->so_states);
390 return state; 375 else
376 list_move_tail(&state->open_states, &state->owner->so_states);
391 } 377 }
392 return NULL; 378 if (mode == 0)
379 list_del_init(&state->inode_states);
380 state->state = mode;
393} 381}
394 382
395static struct nfs4_state * 383static struct nfs4_state *
@@ -400,7 +388,7 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
400 388
401 list_for_each_entry(state, &nfsi->open_states, inode_states) { 389 list_for_each_entry(state, &nfsi->open_states, inode_states) {
402 /* Is this in the process of being freed? */ 390 /* Is this in the process of being freed? */
403 if (state->nreaders == 0 && state->nwriters == 0) 391 if (state->state == 0)
404 continue; 392 continue;
405 if (state->owner == owner) { 393 if (state->owner == owner) {
406 atomic_inc(&state->count); 394 atomic_inc(&state->count);
@@ -410,17 +398,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
410 return NULL; 398 return NULL;
411} 399}
412 400
413struct nfs4_state *
414nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
415{
416 struct nfs4_state *state;
417
418 spin_lock(&inode->i_lock);
419 state = __nfs4_find_state(inode, cred, mode);
420 spin_unlock(&inode->i_lock);
421 return state;
422}
423
424static void 401static void
425nfs4_free_open_state(struct nfs4_state *state) 402nfs4_free_open_state(struct nfs4_state *state)
426{ 403{
@@ -481,7 +458,6 @@ void nfs4_put_open_state(struct nfs4_state *state)
481 spin_unlock(&inode->i_lock); 458 spin_unlock(&inode->i_lock);
482 spin_unlock(&owner->so_lock); 459 spin_unlock(&owner->so_lock);
483 iput(inode); 460 iput(inode);
484 BUG_ON (state->state != 0);
485 nfs4_free_open_state(state); 461 nfs4_free_open_state(state);
486 nfs4_put_state_owner(owner); 462 nfs4_put_state_owner(owner);
487} 463}
@@ -493,7 +469,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
493{ 469{
494 struct inode *inode = state->inode; 470 struct inode *inode = state->inode;
495 struct nfs4_state_owner *owner = state->owner; 471 struct nfs4_state_owner *owner = state->owner;
496 int newstate; 472 int oldstate, newstate = 0;
497 473
498 atomic_inc(&owner->so_count); 474 atomic_inc(&owner->so_count);
499 /* Protect against nfs4_find_state() */ 475 /* Protect against nfs4_find_state() */
@@ -503,30 +479,20 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
503 state->nreaders--; 479 state->nreaders--;
504 if (mode & FMODE_WRITE) 480 if (mode & FMODE_WRITE)
505 state->nwriters--; 481 state->nwriters--;
506 if (state->nwriters == 0) { 482 oldstate = newstate = state->state;
507 if (state->nreaders == 0) 483 if (state->nreaders == 0)
508 list_del_init(&state->inode_states); 484 newstate &= ~FMODE_READ;
509 /* See reclaim code */ 485 if (state->nwriters == 0)
510 list_move_tail(&state->open_states, &owner->so_states); 486 newstate &= ~FMODE_WRITE;
487 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
488 nfs4_state_set_mode_locked(state, newstate);
489 oldstate = newstate;
511 } 490 }
512 spin_unlock(&inode->i_lock); 491 spin_unlock(&inode->i_lock);
513 spin_unlock(&owner->so_lock); 492 spin_unlock(&owner->so_lock);
514 newstate = 0; 493
515 if (state->state != 0) { 494 if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
516 if (state->nreaders) 495 return;
517 newstate |= FMODE_READ;
518 if (state->nwriters)
519 newstate |= FMODE_WRITE;
520 if (state->state == newstate)
521 goto out;
522 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
523 state->state = newstate;
524 goto out;
525 }
526 if (nfs4_do_close(inode, state, newstate) == 0)
527 return;
528 }
529out:
530 nfs4_put_open_state(state); 496 nfs4_put_open_state(state);
531 nfs4_put_state_owner(owner); 497 nfs4_put_state_owner(owner);
532} 498}
@@ -815,7 +781,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
815 int status = 0; 781 int status = 0;
816 782
817 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { 783 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
818 if (!(fl->fl_flags & FL_POSIX)) 784 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
819 continue; 785 continue;
820 if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state) 786 if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
821 continue; 787 continue;
@@ -830,7 +796,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
830 case -NFS4ERR_NO_GRACE: 796 case -NFS4ERR_NO_GRACE:
831 case -NFS4ERR_RECLAIM_BAD: 797 case -NFS4ERR_RECLAIM_BAD:
832 case -NFS4ERR_RECLAIM_CONFLICT: 798 case -NFS4ERR_RECLAIM_CONFLICT:
833 /* kill_proc(fl->fl_owner, SIGLOST, 1); */ 799 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
834 break; 800 break;
835 case -NFS4ERR_STALE_CLIENTID: 801 case -NFS4ERR_STALE_CLIENTID:
836 goto out_err; 802 goto out_err;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 43b03b19731b..5f20eafba8ec 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -507,7 +507,7 @@ int nfs_readpage(struct file *file, struct page *page)
507 goto out_error; 507 goto out_error;
508 508
509 if (file == NULL) { 509 if (file == NULL) {
510 ctx = nfs_find_open_context(inode, FMODE_READ); 510 ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
511 if (ctx == NULL) 511 if (ctx == NULL)
512 return -EBADF; 512 return -EBADF;
513 } else 513 } else
@@ -576,7 +576,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
576 nr_pages); 576 nr_pages);
577 577
578 if (filp == NULL) { 578 if (filp == NULL) {
579 desc.ctx = nfs_find_open_context(inode, FMODE_READ); 579 desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
580 if (desc.ctx == NULL) 580 if (desc.ctx == NULL)
581 return -EBADF; 581 return -EBADF;
582 } else 582 } else
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index f732541a3332..d639d172d568 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -52,8 +52,7 @@ nfs_put_unlinkdata(struct nfs_unlinkdata *data)
52{ 52{
53 if (--data->count == 0) { 53 if (--data->count == 0) {
54 nfs_detach_unlinkdata(data); 54 nfs_detach_unlinkdata(data);
55 if (data->name.name != NULL) 55 kfree(data->name.name);
56 kfree(data->name.name);
57 kfree(data); 56 kfree(data);
58 } 57 }
59} 58}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 819a65f5071f..8f71e766cc5d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -294,7 +294,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
294 if (page->index >= end_index+1 || !offset) 294 if (page->index >= end_index+1 || !offset)
295 goto out; 295 goto out;
296do_it: 296do_it:
297 ctx = nfs_find_open_context(inode, FMODE_WRITE); 297 ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
298 if (ctx == NULL) { 298 if (ctx == NULL) {
299 err = -EBADF; 299 err = -EBADF;
300 goto out; 300 goto out;
@@ -734,14 +734,14 @@ int nfs_updatepage(struct file *file, struct page *page,
734 unsigned int offset, unsigned int count) 734 unsigned int offset, unsigned int count)
735{ 735{
736 struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; 736 struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
737 struct dentry *dentry = file->f_dentry;
738 struct inode *inode = page->mapping->host; 737 struct inode *inode = page->mapping->host;
739 struct nfs_page *req; 738 struct nfs_page *req;
740 int status = 0; 739 int status = 0;
741 740
742 dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n", 741 dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n",
743 dentry->d_parent->d_name.name, dentry->d_name.name, 742 file->f_dentry->d_parent->d_name.name,
744 count, (long long)(page_offset(page) +offset)); 743 file->f_dentry->d_name.name, count,
744 (long long)(page_offset(page) +offset));
745 745
746 if (IS_SYNC(inode)) { 746 if (IS_SYNC(inode)) {
747 status = nfs_writepage_sync(ctx, inode, page, offset, count, 0); 747 status = nfs_writepage_sync(ctx, inode, page, offset, count, 0);
@@ -850,7 +850,6 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
850 unsigned int count, unsigned int offset, 850 unsigned int count, unsigned int offset,
851 int how) 851 int how)
852{ 852{
853 struct rpc_task *task = &data->task;
854 struct inode *inode; 853 struct inode *inode;
855 854
856 /* Set up the RPC argument and reply structs 855 /* Set up the RPC argument and reply structs
@@ -881,7 +880,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
881 data->task.tk_release = nfs_writedata_release; 880 data->task.tk_release = nfs_writedata_release;
882 881
883 dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n", 882 dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
884 task->tk_pid, 883 data->task.tk_pid,
885 inode->i_sb->s_id, 884 inode->i_sb->s_id,
886 (long long)NFS_FILEID(inode), 885 (long long)NFS_FILEID(inode),
887 count, 886 count,
@@ -1217,7 +1216,6 @@ static void nfs_commit_release(struct rpc_task *task)
1217static void nfs_commit_rpcsetup(struct list_head *head, 1216static void nfs_commit_rpcsetup(struct list_head *head,
1218 struct nfs_write_data *data, int how) 1217 struct nfs_write_data *data, int how)
1219{ 1218{
1220 struct rpc_task *task = &data->task;
1221 struct nfs_page *first; 1219 struct nfs_page *first;
1222 struct inode *inode; 1220 struct inode *inode;
1223 1221
@@ -1248,7 +1246,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1248 /* Release requests */ 1246 /* Release requests */
1249 data->task.tk_release = nfs_commit_release; 1247 data->task.tk_release = nfs_commit_release;
1250 1248
1251 dprintk("NFS: %4d initiated commit call\n", task->tk_pid); 1249 dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid);
1252} 1250}
1253 1251
1254/* 1252/*