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

Commit 2d56d3c4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'server-cluster-locking-api' of git://linux-nfs.org/~bfields/linux

* 'server-cluster-locking-api' of git://linux-nfs.org/~bfields/linux:
  gfs2: nfs lock support for gfs2
  lockd: add code to handle deferred lock requests
  lockd: always preallocate block in nlmsvc_lock()
  lockd: handle test_lock deferrals
  lockd: pass cookie in nlmsvc_testlock
  lockd: handle fl_grant callbacks
  lockd: save lock state on deferral
  locks: add fl_grant callback for asynchronous lock return
  nfsd4: Convert NFSv4 to new lock interface
  locks: add lock cancel command
  locks: allow {vfs,posix}_lock_file to return conflicting lock
  locks: factor out generic/filesystem switch from setlock code
  locks: factor out generic/filesystem switch from test_lock
  locks: give posix_test_lock same interface as ->lock
  locks: make ->lock release private data before returning in GETLK case
  locks: create posix-to-flock helper functions
  locks: trivial removal of unnecessary parentheses
parents 0f9008ef 586759f0
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -738,8 +738,7 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)

	if (cmd == F_GETLK) {
		if (fc->no_lock) {
			if (!posix_test_lock(file, fl, fl))
				fl->fl_type = F_UNLCK;
			posix_test_lock(file, fl);
			err = 0;
		} else
			err = fuse_getlk(file, fl);
+99 −10
Original line number Diff line number Diff line
@@ -25,6 +25,15 @@ struct plock_op {
	struct gdlm_plock_info info;
};

struct plock_xop {
	struct plock_op xop;
	void *callback;
	void *fl;
	void *file;
	struct file_lock flc;
};


static inline void set_version(struct gdlm_plock_info *info)
{
	info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
@@ -64,12 +73,14 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
{
	struct gdlm_ls *ls = lockspace;
	struct plock_op *op;
	struct plock_xop *xop;
	int rv;

	op = kzalloc(sizeof(*op), GFP_KERNEL);
	if (!op)
	xop = kzalloc(sizeof(*xop), GFP_KERNEL);
	if (!xop)
		return -ENOMEM;

	op = &xop->xop;
	op->info.optype		= GDLM_PLOCK_OP_LOCK;
	op->info.pid		= fl->fl_pid;
	op->info.ex		= (fl->fl_type == F_WRLCK);
@@ -79,9 +90,21 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
	op->info.start		= fl->fl_start;
	op->info.end		= fl->fl_end;
	op->info.owner		= (__u64)(long) fl->fl_owner;
	if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
		xop->callback	= fl->fl_lmops->fl_grant;
		locks_init_lock(&xop->flc);
		locks_copy_lock(&xop->flc, fl);
		xop->fl		= fl;
		xop->file	= file;
	} else
		xop->callback	= NULL;

	send_op(op);

	if (xop->callback == NULL)
		wait_event(recv_wq, (op->done != 0));
	else
		return -EINPROGRESS;

	spin_lock(&ops_lock);
	if (!list_empty(&op->list)) {
@@ -99,7 +122,63 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
				  (unsigned long long)name->ln_number);
	}

	kfree(op);
	kfree(xop);
	return rv;
}

/* Returns failure iff a succesful lock operation should be canceled */
static int gdlm_plock_callback(struct plock_op *op)
{
	struct file *file;
	struct file_lock *fl;
	struct file_lock *flc;
	int (*notify)(void *, void *, int) = NULL;
	struct plock_xop *xop = (struct plock_xop *)op;
	int rv = 0;

	spin_lock(&ops_lock);
	if (!list_empty(&op->list)) {
		printk(KERN_INFO "plock op on list\n");
		list_del(&op->list);
	}
	spin_unlock(&ops_lock);

	/* check if the following 2 are still valid or make a copy */
	file = xop->file;
	flc = &xop->flc;
	fl = xop->fl;
	notify = xop->callback;

	if (op->info.rv) {
		notify(flc, NULL, op->info.rv);
		goto out;
	}

	/* got fs lock; bookkeep locally as well: */
	flc->fl_flags &= ~FL_SLEEP;
	if (posix_lock_file(file, flc, NULL)) {
		/*
		 * This can only happen in the case of kmalloc() failure.
		 * The filesystem's own lock is the authoritative lock,
		 * so a failure to get the lock locally is not a disaster.
		 * As long as GFS cannot reliably cancel locks (especially
		 * in a low-memory situation), we're better off ignoring
		 * this failure than trying to recover.
		 */
		log_error("gdlm_plock: vfs lock error file %p fl %p",
				file, fl);
	}

	rv = notify(flc, NULL, 0);
	if (rv) {
		/* XXX: We need to cancel the fs lock here: */
		printk("gfs2 lock granted after lock request failed;"
						" dangling lock!\n");
		goto out;
	}

out:
	kfree(xop);
	return rv;
}

@@ -138,6 +217,9 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name,

	rv = op->info.rv;

	if (rv == -ENOENT)
		rv = 0;

	kfree(op);
	return rv;
}
@@ -161,6 +243,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
	op->info.start		= fl->fl_start;
	op->info.end		= fl->fl_end;


	send_op(op);
	wait_event(recv_wq, (op->done != 0));

@@ -173,9 +256,10 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,

	rv = op->info.rv;

	if (rv == 0)
	fl->fl_type = F_UNLCK;
	else if (rv > 0) {
	if (rv == -ENOENT)
		rv = 0;
	else if (rv == 0 && op->info.pid != fl->fl_pid) {
		fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
		fl->fl_pid = op->info.pid;
		fl->fl_start = op->info.start;
@@ -243,9 +327,14 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
	}
	spin_unlock(&ops_lock);

	if (found)
		wake_up(&recv_wq);
	if (found) {
		struct plock_xop *xop;
		xop = (struct plock_xop *)op;
		if (xop->callback)
			count = gdlm_plock_callback(op);
		else
			wake_up(&recv_wq);
	} else
		printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid,
			(unsigned long long)info.number);
	return count;
+1 −7
Original line number Diff line number Diff line
@@ -164,13 +164,7 @@ static void nolock_unhold_lvb(void *lock, char *lvb)
static int nolock_plock_get(void *lockspace, struct lm_lockname *name,
			    struct file *file, struct file_lock *fl)
{
	struct file_lock tmp;
	int ret;

	ret = posix_test_lock(file, fl, &tmp);
	fl->fl_type = F_UNLCK;
	if (ret)
		memcpy(fl, &tmp, sizeof(struct file_lock));
	posix_test_lock(file, fl);

	return 0;
}
+6 −6
Original line number Diff line number Diff line
@@ -513,18 +513,18 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)

	if (sdp->sd_args.ar_localflocks) {
		if (IS_GETLK(cmd)) {
			struct file_lock tmp;
			int ret;
			ret = posix_test_lock(file, fl, &tmp);
			fl->fl_type = F_UNLCK;
			if (ret)
				memcpy(fl, &tmp, sizeof(struct file_lock));
			posix_test_lock(file, fl);
			return 0;
		} else {
			return posix_lock_file_wait(file, fl);
		}
	}

	if (cmd == F_CANCELLK) {
		/* Hack: */
		cmd = F_SETLK;
		fl->fl_type = F_UNLCK;
	}
	if (IS_GETLK(cmd))
		return gfs2_lm_plock_get(sdp, &name, file, fl);
	else if (fl->fl_type == F_UNLCK)
+5 −1
Original line number Diff line number Diff line
@@ -99,7 +99,9 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

	/* Now check for conflicting locks */
	resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock);
	resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie);
	if (resp->status == nlm_drop_reply)
		return rpc_drop_reply;

	dprintk("lockd: TEST4          status %d\n", ntohl(resp->status));
	nlm_release_host(host);
@@ -143,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);
Loading