[DLM] dlm_device interface changes [3/6]
authorDavid Teigland <teigland@redhat.com>
Fri, 18 May 2007 14:00:32 +0000 (09:00 -0500)
committerSteven Whitehouse <swhiteho@redhat.com>
Mon, 9 Jul 2007 07:22:36 +0000 (08:22 +0100)
Change the user/kernel device interface used by libdlm:
- Add ability for userspace to check the version of the interface.  libdlm
  can now adapt to different versions of the kernel interface.
- Increase the size of the flags passed in a lock request so all possible
  flags can be used from userspace.
- Add an opaque "xid" value for each lock.  This "transaction id" will be
  used later to associate locks with each other during deadlock detection.
- Add a "timeout" value for each lock.  This is used along with the
  DLM_LKF_TIMEOUT flag.

Also, remove a fragment of unused code in device_read().

This patch requires updating libdlm which is backward compatible with
older kernels.

Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lock.h
fs/dlm/user.c
include/linux/dlm_device.h

index 65a5fc0..a8d6e99 100644 (file)
@@ -151,6 +151,7 @@ struct dlm_args {
        void                    *bastaddr;
        int                     mode;
        struct dlm_lksb         *lksb;
+       unsigned long           timeout;
 };
 
 
@@ -528,6 +529,7 @@ struct dlm_user_args {
        void __user             *castaddr;
        void __user             *bastparam;
        void __user             *bastaddr;
+       uint64_t                xid;
 };
 
 #define DLM_PROC_FLAGS_CLOSING 1
index ab986df..ad3797a 100644 (file)
@@ -1098,6 +1098,8 @@ void dlm_scan_timeout(struct dlm_ls *ls)
                }
 
                if (do_cancel) {
+                       log_debug("timeout cancel %x node %d %s", lkb->lkb_id,
+                                 lkb->lkb_nodeid, r->res_name);
                        lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
                        lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
                        del_timeout(lkb);
@@ -1864,7 +1866,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
 }
 
 static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
-                        int namelen, uint32_t parent_lkid, void *ast,
+                        int namelen, unsigned long timeout_cs, void *ast,
                         void *astarg, void *bast, struct dlm_args *args)
 {
        int rv = -EINVAL;
@@ -1907,10 +1909,6 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
        if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr)
                goto out;
 
-       /* parent/child locks not yet supported */
-       if (parent_lkid)
-               goto out;
-
        if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid)
                goto out;
 
@@ -1922,6 +1920,7 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
        args->astaddr = ast;
        args->astparam = (long) astarg;
        args->bastaddr = bast;
+       args->timeout = timeout_cs;
        args->mode = mode;
        args->lksb = lksb;
        rv = 0;
@@ -1976,6 +1975,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
        lkb->lkb_lksb = args->lksb;
        lkb->lkb_lvbptr = args->lksb->sb_lvbptr;
        lkb->lkb_ownpid = (int) current->pid;
+       lkb->lkb_timeout_cs = args->timeout;
        rv = 0;
  out:
        return rv;
@@ -2423,7 +2423,7 @@ int dlm_lock(dlm_lockspace_t *lockspace,
        if (error)
                goto out;
 
-       error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast,
+       error = set_lock_args(mode, lksb, flags, namelen, 0, ast,
                              astarg, bast, &args);
        if (error)
                goto out_put;
@@ -4175,7 +4175,7 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
 
 int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
                     int mode, uint32_t flags, void *name, unsigned int namelen,
-                    uint32_t parent_lkid)
+                    unsigned long timeout_cs)
 {
        struct dlm_lkb *lkb;
        struct dlm_args args;
@@ -4203,7 +4203,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
           When DLM_IFL_USER is set, the dlm knows that this is a userspace
           lock and that lkb_astparam is the dlm_user_args structure. */
 
-       error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid,
+       error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
                              DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
        lkb->lkb_flags |= DLM_IFL_USER;
        ua->old_mode = DLM_LOCK_IV;
@@ -4240,7 +4240,8 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
 }
 
 int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
-                    int mode, uint32_t flags, uint32_t lkid, char *lvb_in)
+                    int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+                    unsigned long timeout_cs)
 {
        struct dlm_lkb *lkb;
        struct dlm_args args;
@@ -4268,6 +4269,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
        if (lvb_in && ua->lksb.sb_lvbptr)
                memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
 
+       ua->xid = ua_tmp->xid;
        ua->castparam = ua_tmp->castparam;
        ua->castaddr = ua_tmp->castaddr;
        ua->bastparam = ua_tmp->bastparam;
@@ -4275,8 +4277,8 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
        ua->user_lksb = ua_tmp->user_lksb;
        ua->old_mode = lkb->lkb_grmode;
 
-       error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST,
-                             ua, DLM_FAKE_USER_AST, &args);
+       error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
+                             DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
        if (error)
                goto out_put;
 
index 6b5b71f..99ab463 100644 (file)
@@ -38,9 +38,11 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
 int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
 
 int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
-       uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid);
+       uint32_t flags, void *name, unsigned int namelen,
+       unsigned long timeout_cs);
 int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
-       int mode, uint32_t flags, uint32_t lkid, char *lvb_in);
+       int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+       unsigned long timeout_cs);
 int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
        uint32_t flags, uint32_t lkid, char *lvb_in);
 int dlm_user_cancel(struct dlm_ls *ls,  struct dlm_user_args *ua_tmp,
index c7612da..37aad3f 100644 (file)
@@ -33,16 +33,17 @@ static const struct file_operations device_fops;
 struct dlm_lock_params32 {
        __u8 mode;
        __u8 namelen;
-       __u16 flags;
+       __u16 unused;
+       __u32 flags;
        __u32 lkid;
        __u32 parent;
-
+       __u64 xid;
+       __u64 timeout;
        __u32 castparam;
        __u32 castaddr;
        __u32 bastparam;
        __u32 bastaddr;
        __u32 lksb;
-
        char lvb[DLM_USER_LVB_LEN];
        char name[0];
 };
@@ -68,6 +69,7 @@ struct dlm_lksb32 {
 };
 
 struct dlm_lock_result32 {
+       __u32 version[3];
        __u32 length;
        __u32 user_astaddr;
        __u32 user_astparam;
@@ -102,6 +104,8 @@ static void compat_input(struct dlm_write_request *kb,
                kb->i.lock.flags = kb32->i.lock.flags;
                kb->i.lock.lkid = kb32->i.lock.lkid;
                kb->i.lock.parent = kb32->i.lock.parent;
+               kb->i.lock.xid = kb32->i.lock.xid;
+               kb->i.lock.timeout = kb32->i.lock.timeout;
                kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
                kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
                kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
@@ -115,6 +119,10 @@ static void compat_input(struct dlm_write_request *kb,
 static void compat_output(struct dlm_lock_result *res,
                          struct dlm_lock_result32 *res32)
 {
+       res32->version[0] = res->version[0];
+       res32->version[1] = res->version[1];
+       res32->version[2] = res->version[2];
+
        res32->user_astaddr = (__u32)(long)res->user_astaddr;
        res32->user_astparam = (__u32)(long)res->user_astparam;
        res32->user_lksb = (__u32)(long)res->user_lksb;
@@ -252,16 +260,18 @@ static int device_user_lock(struct dlm_user_proc *proc,
        ua->castaddr = params->castaddr;
        ua->bastparam = params->bastparam;
        ua->bastaddr = params->bastaddr;
+       ua->xid = params->xid;
 
        if (params->flags & DLM_LKF_CONVERT)
                error = dlm_user_convert(ls, ua,
                                         params->mode, params->flags,
-                                        params->lkid, params->lvb);
+                                        params->lkid, params->lvb,
+                                        (unsigned long) params->timeout);
        else {
                error = dlm_user_request(ls, ua,
                                         params->mode, params->flags,
                                         params->name, params->namelen,
-                                        params->parent);
+                                        (unsigned long) params->timeout);
                if (!error)
                        error = ua->lksb.sb_lkid;
        }
@@ -641,6 +651,9 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
        int struct_len;
 
        memset(&result, 0, sizeof(struct dlm_lock_result));
+       result.version[0] = DLM_DEVICE_VERSION_MAJOR;
+       result.version[1] = DLM_DEVICE_VERSION_MINOR;
+       result.version[2] = DLM_DEVICE_VERSION_PATCH;
        memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
        result.user_lksb = ua->user_lksb;
 
@@ -699,6 +712,20 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
        return error;
 }
 
+static int copy_version_to_user(char __user *buf, size_t count)
+{
+       struct dlm_device_version ver;
+
+       memset(&ver, 0, sizeof(struct dlm_device_version));
+       ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
+       ver.version[1] = DLM_DEVICE_VERSION_MINOR;
+       ver.version[2] = DLM_DEVICE_VERSION_PATCH;
+
+       if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
+               return -EFAULT;
+       return sizeof(struct dlm_device_version);
+}
+
 /* a read returns a single ast described in a struct dlm_lock_result */
 
 static ssize_t device_read(struct file *file, char __user *buf, size_t count,
@@ -710,6 +737,16 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
        DECLARE_WAITQUEUE(wait, current);
        int error, type=0, bmode=0, removed = 0;
 
+       if (count == sizeof(struct dlm_device_version)) {
+               error = copy_version_to_user(buf, count);
+               return error;
+       }
+
+       if (!proc) {
+               log_print("non-version read from control device %zu", count);
+               return -EINVAL;
+       }
+
 #ifdef CONFIG_COMPAT
        if (count < sizeof(struct dlm_lock_result32))
 #else
@@ -747,11 +784,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
                }
        }
 
-       if (list_empty(&proc->asts)) {
-               spin_unlock(&proc->asts_spin);
-               return -EAGAIN;
-       }
-
        /* there may be both completion and blocking asts to return for
           the lkb, don't remove lkb from asts list unless no asts remain */
 
@@ -823,6 +855,7 @@ static const struct file_operations device_fops = {
 static const struct file_operations ctl_device_fops = {
        .open    = ctl_device_open,
        .release = ctl_device_close,
+       .read    = device_read,
        .write   = device_write,
        .owner   = THIS_MODULE,
 };
index c2735ca..f7b9b57 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
 #define DLM_USER_LVB_LEN       32
 
 /* Version of the device interface */
-#define DLM_DEVICE_VERSION_MAJOR 5
-#define DLM_DEVICE_VERSION_MINOR 1
+#define DLM_DEVICE_VERSION_MAJOR 6
+#define DLM_DEVICE_VERSION_MINOR 0
 #define DLM_DEVICE_VERSION_PATCH 0
 
 /* struct passed to the lock write */
 struct dlm_lock_params {
        __u8 mode;
        __u8 namelen;
-       __u16 flags;
+       __u16 unused;
+       __u32 flags;
        __u32 lkid;
        __u32 parent;
-        void __user *castparam;
+       __u64 xid;
+       __u64 timeout;
+       void __user *castparam;
        void __user *castaddr;
        void __user *bastparam;
-        void __user *bastaddr;
+       void __user *bastaddr;
        struct dlm_lksb __user *lksb;
        char lvb[DLM_USER_LVB_LEN];
        char name[0];
@@ -62,9 +65,15 @@ struct dlm_write_request {
        } i;
 };
 
+struct dlm_device_version {
+       __u32 version[3];
+};
+
 /* struct read from the "device" fd,
    consists mainly of userspace pointers for the library to use */
+
 struct dlm_lock_result {
+       __u32 version[3];
        __u32 length;
        void __user * user_astaddr;
        void __user * user_astparam;