aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2009-06-17 16:23:00 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-06-17 16:23:00 -0400
commit3f09df70e3a33590ae5a97b8a15486d3711c7065 (patch)
tree18f5c9115aa79dd2cab5f87d7024bea5460ca0af
parent965b5d679146c9f69bc0325388bb9ed357863c4f (diff)
NFS: Ensure we always hold the BKL when dereferencing inode->i_flock
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/delegation.c16
-rw-r--r--fs/nfs/nfs4state.c9
2 files changed, 23 insertions, 2 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index d4f669f0683e..af05b918cb5b 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -70,15 +70,24 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
70 struct file_lock *fl; 70 struct file_lock *fl;
71 int status = 0; 71 int status = 0;
72 72
73 if (inode->i_flock == NULL)
74 goto out;
75
76 /* Protect inode->i_flock using the BKL */
77 lock_kernel();
73 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 78 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
74 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) 79 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
75 continue; 80 continue;
76 if (nfs_file_open_context(fl->fl_file) != ctx) 81 if (nfs_file_open_context(fl->fl_file) != ctx)
77 continue; 82 continue;
83 unlock_kernel();
78 status = nfs4_lock_delegation_recall(state, fl); 84 status = nfs4_lock_delegation_recall(state, fl);
79 if (status < 0) 85 if (status < 0)
80 break; 86 goto out;
87 lock_kernel();
81 } 88 }
89 unlock_kernel();
90out:
82 return status; 91 return status;
83} 92}
84 93
@@ -256,7 +265,10 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat
256 struct nfs_inode *nfsi = NFS_I(inode); 265 struct nfs_inode *nfsi = NFS_I(inode);
257 266
258 nfs_msync_inode(inode); 267 nfs_msync_inode(inode);
259 /* Guard against new delegated open calls */ 268 /*
269 * Guard against new delegated open/lock/unlock calls and against
270 * state recovery
271 */
260 down_write(&nfsi->rwsem); 272 down_write(&nfsi->rwsem);
261 nfs_delegation_claim_opens(inode, &delegation->stateid); 273 nfs_delegation_claim_opens(inode, &delegation->stateid);
262 up_write(&nfsi->rwsem); 274 up_write(&nfsi->rwsem);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 6e094e95cf0f..0b2a19bfe5a0 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -847,12 +847,19 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
847 struct file_lock *fl; 847 struct file_lock *fl;
848 int status = 0; 848 int status = 0;
849 849
850 if (inode->i_flock == NULL)
851 return 0;
852
853 /* Guard against delegation returns and new lock/unlock calls */
850 down_write(&nfsi->rwsem); 854 down_write(&nfsi->rwsem);
855 /* Protect inode->i_flock using the BKL */
856 lock_kernel();
851 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 857 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
852 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) 858 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
853 continue; 859 continue;
854 if (nfs_file_open_context(fl->fl_file)->state != state) 860 if (nfs_file_open_context(fl->fl_file)->state != state)
855 continue; 861 continue;
862 unlock_kernel();
856 status = ops->recover_lock(state, fl); 863 status = ops->recover_lock(state, fl);
857 switch (status) { 864 switch (status) {
858 case 0: 865 case 0:
@@ -875,7 +882,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
875 /* kill_proc(fl->fl_pid, SIGLOST, 1); */ 882 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
876 status = 0; 883 status = 0;
877 } 884 }
885 lock_kernel();
878 } 886 }
887 unlock_kernel();
879out: 888out:
880 up_write(&nfsi->rwsem); 889 up_write(&nfsi->rwsem);
881 return status; 890 return status;