Re: [PATCH 17/17] gfs2: nfs lock support for gfs2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Sorry for the delay,

On Thu, 2007-04-05 at 19:41 -0400, J. Bruce Fields wrote:
> From: Marc Eshel <eshel@xxxxxxxxxxxxxxx> - unquoted
> 
> Add NFS lock support to GFS2.
> 
> Signed-off-by: J. Bruce Fields <bfields@xxxxxxxxxxxxxx>
Acked-by: Steven Whitehouse <swhiteho@xxxxxxxxxx>

Steve.

> ---
>  fs/gfs2/locking/dlm/plock.c |  104 ++++++++++++++++++++++++++++++++++++++----
>  fs/gfs2/ops_file.c          |    5 ++
>  2 files changed, 99 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
> index 1dd4215..1160cde 100644
> --- a/fs/gfs2/locking/dlm/plock.c
> +++ b/fs/gfs2/locking/dlm/plock.c
> @@ -25,6 +25,14 @@ struct plock_op {
>  	struct gdlm_plock_info info;
>  };
>  
> +struct plock_xop {
> +	struct plock_op xop;
> +	void *callback;
> +	void *fl;
> +	void *file;
> +};
> +
> +
>  static inline void set_version(struct gdlm_plock_info *info)
>  {
>  	info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
> @@ -64,12 +72,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 +89,20 @@ 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_notify) {
> +		xop->callback	= fl->fl_lmops->fl_notify;
> +		/* might need to make a copy */
> +		xop->fl		= fl;
> +		xop->file	= file;
> +	} else
> +		xop->callback	= NULL;
>  
>  	send_op(op);
> -	wait_event(recv_wq, (op->done != 0));
> +
> +	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 +120,60 @@ 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;
> +	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;
> +	fl = xop->fl;
> +	notify = xop->callback;
> +
> +	if (op->info.rv) {
> +		notify(fl, NULL, op->info.rv);
> +		goto out;
> +	}
> +
> +	/* got fs lock; bookkeep locally as well: */
> +	if (posix_lock_file(file, fl, 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(fl, 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 +212,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 +238,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 +251,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) {
> +	fl->fl_type = F_UNLCK;
> +	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 +322,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);
> -	else
> +	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;
> diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
> index 48b248d..329c4dc 100644
> --- a/fs/gfs2/ops_file.c
> +++ b/fs/gfs2/ops_file.c
> @@ -520,6 +520,11 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *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)

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux