Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5263e31e authored by Jeff Layton's avatar Jeff Layton Committed by Jeff Layton
Browse files

locks: move flock locks to file_lock_context

parent c362781c
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -239,14 +239,16 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
	return err;
}

/**
 * Must be called with lock_flocks() already held. Fills in the passed
 * counter variables, so you can prepare pagelist metadata before calling
 * ceph_encode_locks.
/*
 * Fills in the passed counter variables, so you can prepare pagelist metadata
 * before calling ceph_encode_locks.
 *
 * FIXME: add counters to struct file_lock_context so we don't need to do this?
 */
void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
{
	struct file_lock *lock;
	struct file_lock_context *ctx;

	*fcntl_count = 0;
	*flock_count = 0;
@@ -255,7 +257,11 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
	for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
		if (lock->fl_flags & FL_POSIX)
			++(*fcntl_count);
		else if (lock->fl_flags & FL_FLOCK)
	}

	ctx = inode->i_flctx;
	if (ctx) {
		list_for_each_entry(lock, &ctx->flc_flock, fl_list)
			++(*flock_count);
	}
	spin_unlock(&inode->i_lock);
@@ -273,6 +279,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
				int num_fcntl_locks, int num_flock_locks)
{
	struct file_lock *lock;
	struct file_lock_context *ctx;
	int err = 0;
	int seen_fcntl = 0;
	int seen_flock = 0;
@@ -295,8 +302,10 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
			++l;
		}
	}
	for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
		if (lock->fl_flags & FL_FLOCK) {

	ctx = inode->i_flctx;
	if (ctx) {
		list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
			++seen_flock;
			if (seen_flock > num_flock_locks) {
				err = -ENOSPC;
+35 −19
Original line number Diff line number Diff line
@@ -694,6 +694,14 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
	locks_insert_global_locks(fl);
}

static void
locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before)
{
	fl->fl_nspid = get_pid(task_tgid(current));
	list_add_tail(&fl->fl_list, before);
	locks_insert_global_locks(fl);
}

/**
 * locks_delete_lock - Delete a lock and then free it.
 * @thisfl_p: pointer that points to the fl_next field of the previous
@@ -739,6 +747,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p,
		locks_free_lock(fl);
}

static void
locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose)
{
	locks_delete_global_locks(fl);
	if (fl->fl_nspid) {
		put_pid(fl->fl_nspid);
		fl->fl_nspid = NULL;
	}
	locks_wake_up_blocks(fl);
	list_move(&fl->fl_list, dispose);
}

/* Determine if lock sys_fl blocks lock caller_fl. Common functionality
 * checks for shared/exclusive status of overlapping locks.
 */
@@ -888,12 +908,17 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
static int flock_lock_file(struct file *filp, struct file_lock *request)
{
	struct file_lock *new_fl = NULL;
	struct file_lock **before;
	struct file_lock *fl;
	struct file_lock_context *ctx;
	struct inode *inode = file_inode(filp);
	int error = 0;
	int found = 0;
	bool found = false;
	LIST_HEAD(dispose);

	ctx = locks_get_lock_context(inode);
	if (!ctx)
		return -ENOMEM;

	if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
		new_fl = locks_alloc_lock();
		if (!new_fl)
@@ -904,18 +929,13 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
	if (request->fl_flags & FL_ACCESS)
		goto find_conflict;

	for_each_lock(inode, before) {
		struct file_lock *fl = *before;
		if (IS_POSIX(fl))
			break;
		if (IS_LEASE(fl))
			continue;
	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
		if (filp != fl->fl_file)
			continue;
		if (request->fl_type == fl->fl_type)
			goto out;
		found = 1;
		locks_delete_lock(before, &dispose);
		found = true;
		locks_delete_lock_ctx(fl, &dispose);
		break;
	}

@@ -936,12 +956,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
	}

find_conflict:
	for_each_lock(inode, before) {
		struct file_lock *fl = *before;
		if (IS_POSIX(fl))
			break;
		if (IS_LEASE(fl))
			continue;
	list_for_each_entry(fl, &ctx->flc_flock, fl_list) {
		if (!flock_locks_conflict(request, fl))
			continue;
		error = -EAGAIN;
@@ -954,7 +969,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
	if (request->fl_flags & FL_ACCESS)
		goto out;
	locks_copy_lock(new_fl, request);
	locks_insert_lock(before, new_fl);
	locks_insert_lock_ctx(new_fl, &ctx->flc_flock);
	new_fl = NULL;
	error = 0;

@@ -2412,8 +2427,9 @@ locks_remove_flock(struct file *filp)
		.fl_type = F_UNLCK,
		.fl_end = OFFSET_MAX,
	};
	struct file_lock_context *flctx = file_inode(filp)->i_flctx;

	if (!file_inode(filp)->i_flock)
	if (!flctx || list_empty(&flctx->flc_flock))
		return;

	if (filp->f_op->flock)
+17 −2
Original line number Diff line number Diff line
@@ -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;
+40 −2
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -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) {
Loading