locks: move flock locks to file_lock_context
Signed-off-by: Jeff Layton <jlayton@primarydata.com> Acked-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
@@ -85,15 +85,16 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
|
||||
{
|
||||
struct inode *inode = state->inode;
|
||||
struct file_lock *fl;
|
||||
struct file_lock_context *flctx;
|
||||
int status = 0;
|
||||
|
||||
if (inode->i_flock == NULL)
|
||||
if (inode->i_flock == NULL && inode->i_flctx == NULL)
|
||||
goto out;
|
||||
|
||||
/* Protect inode->i_flock using the i_lock */
|
||||
spin_lock(&inode->i_lock);
|
||||
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
|
||||
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
||||
if (!(fl->fl_flags & (FL_POSIX)))
|
||||
continue;
|
||||
if (nfs_file_open_context(fl->fl_file) != ctx)
|
||||
continue;
|
||||
@@ -103,6 +104,20 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
|
||||
goto out;
|
||||
spin_lock(&inode->i_lock);
|
||||
}
|
||||
|
||||
flctx = inode->i_flctx;
|
||||
if (flctx) {
|
||||
list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
|
||||
if (nfs_file_open_context(fl->fl_file) != ctx)
|
||||
continue;
|
||||
spin_unlock(&inode->i_lock);
|
||||
status = nfs4_lock_delegation_recall(fl, state,
|
||||
stateid);
|
||||
if (status < 0)
|
||||
goto out;
|
||||
spin_lock(&inode->i_lock);
|
||||
}
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
out:
|
||||
return status;
|
||||
|
@@ -1366,8 +1366,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct file_lock *fl;
|
||||
int status = 0;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
|
||||
if (inode->i_flock == NULL)
|
||||
if (inode->i_flock == NULL && flctx == NULL)
|
||||
return 0;
|
||||
|
||||
/* 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_
|
||||
/* Protect inode->i_flock using the BKL */
|
||||
spin_lock(&inode->i_lock);
|
||||
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
|
||||
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
|
||||
if (!(fl->fl_flags & FL_POSIX))
|
||||
continue;
|
||||
if (nfs_file_open_context(fl->fl_file)->state != state)
|
||||
continue;
|
||||
@@ -1408,6 +1409,43 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
|
||||
}
|
||||
spin_lock(&inode->i_lock);
|
||||
}
|
||||
|
||||
if (!flctx)
|
||||
goto out_unlock;
|
||||
|
||||
list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
|
||||
if (nfs_file_open_context(fl->fl_file)->state != state)
|
||||
continue;
|
||||
spin_unlock(&inode->i_lock);
|
||||
status = ops->recover_lock(state, fl);
|
||||
switch (status) {
|
||||
case 0:
|
||||
break;
|
||||
case -ESTALE:
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_STALE_STATEID:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
case -NFS4ERR_EXPIRED:
|
||||
case -NFS4ERR_NO_GRACE:
|
||||
case -NFS4ERR_STALE_CLIENTID:
|
||||
case -NFS4ERR_BADSESSION:
|
||||
case -NFS4ERR_BADSLOT:
|
||||
case -NFS4ERR_BAD_HIGH_SLOT:
|
||||
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
|
||||
goto out;
|
||||
default:
|
||||
pr_err("NFS: %s: unhandled error %d\n",
|
||||
__func__, status);
|
||||
case -ENOMEM:
|
||||
case -NFS4ERR_DENIED:
|
||||
case -NFS4ERR_RECLAIM_BAD:
|
||||
case -NFS4ERR_RECLAIM_CONFLICT:
|
||||
/* kill_proc(fl->fl_pid, SIGLOST, 1); */
|
||||
status = 0;
|
||||
}
|
||||
spin_lock(&inode->i_lock);
|
||||
}
|
||||
out_unlock:
|
||||
spin_unlock(&inode->i_lock);
|
||||
out:
|
||||
up_write(&nfsi->rwsem);
|
||||
|
@@ -826,6 +826,7 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
|
||||
struct nfs_pageio_descriptor *pgio)
|
||||
{
|
||||
size_t size;
|
||||
struct file_lock_context *flctx;
|
||||
|
||||
if (prev) {
|
||||
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,
|
||||
!nfs_match_lock_context(req->wb_lock_context,
|
||||
prev->wb_lock_context))
|
||||
return false;
|
||||
flctx = req->wb_context->dentry->d_inode->i_flctx;
|
||||
if (flctx != NULL && !list_empty_careful(&flctx->flc_flock) &&
|
||||
!nfs_match_lock_context(req->wb_lock_context,
|
||||
prev->wb_lock_context))
|
||||
return false;
|
||||
if (req_offset(req) != req_offset(prev) + prev->wb_bytes)
|
||||
return false;
|
||||
if (req->wb_page == prev->wb_page) {
|
||||
|
@@ -1113,6 +1113,11 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
|
||||
do_flush |= l_ctx->lockowner.l_owner != current->files
|
||||
|| l_ctx->lockowner.l_pid != current->tgid;
|
||||
}
|
||||
if (l_ctx && ctx->dentry->d_inode->i_flctx &&
|
||||
!list_empty_careful(&ctx->dentry->d_inode->i_flctx->flc_flock)) {
|
||||
do_flush |= l_ctx->lockowner.l_owner != current->files
|
||||
|| l_ctx->lockowner.l_pid != current->tgid;
|
||||
}
|
||||
nfs_release_request(req);
|
||||
if (!do_flush)
|
||||
return 0;
|
||||
@@ -1170,6 +1175,13 @@ out:
|
||||
return PageUptodate(page) != 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_whole_file_wrlock(struct file_lock *fl)
|
||||
{
|
||||
return fl->fl_start == 0 && fl->fl_end == OFFSET_MAX &&
|
||||
fl->fl_type == F_WRLCK;
|
||||
}
|
||||
|
||||
/* If we know the page is up to date, and we're not using byte range locks (or
|
||||
* if we have the whole file locked for writing), it may be more efficient to
|
||||
* extend the write to cover the entire page in order to avoid fragmentation
|
||||
@@ -1180,17 +1192,38 @@ out:
|
||||
*/
|
||||
static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode)
|
||||
{
|
||||
int ret;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
struct file_lock *fl;
|
||||
|
||||
if (file->f_flags & O_DSYNC)
|
||||
return 0;
|
||||
if (!nfs_write_pageuptodate(page, inode))
|
||||
return 0;
|
||||
if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
|
||||
return 1;
|
||||
if (inode->i_flock == NULL || (inode->i_flock->fl_start == 0 &&
|
||||
inode->i_flock->fl_end == OFFSET_MAX &&
|
||||
inode->i_flock->fl_type != F_RDLCK))
|
||||
return 1;
|
||||
return 0;
|
||||
if (!inode->i_flock && !flctx)
|
||||
return 0;
|
||||
|
||||
/* Check to see if there are whole file write locks */
|
||||
spin_lock(&inode->i_lock);
|
||||
ret = 0;
|
||||
|
||||
fl = inode->i_flock;
|
||||
if (fl && is_whole_file_wrlock(fl)) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!list_empty(&flctx->flc_flock)) {
|
||||
fl = list_first_entry(&flctx->flc_flock, struct file_lock,
|
||||
fl_list);
|
||||
if (fl->fl_type == F_WRLCK)
|
||||
ret = 1;
|
||||
}
|
||||
out:
|
||||
spin_unlock(&inode->i_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user