aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2015-01-16 15:05:55 -0500
committerJeff Layton <jeff.layton@primarydata.com>2015-01-16 15:09:25 -0500
commit5263e31e452fb84138b9bee061d5c06c0f359fea (patch)
tree68726ce860d2c824f605e6ec3f2adc9187d6dc86 /fs/nfs
parentc362781cadd37858c3d8f5d18b1e9957d4671298 (diff)
locks: move flock locks to file_lock_context
Signed-off-by: Jeff Layton <jlayton@primarydata.com> Acked-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/delegation.c19
-rw-r--r--fs/nfs/nfs4state.c42
-rw-r--r--fs/nfs/pagelist.c6
-rw-r--r--fs/nfs/write.c43
4 files changed, 101 insertions, 9 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 7f3f60641344..9f9f67b17e2b 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -85,15 +85,16 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
85{ 85{
86 struct inode *inode = state->inode; 86 struct inode *inode = state->inode;
87 struct file_lock *fl; 87 struct file_lock *fl;
88 struct file_lock_context *flctx;
88 int status = 0; 89 int status = 0;
89 90
90 if (inode->i_flock == NULL) 91 if (inode->i_flock == NULL && inode->i_flctx == NULL)
91 goto out; 92 goto out;
92 93
93 /* Protect inode->i_flock using the i_lock */ 94 /* Protect inode->i_flock using the i_lock */
94 spin_lock(&inode->i_lock); 95 spin_lock(&inode->i_lock);
95 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 96 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
96 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) 97 if (!(fl->fl_flags & (FL_POSIX)))
97 continue; 98 continue;
98 if (nfs_file_open_context(fl->fl_file) != ctx) 99 if (nfs_file_open_context(fl->fl_file) != ctx)
99 continue; 100 continue;
@@ -103,6 +104,20 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
103 goto out; 104 goto out;
104 spin_lock(&inode->i_lock); 105 spin_lock(&inode->i_lock);
105 } 106 }
107
108 flctx = inode->i_flctx;
109 if (flctx) {
110 list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
111 if (nfs_file_open_context(fl->fl_file) != ctx)
112 continue;
113 spin_unlock(&inode->i_lock);
114 status = nfs4_lock_delegation_recall(fl, state,
115 stateid);
116 if (status < 0)
117 goto out;
118 spin_lock(&inode->i_lock);
119 }
120 }
106 spin_unlock(&inode->i_lock); 121 spin_unlock(&inode->i_lock);
107out: 122out:
108 return status; 123 return status;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 5194933ed419..65c404bf61ae 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1366,8 +1366,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
1366 struct nfs_inode *nfsi = NFS_I(inode); 1366 struct nfs_inode *nfsi = NFS_I(inode);
1367 struct file_lock *fl; 1367 struct file_lock *fl;
1368 int status = 0; 1368 int status = 0;
1369 struct file_lock_context *flctx = inode->i_flctx;
1369 1370
1370 if (inode->i_flock == NULL) 1371 if (inode->i_flock == NULL && flctx == NULL)
1371 return 0; 1372 return 0;
1372 1373
1373 /* Guard against delegation returns and new lock/unlock calls */ 1374 /* Guard against delegation returns and new lock/unlock calls */
@@ -1375,7 +1376,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
1375 /* Protect inode->i_flock using the BKL */ 1376 /* Protect inode->i_flock using the BKL */
1376 spin_lock(&inode->i_lock); 1377 spin_lock(&inode->i_lock);
1377 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 1378 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
1378 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) 1379 if (!(fl->fl_flags & FL_POSIX))
1379 continue; 1380 continue;
1380 if (nfs_file_open_context(fl->fl_file)->state != state) 1381 if (nfs_file_open_context(fl->fl_file)->state != state)
1381 continue; 1382 continue;
@@ -1408,6 +1409,43 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
1408 } 1409 }
1409 spin_lock(&inode->i_lock); 1410 spin_lock(&inode->i_lock);
1410 } 1411 }
1412
1413 if (!flctx)
1414 goto out_unlock;
1415
1416 list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
1417 if (nfs_file_open_context(fl->fl_file)->state != state)
1418 continue;
1419 spin_unlock(&inode->i_lock);
1420 status = ops->recover_lock(state, fl);
1421 switch (status) {
1422 case 0:
1423 break;
1424 case -ESTALE:
1425 case -NFS4ERR_ADMIN_REVOKED:
1426 case -NFS4ERR_STALE_STATEID:
1427 case -NFS4ERR_BAD_STATEID:
1428 case -NFS4ERR_EXPIRED:
1429 case -NFS4ERR_NO_GRACE:
1430 case -NFS4ERR_STALE_CLIENTID:
1431 case -NFS4ERR_BADSESSION:
1432 case -NFS4ERR_BADSLOT:
1433 case -NFS4ERR_BAD_HIGH_SLOT:
1434 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
1435 goto out;
1436 default:
1437 pr_err("NFS: %s: unhandled error %d\n",
1438 __func__, status);
1439 case -ENOMEM:
1440 case -NFS4ERR_DENIED:
1441 case -NFS4ERR_RECLAIM_BAD:
1442 case -NFS4ERR_RECLAIM_CONFLICT:
1443 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
1444 status = 0;
1445 }
1446 spin_lock(&inode->i_lock);
1447 }
1448out_unlock:
1411 spin_unlock(&inode->i_lock); 1449 spin_unlock(&inode->i_lock);
1412out: 1450out:
1413 up_write(&nfsi->rwsem); 1451 up_write(&nfsi->rwsem);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 2b5e769beb16..a3b62e15b444 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -826,6 +826,7 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
826 struct nfs_pageio_descriptor *pgio) 826 struct nfs_pageio_descriptor *pgio)
827{ 827{
828 size_t size; 828 size_t size;
829 struct file_lock_context *flctx;
829 830
830 if (prev) { 831 if (prev) {
831 if (!nfs_match_open_context(req->wb_context, prev->wb_context)) 832 if (!nfs_match_open_context(req->wb_context, prev->wb_context))
@@ -834,6 +835,11 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
834 !nfs_match_lock_context(req->wb_lock_context, 835 !nfs_match_lock_context(req->wb_lock_context,
835 prev->wb_lock_context)) 836 prev->wb_lock_context))
836 return false; 837 return false;
838 flctx = req->wb_context->dentry->d_inode->i_flctx;
839 if (flctx != NULL && !list_empty_careful(&flctx->flc_flock) &&
840 !nfs_match_lock_context(req->wb_lock_context,
841 prev->wb_lock_context))
842 return false;
837 if (req_offset(req) != req_offset(prev) + prev->wb_bytes) 843 if (req_offset(req) != req_offset(prev) + prev->wb_bytes)
838 return false; 844 return false;
839 if (req->wb_page == prev->wb_page) { 845 if (req->wb_page == prev->wb_page) {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index af3af685a9e3..e072aeb34195 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1113,6 +1113,11 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
1113 do_flush |= l_ctx->lockowner.l_owner != current->files 1113 do_flush |= l_ctx->lockowner.l_owner != current->files
1114 || l_ctx->lockowner.l_pid != current->tgid; 1114 || l_ctx->lockowner.l_pid != current->tgid;
1115 } 1115 }
1116 if (l_ctx && ctx->dentry->d_inode->i_flctx &&
1117 !list_empty_careful(&ctx->dentry->d_inode->i_flctx->flc_flock)) {
1118 do_flush |= l_ctx->lockowner.l_owner != current->files
1119 || l_ctx->lockowner.l_pid != current->tgid;
1120 }
1116 nfs_release_request(req); 1121 nfs_release_request(req);
1117 if (!do_flush) 1122 if (!do_flush)
1118 return 0; 1123 return 0;
@@ -1170,6 +1175,13 @@ out:
1170 return PageUptodate(page) != 0; 1175 return PageUptodate(page) != 0;
1171} 1176}
1172 1177
1178static bool
1179is_whole_file_wrlock(struct file_lock *fl)
1180{
1181 return fl->fl_start == 0 && fl->fl_end == OFFSET_MAX &&
1182 fl->fl_type == F_WRLCK;
1183}
1184
1173/* If we know the page is up to date, and we're not using byte range locks (or 1185/* If we know the page is up to date, and we're not using byte range locks (or
1174 * if we have the whole file locked for writing), it may be more efficient to 1186 * if we have the whole file locked for writing), it may be more efficient to
1175 * extend the write to cover the entire page in order to avoid fragmentation 1187 * extend the write to cover the entire page in order to avoid fragmentation
@@ -1180,17 +1192,38 @@ out:
1180 */ 1192 */
1181static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode) 1193static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode)
1182{ 1194{
1195 int ret;
1196 struct file_lock_context *flctx = inode->i_flctx;
1197 struct file_lock *fl;
1198
1183 if (file->f_flags & O_DSYNC) 1199 if (file->f_flags & O_DSYNC)
1184 return 0; 1200 return 0;
1185 if (!nfs_write_pageuptodate(page, inode)) 1201 if (!nfs_write_pageuptodate(page, inode))
1186 return 0; 1202 return 0;
1187 if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) 1203 if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
1188 return 1; 1204 return 1;
1189 if (inode->i_flock == NULL || (inode->i_flock->fl_start == 0 && 1205 if (!inode->i_flock && !flctx)
1190 inode->i_flock->fl_end == OFFSET_MAX && 1206 return 0;
1191 inode->i_flock->fl_type != F_RDLCK)) 1207
1192 return 1; 1208 /* Check to see if there are whole file write locks */
1193 return 0; 1209 spin_lock(&inode->i_lock);
1210 ret = 0;
1211
1212 fl = inode->i_flock;
1213 if (fl && is_whole_file_wrlock(fl)) {
1214 ret = 1;
1215 goto out;
1216 }
1217
1218 if (!list_empty(&flctx->flc_flock)) {
1219 fl = list_first_entry(&flctx->flc_flock, struct file_lock,
1220 fl_list);
1221 if (fl->fl_type == F_WRLCK)
1222 ret = 1;
1223 }
1224out:
1225 spin_unlock(&inode->i_lock);
1226 return ret;
1194} 1227}
1195 1228
1196/* 1229/*