From mboxrd@z Thu Jan 1 00:00:00 1970 From: Steven Whitehouse Subject: Re: [PATCH 17/17] gfs2: nfs lock support for gfs2 Date: Tue, 17 Apr 2007 14:34:45 +0100 Message-ID: <1176816885.1636.263.camel@quoit.chygwyn.com> References: <117581646786-git-send-email-> <11758164673642-git-send-email-> <11758164671398-git-send-email-> <11758164672114-git-send-email-> <11758164672880-git-send-email-> <1175816467294-git-send-email-> <11758164671240-git-send-email-> <11758164686-git-send-email-> <1175816468241-git-send-email-> <1175816468106-git-send-email-> <11758164681548-git-send-email-> <11758164683313-git-send-email-> <11758164681958-git-send-email-> <117581646812-git-send-email-> <11758164681424-git-send-email-> <11758164682315-git-send-email-> <11758164693717-git-send-email-> <11758164694159-git-send-email-> Mime-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit Cc: akpm@osdl.org, Trond Myklebust , Marc Eshel , linux-fsdevel@vger.kernel.org To: "J. Bruce Fields" Return-path: Received: from fogou.chygwyn.com ([195.171.2.24]:34247 "EHLO fogou.chygwyn.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754441AbXDQOmu (ORCPT ); Tue, 17 Apr 2007 10:42:50 -0400 In-Reply-To: <11758164694159-git-send-email-> Sender: linux-fsdevel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org Hi, Sorry for the delay, On Thu, 2007-04-05 at 19:41 -0400, J. Bruce Fields wrote: > From: Marc Eshel - unquoted > > Add NFS lock support to GFS2. > > Signed-off-by: J. Bruce Fields Acked-by: Steven Whitehouse 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)