Hi,

Sorry for the delay,

On Thu, 2007-04-05 at 19:41 -0400, J. Bruce Fields wrote:
> From: Marc Eshel <[EMAIL PROTECTED]> - unquoted
> 
> Add NFS lock support to GFS2.
> 
> Signed-off-by: J. Bruce Fields <[EMAIL PROTECTED]>
Acked-by: Steven Whitehouse <[EMAIL PROTECTED]>

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 [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to