[DLM] compat patch
authorPatrick Caulfield <pcaulfie@redhat.com>
Fri, 9 Jun 2006 20:14:20 +0000 (16:14 -0400)
committerSteven Whitehouse <swhiteho@redhat.com>
Fri, 9 Jun 2006 20:14:20 +0000 (16:14 -0400)
Here's a patch which add 32/64 bit compat to the DLM IOs and tidies the
structures for alignment.

As it causes an ABI change I had few qualms about adding the extra flag for
"is64bit" as it simply uses a byte that would have been padding.

Cc: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Patrick Caulfield <pcaulfie@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/dlm/device.c
include/linux/dlm_device.h

index 49a20d5..47798fe 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-2006 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
@@ -59,6 +59,9 @@ static rwlock_t lockinfo_lock;
 #define LS_FLAG_DELETED   1
 #define LS_FLAG_AUTOFREE  2
 
+/* flags in ls_flags*/
+#define FI_FLAG_OPEN      1
+#define FI_FLAG_COMPAT    2
 
 #define LOCKINFO_MAGIC 0x53595324
 
@@ -117,9 +120,110 @@ struct file_info {
        wait_queue_head_t   fi_wait;
        struct user_ls     *fi_ls;
        atomic_t            fi_refcnt;   /* Number of users */
-       unsigned long       fi_flags;    /* Bit 1 means the device is open */
+       unsigned long       fi_flags;
+};
+
+#ifdef CONFIG_COMPAT
+
+struct dlm_lock_params32 {
+       __u8 mode;
+       __u8 namelen;
+       __u16 flags;
+       __u32 lkid;
+       __u32 parent;
+
+       __u32 castparam;
+       __u32 castaddr;
+       __u32 bastparam;
+       __u32 bastaddr;
+       __u32 lksb;
+
+       char lvb[DLM_USER_LVB_LEN];
+       char name[0];
 };
 
+struct dlm_write_request32 {
+       __u32 version[3];
+       __u8 cmd;
+       __u8 is64bit;
+       __u8 unused[2];
+
+       union  {
+               struct dlm_lock_params32 lock;
+               struct dlm_lspace_params lspace;
+       } i;
+};
+
+struct dlm_lksb32 {
+       __u32    sb_status;
+       __u32    sb_lkid;
+       __u8     sb_flags;
+       __u32    sb_lvbptr;
+};
+
+struct dlm_lock_result32 {
+       __u32 length;
+       __u32 user_astaddr;
+       __u32 user_astparam;
+       __u32 user_lksb;
+       struct dlm_lksb32 lksb;
+       __u8 bast_mode;
+       __u8 unused[3];
+       /* Offsets may be zero if no data is present */
+       __u32 lvb_offset;
+};
+
+
+static void compat_input(struct dlm_write_request *kparams, struct dlm_write_request32 *k32params)
+{
+
+       kparams->version[0] = k32params->version[0];
+       kparams->version[1] = k32params->version[1];
+       kparams->version[2] = k32params->version[2];
+
+       kparams->cmd = k32params->cmd;
+       kparams->is64bit = k32params->is64bit;
+       if (kparams->cmd == DLM_USER_CREATE_LOCKSPACE ||
+           kparams->cmd == DLM_USER_REMOVE_LOCKSPACE) {
+
+               kparams->i.lspace.flags = k32params->i.lspace.flags;
+               kparams->i.lspace.minor = k32params->i.lspace.minor;
+               strcpy(kparams->i.lspace.name, k32params->i.lspace.name);
+       }
+       else {
+               kparams->i.lock.mode = k32params->i.lock.mode;
+               kparams->i.lock.namelen = k32params->i.lock.namelen;
+               kparams->i.lock.flags = k32params->i.lock.flags;
+               kparams->i.lock.lkid = k32params->i.lock.lkid;
+               kparams->i.lock.parent = k32params->i.lock.parent;
+               kparams->i.lock.castparam = (void *)(long)k32params->i.lock.castparam;
+               kparams->i.lock.castaddr = (void *)(long)k32params->i.lock.castaddr;
+               kparams->i.lock.bastparam = (void *)(long)k32params->i.lock.bastparam;
+               kparams->i.lock.bastaddr = (void *)(long)k32params->i.lock.bastaddr;
+               kparams->i.lock.lksb = (void *)(long)k32params->i.lock.lksb;
+               memcpy(kparams->i.lock.lvb, k32params->i.lock.lvb, DLM_USER_LVB_LEN);
+               memcpy(kparams->i.lock.name, k32params->i.lock.name, kparams->i.lock.namelen);
+       }
+}
+
+void compat_output(struct dlm_lock_result *res, struct dlm_lock_result32 *res32)
+{
+       res32->length = res->length - (sizeof(struct dlm_lock_result) - sizeof(struct dlm_lock_result32));
+       res32->user_astaddr = (__u32)(long)res->user_astaddr;
+       res32->user_astparam = (__u32)(long)res->user_astparam;
+       res32->user_lksb = (__u32)(long)res->user_lksb;
+       res32->bast_mode = res->bast_mode;
+
+       res32->lvb_offset = res->lvb_offset;
+       res32->length = res->length;
+
+       res32->lksb.sb_status = res->lksb.sb_status;
+       res32->lksb.sb_flags = res->lksb.sb_flags;
+       res32->lksb.sb_lkid = res->lksb.sb_lkid;
+       res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
+}
+#endif
+
 
 /* get and put ops for file_info.
    Actually I don't really like "get" and "put", but everyone
@@ -364,7 +468,7 @@ static void ast_routine(void *param)
                        li->li_grmode = li->li_rqmode;
 
                /* Only queue AST if the device is still open */
-               if (test_bit(1, &li->li_file->fi_flags))
+               if (test_bit(FI_FLAG_OPEN, &li->li_file->fi_flags))
                        add_to_astqueue(li, li->li_castaddr, li->li_castparam,
                                        lvb_updated);
 
@@ -449,7 +553,7 @@ static int dlm_open(struct inode *inode, struct file *file)
        f->fi_ls = lsinfo;
        f->fi_flags = 0;
        get_file_info(f);
-       set_bit(1, &f->fi_flags);
+       set_bit(FI_FLAG_OPEN, &f->fi_flags);
 
        file->private_data = f;
 
@@ -494,7 +598,7 @@ static int dlm_close(struct inode *inode, struct file *file)
                return -ENOENT;
 
        /* Mark this closed so that ASTs will not be delivered any more */
-       clear_bit(1, &f->fi_flags);
+       clear_bit(FI_FLAG_OPEN, &f->fi_flags);
 
        /* Block signals while we are doing this */
        sigfillset(&allsigs);
@@ -643,11 +747,18 @@ static ssize_t dlm_read(struct file *file, char __user *buffer, size_t count,
 {
        struct file_info *fi = file->private_data;
        struct ast_info *ast;
+       void *data;
        int data_size;
+       int struct_size;
        int offset;
        DECLARE_WAITQUEUE(wait, current);
+#ifdef CONFIG_COMPAT
+       struct dlm_lock_result32 result32;
 
+       if (count < sizeof(struct dlm_lock_result32))
+#else
        if (count < sizeof(struct dlm_lock_result))
+#endif
                return -EINVAL;
 
        spin_lock(&fi->fi_ast_lock);
@@ -691,11 +802,21 @@ static ssize_t dlm_read(struct file *file, char __user *buffer, size_t count,
        spin_unlock(&fi->fi_ast_lock);
 
        /* Work out the size of the returned data */
-       data_size = sizeof(struct dlm_lock_result);
+#ifdef CONFIG_COMPAT
+       if (test_bit(FI_FLAG_COMPAT, &fi->fi_flags)) {
+               data_size = struct_size = sizeof(struct dlm_lock_result32);
+               data = &result32;
+       }
+       else
+#endif
+       {
+               data_size = struct_size = sizeof(struct dlm_lock_result);
+               data = &ast->result;
+       }
        if (ast->lvb_updated && ast->result.lksb.sb_lvbptr)
                data_size += DLM_USER_LVB_LEN;
 
-       offset = sizeof(struct dlm_lock_result);
+       offset = struct_size;
 
        /* Room for the extended data ? */
        if (count >= data_size) {
@@ -711,8 +832,13 @@ static ssize_t dlm_read(struct file *file, char __user *buffer, size_t count,
        }
 
        ast->result.length = data_size;
+
+#ifdef CONFIG_COMPAT
+       compat_output(&ast->result, &result32);
+#endif
+
        /* Copy the header now it has all the offsets in it */
-       if (copy_to_user(buffer, &ast->result, sizeof(struct dlm_lock_result)))
+       if (copy_to_user(buffer, data, struct_size))
                offset = -EFAULT;
 
        /* If we only returned a header and there's more to come then put it
@@ -970,8 +1096,14 @@ static ssize_t dlm_write(struct file *file, const char __user *buffer,
        sigset_t allsigs;
        int status;
 
-       /* -1 because lock name is optional */
-       if (count < sizeof(struct dlm_write_request)-1)
+#ifdef CONFIG_COMPAT
+       if (count < sizeof(struct dlm_write_request32))
+#else
+       if (count < sizeof(struct dlm_write_request))
+#endif
+               return -EINVAL;
+
+       if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN)
                return -EINVAL;
 
        /* Has the lockspace been deleted */
@@ -991,6 +1123,20 @@ static ssize_t dlm_write(struct file *file, const char __user *buffer,
        if (check_version(kparams))
                goto out_free;
 
+#ifdef CONFIG_COMPAT
+       if (!kparams->is64bit) {
+               struct dlm_write_request32 *k32params = (struct dlm_write_request32 *)kparams;
+               kparams = kmalloc(count + (sizeof(struct dlm_write_request) - sizeof(struct dlm_write_request32)), GFP_KERNEL);
+               if (!kparams)
+                       return -ENOMEM;
+
+               if (fi)
+                       set_bit(FI_FLAG_COMPAT, &fi->fi_flags);
+               compat_input(kparams, k32params);
+               kfree(k32params);
+       }
+#endif
+
        /* Block signals while we are doing this */
        sigfillset(&allsigs);
        sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
index f8ba198..2a2dd18 100644 (file)
 #define DLM_USER_LVB_LEN       32
 
 /* Version of the device interface */
-#define DLM_DEVICE_VERSION_MAJOR 4
+#define DLM_DEVICE_VERSION_MAJOR 5
 #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;
        __u32 lkid;
        __u32 parent;
-       __u8 namelen;
         void __user *castparam;
        void __user *castaddr;
        void __user *bastparam;
         void __user *bastaddr;
        struct dlm_lksb __user *lksb;
        char lvb[DLM_USER_LVB_LEN];
-       char name[1];
+       char name[0];
 };
 
 struct dlm_lspace_params {
        __u32 flags;
        __u32 minor;
-       char name[1];
+       char name[0];
 };
 
 struct dlm_write_request {
        __u32 version[3];
        __u8 cmd;
+       __u8 is64bit;
+       __u8 unused[2];
 
        union  {
                struct dlm_lock_params   lock;
@@ -63,6 +65,7 @@ struct dlm_lock_result {
        struct dlm_lksb __user * user_lksb;
        struct dlm_lksb lksb;
        __u8 bast_mode;
+       __u8 unused[3];
        /* Offsets may be zero if no data is present */
        __u32 lvb_offset;
 };