aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorPatrick Caulfield <pcaulfie@redhat.com>2006-06-19 16:27:52 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-06-19 16:27:52 -0400
commit9f5aa2a921797ce6eb4542c7517915bd1d5fbd0b (patch)
tree69989c1aa9c05af3589e8b2b7c167a81626cb853 /fs
parentb61dde795f120f5dca2c865a1860dd9ff76705a1 (diff)
[DLM] Fix potential conflict in DLM userland locks
Just spotted this one. The lockinfo structs are hashed by lockid but into a global structure. So that if there are two lockspaces with the same lockid all hell breaks loose. I'm not exactly sure what will happen but it can't be good! The attached patch moves the lockinfo_idr into the user_ls structure so that lockids are localised. patrick Signed-Off-By: Patrick Caulfield <pcaulfie@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/dlm/device.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/fs/dlm/device.c b/fs/dlm/device.c
index 47798fe46d72..825bbc0a09c0 100644
--- a/fs/dlm/device.c
+++ b/fs/dlm/device.c
@@ -45,10 +45,6 @@ static const char *name_prefix="dlm";
45static struct list_head user_ls_list; 45static struct list_head user_ls_list;
46static struct mutex user_ls_lock; 46static struct mutex user_ls_lock;
47 47
48/* Lock infos are stored in here indexed by lock ID */
49static DEFINE_IDR(lockinfo_idr);
50static rwlock_t lockinfo_lock;
51
52/* Flags in li_flags */ 48/* Flags in li_flags */
53#define LI_FLAG_COMPLETE 1 49#define LI_FLAG_COMPLETE 1
54#define LI_FLAG_FIRSTLOCK 2 50#define LI_FLAG_FIRSTLOCK 2
@@ -99,6 +95,10 @@ struct user_ls {
99 atomic_t ls_refcnt; 95 atomic_t ls_refcnt;
100 long ls_flags; 96 long ls_flags;
101 97
98 /* Lock infos are stored in here indexed by lock ID */
99 struct idr lockinfo_idr;
100 rwlock_t lockinfo_lock;
101
102 /* Passed into misc_register() */ 102 /* Passed into misc_register() */
103 struct miscdevice ls_miscinfo; 103 struct miscdevice ls_miscinfo;
104 struct list_head ls_list; 104 struct list_head ls_list;
@@ -240,13 +240,13 @@ static void put_file_info(struct file_info *f)
240 kfree(f); 240 kfree(f);
241} 241}
242 242
243static void release_lockinfo(struct lock_info *li) 243static void release_lockinfo(struct user_ls *ls, struct lock_info *li)
244{ 244{
245 put_file_info(li->li_file); 245 put_file_info(li->li_file);
246 246
247 write_lock(&lockinfo_lock); 247 write_lock(&ls->lockinfo_lock);
248 idr_remove(&lockinfo_idr, li->li_lksb.sb_lkid); 248 idr_remove(&ls->lockinfo_idr, li->li_lksb.sb_lkid);
249 write_unlock(&lockinfo_lock); 249 write_unlock(&ls->lockinfo_lock);
250 250
251 if (li->li_lksb.sb_lvbptr) 251 if (li->li_lksb.sb_lvbptr)
252 kfree(li->li_lksb.sb_lvbptr); 252 kfree(li->li_lksb.sb_lvbptr);
@@ -255,46 +255,46 @@ static void release_lockinfo(struct lock_info *li)
255 module_put(THIS_MODULE); 255 module_put(THIS_MODULE);
256} 256}
257 257
258static struct lock_info *get_lockinfo(uint32_t lockid) 258static struct lock_info *get_lockinfo(struct user_ls *ls, uint32_t lockid)
259{ 259{
260 struct lock_info *li; 260 struct lock_info *li;
261 261
262 read_lock(&lockinfo_lock); 262 read_lock(&ls->lockinfo_lock);
263 li = idr_find(&lockinfo_idr, lockid); 263 li = idr_find(&ls->lockinfo_idr, lockid);
264 read_unlock(&lockinfo_lock); 264 read_unlock(&ls->lockinfo_lock);
265 265
266 return li; 266 return li;
267} 267}
268 268
269static int add_lockinfo(struct lock_info *li) 269static int add_lockinfo(struct user_ls *ls, struct lock_info *li)
270{ 270{
271 int n; 271 int n;
272 int r; 272 int r;
273 int ret = -EINVAL; 273 int ret = -EINVAL;
274 274
275 write_lock(&lockinfo_lock); 275 write_lock(&ls->lockinfo_lock);
276 276
277 if (idr_find(&lockinfo_idr, li->li_lksb.sb_lkid)) 277 if (idr_find(&ls->lockinfo_idr, li->li_lksb.sb_lkid))
278 goto out_up; 278 goto out_up;
279 279
280 ret = -ENOMEM; 280 ret = -ENOMEM;
281 r = idr_pre_get(&lockinfo_idr, GFP_KERNEL); 281 r = idr_pre_get(&ls->lockinfo_idr, GFP_KERNEL);
282 if (!r) 282 if (!r)
283 goto out_up; 283 goto out_up;
284 284
285 r = idr_get_new_above(&lockinfo_idr, li, li->li_lksb.sb_lkid, &n); 285 r = idr_get_new_above(&ls->lockinfo_idr, li, li->li_lksb.sb_lkid, &n);
286 if (r) 286 if (r)
287 goto out_up; 287 goto out_up;
288 288
289 if (n != li->li_lksb.sb_lkid) { 289 if (n != li->li_lksb.sb_lkid) {
290 idr_remove(&lockinfo_idr, n); 290 idr_remove(&ls->lockinfo_idr, n);
291 goto out_up; 291 goto out_up;
292 } 292 }
293 293
294 ret = 0; 294 ret = 0;
295 295
296 out_up: 296 out_up:
297 write_unlock(&lockinfo_lock); 297 write_unlock(&ls->lockinfo_lock);
298 298
299 return ret; 299 return ret;
300} 300}
@@ -358,6 +358,9 @@ static int register_lockspace(char *name, struct user_ls **ls, int flags)
358 return status; 358 return status;
359 } 359 }
360 360
361 idr_init(&newls->lockinfo_idr);
362 rwlock_init(&newls->lockinfo_lock);
363
361 snprintf((char*)newls->ls_miscinfo.name, namelen, "%s_%s", 364 snprintf((char*)newls->ls_miscinfo.name, namelen, "%s_%s",
362 name_prefix, name); 365 name_prefix, name);
363 366
@@ -486,13 +489,13 @@ static void ast_routine(void *param)
486 list_del(&li->li_ownerqueue); 489 list_del(&li->li_ownerqueue);
487 clear_bit(LI_FLAG_ONLIST, &li->li_flags); 490 clear_bit(LI_FLAG_ONLIST, &li->li_flags);
488 spin_unlock(&li->li_file->fi_li_lock); 491 spin_unlock(&li->li_file->fi_li_lock);
489 release_lockinfo(li); 492 release_lockinfo(li->li_file->fi_ls, li);
490 return; 493 return;
491 } 494 }
492 /* Free unlocks & queries */ 495 /* Free unlocks & queries */
493 if (li->li_lksb.sb_status == -DLM_EUNLOCK || 496 if (li->li_lksb.sb_status == -DLM_EUNLOCK ||
494 li->li_cmd == DLM_USER_QUERY) { 497 li->li_cmd == DLM_USER_QUERY) {
495 release_lockinfo(li); 498 release_lockinfo(li->li_file->fi_ls, li);
496 } 499 }
497 } else { 500 } else {
498 /* Synchronous request, just wake up the caller */ 501 /* Synchronous request, just wake up the caller */
@@ -641,7 +644,7 @@ static int dlm_close(struct inode *inode, struct file *file)
641 old_li->li_lksb.sb_lkid, status); 644 old_li->li_lksb.sb_lkid, status);
642 645
643 /* But tidy our references in it */ 646 /* But tidy our references in it */
644 release_lockinfo(old_li); 647 release_lockinfo(old_li->li_file->fi_ls, old_li);
645 continue; 648 continue;
646 } 649 }
647 650
@@ -662,7 +665,7 @@ static int dlm_close(struct inode *inode, struct file *file)
662 665
663 /* Unlock suceeded, free the lock_info struct. */ 666 /* Unlock suceeded, free the lock_info struct. */
664 if (status == 0) 667 if (status == 0)
665 release_lockinfo(old_li); 668 release_lockinfo(old_li->li_file->fi_ls, old_li);
666 } 669 }
667 670
668 remove_wait_queue(&li.li_waitq, &wq); 671 remove_wait_queue(&li.li_waitq, &wq);
@@ -920,7 +923,7 @@ static int do_user_lock(struct file_info *fi, uint8_t cmd,
920 unless we are adopting an orphaned persistent lock */ 923 unless we are adopting an orphaned persistent lock */
921 if (kparams->flags & DLM_LKF_CONVERT) { 924 if (kparams->flags & DLM_LKF_CONVERT) {
922 925
923 li = get_lockinfo(kparams->lkid); 926 li = get_lockinfo(fi->fi_ls, kparams->lkid);
924 927
925 /* If this is a persistent lock we will have to create a 928 /* If this is a persistent lock we will have to create a
926 lockinfo again */ 929 lockinfo again */
@@ -938,7 +941,7 @@ static int do_user_lock(struct file_info *fi, uint8_t cmd,
938 fail we want rid of it */ 941 fail we want rid of it */
939 init_completion(&li->li_firstcomp); 942 init_completion(&li->li_firstcomp);
940 set_bit(LI_FLAG_FIRSTLOCK, &li->li_flags); 943 set_bit(LI_FLAG_FIRSTLOCK, &li->li_flags);
941 add_lockinfo(li); 944 add_lockinfo(fi->fi_ls, li);
942 945
943 /* TODO: do a query to get the current state ?? */ 946 /* TODO: do a query to get the current state ?? */
944 } 947 }
@@ -1014,7 +1017,7 @@ static int do_user_lock(struct file_info *fi, uint8_t cmd,
1014 list_add(&li->li_ownerqueue, &fi->fi_li_list); 1017 list_add(&li->li_ownerqueue, &fi->fi_li_list);
1015 set_bit(LI_FLAG_ONLIST, &li->li_flags); 1018 set_bit(LI_FLAG_ONLIST, &li->li_flags);
1016 spin_unlock(&fi->fi_li_lock); 1019 spin_unlock(&fi->fi_li_lock);
1017 if (add_lockinfo(li)) 1020 if (add_lockinfo(fi->fi_ls, li))
1018 printk(KERN_WARNING "Add lockinfo failed\n"); 1021 printk(KERN_WARNING "Add lockinfo failed\n");
1019 1022
1020 complete(&li->li_firstcomp); 1023 complete(&li->li_firstcomp);
@@ -1025,7 +1028,7 @@ static int do_user_lock(struct file_info *fi, uint8_t cmd,
1025 1028
1026 out_err: 1029 out_err:
1027 if (test_bit(LI_FLAG_FIRSTLOCK, &li->li_flags)) 1030 if (test_bit(LI_FLAG_FIRSTLOCK, &li->li_flags))
1028 release_lockinfo(li); 1031 release_lockinfo(fi->fi_ls, li);
1029 return status; 1032 return status;
1030 1033
1031} 1034}
@@ -1037,7 +1040,7 @@ static int do_user_unlock(struct file_info *fi, uint8_t cmd,
1037 int status; 1040 int status;
1038 int convert_cancel = 0; 1041 int convert_cancel = 0;
1039 1042
1040 li = get_lockinfo(kparams->lkid); 1043 li = get_lockinfo(fi->fi_ls, kparams->lkid);
1041 if (!li) { 1044 if (!li) {
1042 li = allocate_lockinfo(fi, cmd, kparams); 1045 li = allocate_lockinfo(fi, cmd, kparams);
1043 if (!li) 1046 if (!li)
@@ -1209,7 +1212,6 @@ static int __init dlm_device_init(void)
1209 1212
1210 INIT_LIST_HEAD(&user_ls_list); 1213 INIT_LIST_HEAD(&user_ls_list);
1211 mutex_init(&user_ls_lock); 1214 mutex_init(&user_ls_lock);
1212 rwlock_init(&lockinfo_lock);
1213 1215
1214 ctl_device.name = "dlm-control"; 1216 ctl_device.name = "dlm-control";
1215 ctl_device.fops = &_dlm_ctl_fops; 1217 ctl_device.fops = &_dlm_ctl_fops;