[DLM] compat patch
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>
This commit is contained in:
parent
01eb7c0796
commit
22da645fd6
166
fs/dlm/device.c
166
fs/dlm/device.c
@ -2,7 +2,7 @@
|
|||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
** 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,
|
** This copyrighted material is made available to anyone wishing to use,
|
||||||
** modify, copy, or redistribute it subject to the terms and conditions
|
** 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_DELETED 1
|
||||||
#define LS_FLAG_AUTOFREE 2
|
#define LS_FLAG_AUTOFREE 2
|
||||||
|
|
||||||
|
/* flags in ls_flags*/
|
||||||
|
#define FI_FLAG_OPEN 1
|
||||||
|
#define FI_FLAG_COMPAT 2
|
||||||
|
|
||||||
#define LOCKINFO_MAGIC 0x53595324
|
#define LOCKINFO_MAGIC 0x53595324
|
||||||
|
|
||||||
@ -117,9 +120,110 @@ struct file_info {
|
|||||||
wait_queue_head_t fi_wait;
|
wait_queue_head_t fi_wait;
|
||||||
struct user_ls *fi_ls;
|
struct user_ls *fi_ls;
|
||||||
atomic_t fi_refcnt; /* Number of users */
|
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.
|
/* get and put ops for file_info.
|
||||||
Actually I don't really like "get" and "put", but everyone
|
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;
|
li->li_grmode = li->li_rqmode;
|
||||||
|
|
||||||
/* Only queue AST if the device is still open */
|
/* 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,
|
add_to_astqueue(li, li->li_castaddr, li->li_castparam,
|
||||||
lvb_updated);
|
lvb_updated);
|
||||||
|
|
||||||
@ -449,7 +553,7 @@ static int dlm_open(struct inode *inode, struct file *file)
|
|||||||
f->fi_ls = lsinfo;
|
f->fi_ls = lsinfo;
|
||||||
f->fi_flags = 0;
|
f->fi_flags = 0;
|
||||||
get_file_info(f);
|
get_file_info(f);
|
||||||
set_bit(1, &f->fi_flags);
|
set_bit(FI_FLAG_OPEN, &f->fi_flags);
|
||||||
|
|
||||||
file->private_data = f;
|
file->private_data = f;
|
||||||
|
|
||||||
@ -494,7 +598,7 @@ static int dlm_close(struct inode *inode, struct file *file)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* Mark this closed so that ASTs will not be delivered any more */
|
/* 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 */
|
/* Block signals while we are doing this */
|
||||||
sigfillset(&allsigs);
|
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 file_info *fi = file->private_data;
|
||||||
struct ast_info *ast;
|
struct ast_info *ast;
|
||||||
|
void *data;
|
||||||
int data_size;
|
int data_size;
|
||||||
|
int struct_size;
|
||||||
int offset;
|
int offset;
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
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))
|
if (count < sizeof(struct dlm_lock_result))
|
||||||
|
#endif
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock(&fi->fi_ast_lock);
|
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);
|
spin_unlock(&fi->fi_ast_lock);
|
||||||
|
|
||||||
/* Work out the size of the returned data */
|
/* 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)
|
if (ast->lvb_updated && ast->result.lksb.sb_lvbptr)
|
||||||
data_size += DLM_USER_LVB_LEN;
|
data_size += DLM_USER_LVB_LEN;
|
||||||
|
|
||||||
offset = sizeof(struct dlm_lock_result);
|
offset = struct_size;
|
||||||
|
|
||||||
/* Room for the extended data ? */
|
/* Room for the extended data ? */
|
||||||
if (count >= data_size) {
|
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;
|
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 */
|
/* 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;
|
offset = -EFAULT;
|
||||||
|
|
||||||
/* If we only returned a header and there's more to come then put it
|
/* 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;
|
sigset_t allsigs;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* -1 because lock name is optional */
|
#ifdef CONFIG_COMPAT
|
||||||
if (count < sizeof(struct dlm_write_request)-1)
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Has the lockspace been deleted */
|
/* 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))
|
if (check_version(kparams))
|
||||||
goto out_free;
|
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 */
|
/* Block signals while we are doing this */
|
||||||
sigfillset(&allsigs);
|
sigfillset(&allsigs);
|
||||||
sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
|
sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
|
||||||
|
@ -18,35 +18,37 @@
|
|||||||
#define DLM_USER_LVB_LEN 32
|
#define DLM_USER_LVB_LEN 32
|
||||||
|
|
||||||
/* Version of the device interface */
|
/* 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_MINOR 0
|
||||||
#define DLM_DEVICE_VERSION_PATCH 0
|
#define DLM_DEVICE_VERSION_PATCH 0
|
||||||
|
|
||||||
/* struct passed to the lock write */
|
/* struct passed to the lock write */
|
||||||
struct dlm_lock_params {
|
struct dlm_lock_params {
|
||||||
__u8 mode;
|
__u8 mode;
|
||||||
|
__u8 namelen;
|
||||||
__u16 flags;
|
__u16 flags;
|
||||||
__u32 lkid;
|
__u32 lkid;
|
||||||
__u32 parent;
|
__u32 parent;
|
||||||
__u8 namelen;
|
|
||||||
void __user *castparam;
|
void __user *castparam;
|
||||||
void __user *castaddr;
|
void __user *castaddr;
|
||||||
void __user *bastparam;
|
void __user *bastparam;
|
||||||
void __user *bastaddr;
|
void __user *bastaddr;
|
||||||
struct dlm_lksb __user *lksb;
|
struct dlm_lksb __user *lksb;
|
||||||
char lvb[DLM_USER_LVB_LEN];
|
char lvb[DLM_USER_LVB_LEN];
|
||||||
char name[1];
|
char name[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dlm_lspace_params {
|
struct dlm_lspace_params {
|
||||||
__u32 flags;
|
__u32 flags;
|
||||||
__u32 minor;
|
__u32 minor;
|
||||||
char name[1];
|
char name[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dlm_write_request {
|
struct dlm_write_request {
|
||||||
__u32 version[3];
|
__u32 version[3];
|
||||||
__u8 cmd;
|
__u8 cmd;
|
||||||
|
__u8 is64bit;
|
||||||
|
__u8 unused[2];
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct dlm_lock_params lock;
|
struct dlm_lock_params lock;
|
||||||
@ -63,6 +65,7 @@ struct dlm_lock_result {
|
|||||||
struct dlm_lksb __user * user_lksb;
|
struct dlm_lksb __user * user_lksb;
|
||||||
struct dlm_lksb lksb;
|
struct dlm_lksb lksb;
|
||||||
__u8 bast_mode;
|
__u8 bast_mode;
|
||||||
|
__u8 unused[3];
|
||||||
/* Offsets may be zero if no data is present */
|
/* Offsets may be zero if no data is present */
|
||||||
__u32 lvb_offset;
|
__u32 lvb_offset;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user