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

Commit 1a8322b2 authored by Marc Eshel's avatar Marc Eshel Committed by J. Bruce Fields
Browse files

lockd: add code to handle deferred lock requests



Rewrite nlmsvc_lock() to use the asynchronous interface.

As with testlock, we answer nlm requests in nlmsvc_lock by first looking up
the block and then using the results we find in the block if B_QUEUED is
set, and calling vfs_lock_file() otherwise.

If this a new lock request and we get -EINPROGRESS return on a non-blocking
request then we defer the request.

Also modify nlmsvc_unlock() to call the filesystem method if appropriate.

Signed-off-by: default avatarMarc Eshel <eshel@almaden.ibm.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent f8120480
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -145,6 +145,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
	/* Now try to lock the file */
	resp->status = nlmsvc_lock(rqstp, file, &argp->lock,
					argp->block, &argp->cookie);
	if (resp->status == nlm_drop_reply)
		return rpc_drop_reply;

	dprintk("lockd: LOCK          status %d\n", ntohl(resp->status));
	nlm_release_host(host);
+35 −6
Original line number Diff line number Diff line
@@ -393,17 +393,43 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
	} else
		lock->fl.fl_flags &= ~FL_SLEEP;

	error = posix_lock_file(file->f_file, &lock->fl, NULL);
	lock->fl.fl_flags &= ~FL_SLEEP;
	if (block->b_flags & B_QUEUED) {
		dprintk("lockd: nlmsvc_lock deferred block %p flags %d\n",
							block, block->b_flags);
		if (block->b_granted) {
			nlmsvc_unlink_block(block);
			ret = nlm_granted;
			goto out;
		}
		if (block->b_flags & B_TIMED_OUT) {
			nlmsvc_unlink_block(block);
			ret = nlm_lck_denied;
			goto out;
		}
		ret = nlm_drop_reply;
		goto out;
	}

	dprintk("lockd: posix_lock_file returned %d\n", error);
	if (!wait)
		lock->fl.fl_flags &= ~FL_SLEEP;
	error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
	lock->fl.fl_flags &= ~FL_SLEEP;

	dprintk("lockd: vfs_lock_file returned %d\n", error);
	switch(error) {
		case 0:
			ret = nlm_granted;
			goto out;
		case -EAGAIN:
			ret = nlm_lck_denied;
			break;
		case -EINPROGRESS:
			if (wait)
				break;
			/* Filesystem lock operation is in progress
			   Add it to the queue waiting for callback */
			ret = nlmsvc_defer_lock_rqst(rqstp, block);
			goto out;
		case -EDEADLK:
			ret = nlm_deadlock;
			goto out;
@@ -535,7 +561,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
	nlmsvc_cancel_blocked(file, lock);

	lock->fl.fl_type = F_UNLCK;
	error = posix_lock_file(file->f_file, &lock->fl, NULL);
	error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);

	return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
}
@@ -564,6 +590,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
	block = nlmsvc_lookup_block(file, lock);
	mutex_unlock(&file->f_mutex);
	if (block != NULL) {
		vfs_cancel_lock(block->b_file->f_file,
				&block->b_call->a_args.lock.fl);
		status = nlmsvc_unlink_block(block);
		nlmsvc_release_block(block);
	}
@@ -697,14 +725,15 @@ nlmsvc_grant_blocked(struct nlm_block *block)

	/* Try the lock operation again */
	lock->fl.fl_flags |= FL_SLEEP;
	error = posix_lock_file(file->f_file, &lock->fl, NULL);
	error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
	lock->fl.fl_flags &= ~FL_SLEEP;

	switch (error) {
	case 0:
		break;
	case -EAGAIN:
		dprintk("lockd: lock still blocked\n");
	case -EINPROGRESS:
		dprintk("lockd: lock still blocked error %d\n", error);
		nlmsvc_insert_block(block, NLM_NEVER);
		nlmsvc_release_block(block);
		return;
+2 −0
Original line number Diff line number Diff line
@@ -175,6 +175,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
	/* Now try to lock the file */
	resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock,
					       argp->block, &argp->cookie));
	if (resp->status == nlm_drop_reply)
		return rpc_drop_reply;

	dprintk("lockd: LOCK          status %d\n", ntohl(resp->status));
	nlm_release_host(host);
+1 −1
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
			lock.fl_type  = F_UNLCK;
			lock.fl_start = 0;
			lock.fl_end   = OFFSET_MAX;
			if (posix_lock_file(file->f_file, &lock, NULL) < 0) {
			if (vfs_lock_file(file->f_file, F_SETLK, &lock, NULL) < 0) {
				printk("lockd: unlock failure in %s:%d\n",
						__FILE__, __LINE__);
				return 1;