aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/device.c166
1 files changed, 156 insertions, 10 deletions
diff --git a/fs/dlm/device.c b/fs/dlm/device.c
index 49a20d549216..47798fe46d72 100644
--- a/fs/dlm/device.c
+++ b/fs/dlm/device.c
@@ -2,7 +2,7 @@
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
6** 6**
7** This copyrighted material is made available to anyone wishing to use, 7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions 8** modify, copy, or redistribute it subject to the terms and conditions
@@ -59,6 +59,9 @@ static rwlock_t lockinfo_lock;
59#define LS_FLAG_DELETED 1 59#define LS_FLAG_DELETED 1
60#define LS_FLAG_AUTOFREE 2 60#define LS_FLAG_AUTOFREE 2
61 61
62/* flags in ls_flags*/
63#define FI_FLAG_OPEN 1
64#define FI_FLAG_COMPAT 2
62 65
63#define LOCKINFO_MAGIC 0x53595324 66#define LOCKINFO_MAGIC 0x53595324
64 67
@@ -117,9 +120,110 @@ struct file_info {
117 wait_queue_head_t fi_wait; 120 wait_queue_head_t fi_wait;
118 struct user_ls *fi_ls; 121 struct user_ls *fi_ls;
119 atomic_t fi_refcnt; /* Number of users */ 122 atomic_t fi_refcnt; /* Number of users */
120 unsigned long fi_flags; /* Bit 1 means the device is open */ 123 unsigned long fi_flags;
124};
125
126#ifdef CONFIG_COMPAT
127
128struct dlm_lock_params32 {
129 __u8 mode;
130 __u8 namelen;
131 __u16 flags;
132 __u32 lkid;
133 __u32 parent;
134
135 __u32 castparam;
136 __u32 castaddr;
137 __u32 bastparam;
138 __u32 bastaddr;
139 __u32 lksb;
140
141 char lvb[DLM_USER_LVB_LEN];
142 char name[0];
121}; 143};
122 144
145struct dlm_write_request32 {
146 __u32 version[3];
147 __u8 cmd;
148 __u8 is64bit;
149 __u8 unused[2];
150
151 union {
152 struct dlm_lock_params32 lock;
153 struct dlm_lspace_params lspace;
154 } i;
155};
156
157struct dlm_lksb32 {
158 __u32 sb_status;
159 __u32 sb_lkid;
160 __u8 sb_flags;
161 __u32 sb_lvbptr;
162};
163
164struct dlm_lock_result32 {
165 __u32 length;
166 __u32 user_astaddr;
167 __u32 user_astparam;
168 __u32 user_lksb;
169 struct dlm_lksb32 lksb;
170 __u8 bast_mode;
171 __u8 unused[3];
172 /* Offsets may be zero if no data is present */
173 __u32 lvb_offset;
174};
175
176
177static void compat_input(struct dlm_write_request *kparams, struct dlm_write_request32 *k32params)
178{
179
180 kparams->version[0] = k32params->version[0];
181 kparams->version[1] = k32params->version[1];
182 kparams->version[2] = k32params->version[2];
183
184 kparams->cmd = k32params->cmd;
185 kparams->is64bit = k32params->is64bit;
186 if (kparams->cmd == DLM_USER_CREATE_LOCKSPACE ||
187 kparams->cmd == DLM_USER_REMOVE_LOCKSPACE) {
188
189 kparams->i.lspace.flags = k32params->i.lspace.flags;
190 kparams->i.lspace.minor = k32params->i.lspace.minor;
191 strcpy(kparams->i.lspace.name, k32params->i.lspace.name);
192 }
193 else {
194 kparams->i.lock.mode = k32params->i.lock.mode;
195 kparams->i.lock.namelen = k32params->i.lock.namelen;
196 kparams->i.lock.flags = k32params->i.lock.flags;
197 kparams->i.lock.lkid = k32params->i.lock.lkid;
198 kparams->i.lock.parent = k32params->i.lock.parent;
199 kparams->i.lock.castparam = (void *)(long)k32params->i.lock.castparam;
200 kparams->i.lock.castaddr = (void *)(long)k32params->i.lock.castaddr;
201 kparams->i.lock.bastparam = (void *)(long)k32params->i.lock.bastparam;
202 kparams->i.lock.bastaddr = (void *)(long)k32params->i.lock.bastaddr;
203 kparams->i.lock.lksb = (void *)(long)k32params->i.lock.lksb;
204 memcpy(kparams->i.lock.lvb, k32params->i.lock.lvb, DLM_USER_LVB_LEN);
205 memcpy(kparams->i.lock.name, k32params->i.lock.name, kparams->i.lock.namelen);
206 }
207}
208
209void compat_output(struct dlm_lock_result *res, struct dlm_lock_result32 *res32)
210{
211 res32->length = res->length - (sizeof(struct dlm_lock_result) - sizeof(struct dlm_lock_result32));
212 res32->user_astaddr = (__u32)(long)res->user_astaddr;
213 res32->user_astparam = (__u32)(long)res->user_astparam;
214 res32->user_lksb = (__u32)(long)res->user_lksb;
215 res32->bast_mode = res->bast_mode;
216
217 res32->lvb_offset = res->lvb_offset;
218 res32->length = res->length;
219
220 res32->lksb.sb_status = res->lksb.sb_status;
221 res32->lksb.sb_flags = res->lksb.sb_flags;
222 res32->lksb.sb_lkid = res->lksb.sb_lkid;
223 res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
224}
225#endif
226
123 227
124/* get and put ops for file_info. 228/* get and put ops for file_info.
125 Actually I don't really like "get" and "put", but everyone 229 Actually I don't really like "get" and "put", but everyone
@@ -364,7 +468,7 @@ static void ast_routine(void *param)
364 li->li_grmode = li->li_rqmode; 468 li->li_grmode = li->li_rqmode;
365 469
366 /* Only queue AST if the device is still open */ 470 /* Only queue AST if the device is still open */
367 if (test_bit(1, &li->li_file->fi_flags)) 471 if (test_bit(FI_FLAG_OPEN, &li->li_file->fi_flags))
368 add_to_astqueue(li, li->li_castaddr, li->li_castparam, 472 add_to_astqueue(li, li->li_castaddr, li->li_castparam,
369 lvb_updated); 473 lvb_updated);
370 474
@@ -449,7 +553,7 @@ static int dlm_open(struct inode *inode, struct file *file)
449 f->fi_ls = lsinfo; 553 f->fi_ls = lsinfo;
450 f->fi_flags = 0; 554 f->fi_flags = 0;
451 get_file_info(f); 555 get_file_info(f);
452 set_bit(1, &f->fi_flags); 556 set_bit(FI_FLAG_OPEN, &f->fi_flags);
453 557
454 file->private_data = f; 558 file->private_data = f;
455 559
@@ -494,7 +598,7 @@ static int dlm_close(struct inode *inode, struct file *file)
494 return -ENOENT; 598 return -ENOENT;
495 599
496 /* Mark this closed so that ASTs will not be delivered any more */ 600 /* Mark this closed so that ASTs will not be delivered any more */
497 clear_bit(1, &f->fi_flags); 601 clear_bit(FI_FLAG_OPEN, &f->fi_flags);
498 602
499 /* Block signals while we are doing this */ 603 /* Block signals while we are doing this */
500 sigfillset(&allsigs); 604 sigfillset(&allsigs);
@@ -643,11 +747,18 @@ static ssize_t dlm_read(struct file *file, char __user *buffer, size_t count,
643{ 747{
644 struct file_info *fi = file->private_data; 748 struct file_info *fi = file->private_data;
645 struct ast_info *ast; 749 struct ast_info *ast;
750 void *data;
646 int data_size; 751 int data_size;
752 int struct_size;
647 int offset; 753 int offset;
648 DECLARE_WAITQUEUE(wait, current); 754 DECLARE_WAITQUEUE(wait, current);
755#ifdef CONFIG_COMPAT
756 struct dlm_lock_result32 result32;
649 757
758 if (count < sizeof(struct dlm_lock_result32))
759#else
650 if (count < sizeof(struct dlm_lock_result)) 760 if (count < sizeof(struct dlm_lock_result))
761#endif
651 return -EINVAL; 762 return -EINVAL;
652 763
653 spin_lock(&fi->fi_ast_lock); 764 spin_lock(&fi->fi_ast_lock);
@@ -691,11 +802,21 @@ static ssize_t dlm_read(struct file *file, char __user *buffer, size_t count,
691 spin_unlock(&fi->fi_ast_lock); 802 spin_unlock(&fi->fi_ast_lock);
692 803
693 /* Work out the size of the returned data */ 804 /* Work out the size of the returned data */
694 data_size = sizeof(struct dlm_lock_result); 805#ifdef CONFIG_COMPAT
806 if (test_bit(FI_FLAG_COMPAT, &fi->fi_flags)) {
807 data_size = struct_size = sizeof(struct dlm_lock_result32);
808 data = &result32;
809 }
810 else
811#endif
812 {
813 data_size = struct_size = sizeof(struct dlm_lock_result);
814 data = &ast->result;
815 }
695 if (ast->lvb_updated && ast->result.lksb.sb_lvbptr) 816 if (ast->lvb_updated && ast->result.lksb.sb_lvbptr)
696 data_size += DLM_USER_LVB_LEN; 817 data_size += DLM_USER_LVB_LEN;
697 818
698 offset = sizeof(struct dlm_lock_result); 819 offset = struct_size;
699 820
700 /* Room for the extended data ? */ 821 /* Room for the extended data ? */
701 if (count >= data_size) { 822 if (count >= data_size) {
@@ -711,8 +832,13 @@ static ssize_t dlm_read(struct file *file, char __user *buffer, size_t count,
711 } 832 }
712 833
713 ast->result.length = data_size; 834 ast->result.length = data_size;
835
836#ifdef CONFIG_COMPAT
837 compat_output(&ast->result, &result32);
838#endif
839
714 /* Copy the header now it has all the offsets in it */ 840 /* Copy the header now it has all the offsets in it */
715 if (copy_to_user(buffer, &ast->result, sizeof(struct dlm_lock_result))) 841 if (copy_to_user(buffer, data, struct_size))
716 offset = -EFAULT; 842 offset = -EFAULT;
717 843
718 /* If we only returned a header and there's more to come then put it 844 /* 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,
970 sigset_t allsigs; 1096 sigset_t allsigs;
971 int status; 1097 int status;
972 1098
973 /* -1 because lock name is optional */ 1099#ifdef CONFIG_COMPAT
974 if (count < sizeof(struct dlm_write_request)-1) 1100 if (count < sizeof(struct dlm_write_request32))
1101#else
1102 if (count < sizeof(struct dlm_write_request))
1103#endif
1104 return -EINVAL;
1105
1106 if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN)
975 return -EINVAL; 1107 return -EINVAL;
976 1108
977 /* Has the lockspace been deleted */ 1109 /* Has the lockspace been deleted */
@@ -991,6 +1123,20 @@ static ssize_t dlm_write(struct file *file, const char __user *buffer,
991 if (check_version(kparams)) 1123 if (check_version(kparams))
992 goto out_free; 1124 goto out_free;
993 1125
1126#ifdef CONFIG_COMPAT
1127 if (!kparams->is64bit) {
1128 struct dlm_write_request32 *k32params = (struct dlm_write_request32 *)kparams;
1129 kparams = kmalloc(count + (sizeof(struct dlm_write_request) - sizeof(struct dlm_write_request32)), GFP_KERNEL);
1130 if (!kparams)
1131 return -ENOMEM;
1132
1133 if (fi)
1134 set_bit(FI_FLAG_COMPAT, &fi->fi_flags);
1135 compat_input(kparams, k32params);
1136 kfree(k32params);
1137 }
1138#endif
1139
994 /* Block signals while we are doing this */ 1140 /* Block signals while we are doing this */
995 sigfillset(&allsigs); 1141 sigfillset(&allsigs);
996 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig); 1142 sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);