diff options
author | David Teigland <teigland@redhat.com> | 2007-05-18 10:00:32 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2007-07-09 03:22:36 -0400 |
commit | d7db923ea4990edb5583bf54af868ba687a1bc84 (patch) | |
tree | 3efa0db00a3a6400f43a65aef2726fa813f9dfa2 /fs/dlm | |
parent | 3ae1acf93a21512512f8a78430fcde5992dd208e (diff) |
[DLM] dlm_device interface changes [3/6]
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>
Diffstat (limited to 'fs/dlm')
-rw-r--r-- | fs/dlm/dlm_internal.h | 2 | ||||
-rw-r--r-- | fs/dlm/lock.c | 24 | ||||
-rw-r--r-- | fs/dlm/lock.h | 6 | ||||
-rw-r--r-- | fs/dlm/user.c | 53 |
4 files changed, 62 insertions, 23 deletions
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 65a5fc076b8a..a8d6e993697c 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -151,6 +151,7 @@ struct dlm_args { | |||
151 | void *bastaddr; | 151 | void *bastaddr; |
152 | int mode; | 152 | int mode; |
153 | struct dlm_lksb *lksb; | 153 | struct dlm_lksb *lksb; |
154 | unsigned long timeout; | ||
154 | }; | 155 | }; |
155 | 156 | ||
156 | 157 | ||
@@ -528,6 +529,7 @@ struct dlm_user_args { | |||
528 | void __user *castaddr; | 529 | void __user *castaddr; |
529 | void __user *bastparam; | 530 | void __user *bastparam; |
530 | void __user *bastaddr; | 531 | void __user *bastaddr; |
532 | uint64_t xid; | ||
531 | }; | 533 | }; |
532 | 534 | ||
533 | #define DLM_PROC_FLAGS_CLOSING 1 | 535 | #define DLM_PROC_FLAGS_CLOSING 1 |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index ab986dfbe6d3..ad3797a37942 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
@@ -1098,6 +1098,8 @@ void dlm_scan_timeout(struct dlm_ls *ls) | |||
1098 | } | 1098 | } |
1099 | 1099 | ||
1100 | if (do_cancel) { | 1100 | if (do_cancel) { |
1101 | log_debug("timeout cancel %x node %d %s", lkb->lkb_id, | ||
1102 | lkb->lkb_nodeid, r->res_name); | ||
1101 | lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN; | 1103 | lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN; |
1102 | lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL; | 1104 | lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL; |
1103 | del_timeout(lkb); | 1105 | del_timeout(lkb); |
@@ -1864,7 +1866,7 @@ static void confirm_master(struct dlm_rsb *r, int error) | |||
1864 | } | 1866 | } |
1865 | 1867 | ||
1866 | static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, | 1868 | static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, |
1867 | int namelen, uint32_t parent_lkid, void *ast, | 1869 | int namelen, unsigned long timeout_cs, void *ast, |
1868 | void *astarg, void *bast, struct dlm_args *args) | 1870 | void *astarg, void *bast, struct dlm_args *args) |
1869 | { | 1871 | { |
1870 | int rv = -EINVAL; | 1872 | int rv = -EINVAL; |
@@ -1907,10 +1909,6 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, | |||
1907 | if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr) | 1909 | if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr) |
1908 | goto out; | 1910 | goto out; |
1909 | 1911 | ||
1910 | /* parent/child locks not yet supported */ | ||
1911 | if (parent_lkid) | ||
1912 | goto out; | ||
1913 | |||
1914 | if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid) | 1912 | if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid) |
1915 | goto out; | 1913 | goto out; |
1916 | 1914 | ||
@@ -1922,6 +1920,7 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, | |||
1922 | args->astaddr = ast; | 1920 | args->astaddr = ast; |
1923 | args->astparam = (long) astarg; | 1921 | args->astparam = (long) astarg; |
1924 | args->bastaddr = bast; | 1922 | args->bastaddr = bast; |
1923 | args->timeout = timeout_cs; | ||
1925 | args->mode = mode; | 1924 | args->mode = mode; |
1926 | args->lksb = lksb; | 1925 | args->lksb = lksb; |
1927 | rv = 0; | 1926 | rv = 0; |
@@ -1976,6 +1975,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
1976 | lkb->lkb_lksb = args->lksb; | 1975 | lkb->lkb_lksb = args->lksb; |
1977 | lkb->lkb_lvbptr = args->lksb->sb_lvbptr; | 1976 | lkb->lkb_lvbptr = args->lksb->sb_lvbptr; |
1978 | lkb->lkb_ownpid = (int) current->pid; | 1977 | lkb->lkb_ownpid = (int) current->pid; |
1978 | lkb->lkb_timeout_cs = args->timeout; | ||
1979 | rv = 0; | 1979 | rv = 0; |
1980 | out: | 1980 | out: |
1981 | return rv; | 1981 | return rv; |
@@ -2423,7 +2423,7 @@ int dlm_lock(dlm_lockspace_t *lockspace, | |||
2423 | if (error) | 2423 | if (error) |
2424 | goto out; | 2424 | goto out; |
2425 | 2425 | ||
2426 | error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast, | 2426 | error = set_lock_args(mode, lksb, flags, namelen, 0, ast, |
2427 | astarg, bast, &args); | 2427 | astarg, bast, &args); |
2428 | if (error) | 2428 | if (error) |
2429 | goto out_put; | 2429 | goto out_put; |
@@ -4175,7 +4175,7 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc) | |||
4175 | 4175 | ||
4176 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | 4176 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, |
4177 | int mode, uint32_t flags, void *name, unsigned int namelen, | 4177 | int mode, uint32_t flags, void *name, unsigned int namelen, |
4178 | uint32_t parent_lkid) | 4178 | unsigned long timeout_cs) |
4179 | { | 4179 | { |
4180 | struct dlm_lkb *lkb; | 4180 | struct dlm_lkb *lkb; |
4181 | struct dlm_args args; | 4181 | struct dlm_args args; |
@@ -4203,7 +4203,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | |||
4203 | When DLM_IFL_USER is set, the dlm knows that this is a userspace | 4203 | When DLM_IFL_USER is set, the dlm knows that this is a userspace |
4204 | lock and that lkb_astparam is the dlm_user_args structure. */ | 4204 | lock and that lkb_astparam is the dlm_user_args structure. */ |
4205 | 4205 | ||
4206 | error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid, | 4206 | error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs, |
4207 | DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); | 4207 | DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); |
4208 | lkb->lkb_flags |= DLM_IFL_USER; | 4208 | lkb->lkb_flags |= DLM_IFL_USER; |
4209 | ua->old_mode = DLM_LOCK_IV; | 4209 | ua->old_mode = DLM_LOCK_IV; |
@@ -4240,7 +4240,8 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | |||
4240 | } | 4240 | } |
4241 | 4241 | ||
4242 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 4242 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
4243 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in) | 4243 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in, |
4244 | unsigned long timeout_cs) | ||
4244 | { | 4245 | { |
4245 | struct dlm_lkb *lkb; | 4246 | struct dlm_lkb *lkb; |
4246 | struct dlm_args args; | 4247 | struct dlm_args args; |
@@ -4268,6 +4269,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4268 | if (lvb_in && ua->lksb.sb_lvbptr) | 4269 | if (lvb_in && ua->lksb.sb_lvbptr) |
4269 | memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); | 4270 | memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); |
4270 | 4271 | ||
4272 | ua->xid = ua_tmp->xid; | ||
4271 | ua->castparam = ua_tmp->castparam; | 4273 | ua->castparam = ua_tmp->castparam; |
4272 | ua->castaddr = ua_tmp->castaddr; | 4274 | ua->castaddr = ua_tmp->castaddr; |
4273 | ua->bastparam = ua_tmp->bastparam; | 4275 | ua->bastparam = ua_tmp->bastparam; |
@@ -4275,8 +4277,8 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4275 | ua->user_lksb = ua_tmp->user_lksb; | 4277 | ua->user_lksb = ua_tmp->user_lksb; |
4276 | ua->old_mode = lkb->lkb_grmode; | 4278 | ua->old_mode = lkb->lkb_grmode; |
4277 | 4279 | ||
4278 | error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST, | 4280 | error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs, |
4279 | ua, DLM_FAKE_USER_AST, &args); | 4281 | DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); |
4280 | if (error) | 4282 | if (error) |
4281 | goto out_put; | 4283 | goto out_put; |
4282 | 4284 | ||
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h index 6b5b71f0e9dd..99ab4635074e 100644 --- a/fs/dlm/lock.h +++ b/fs/dlm/lock.h | |||
@@ -38,9 +38,11 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc); | |||
38 | int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc); | 38 | int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc); |
39 | 39 | ||
40 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode, | 40 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode, |
41 | uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid); | 41 | uint32_t flags, void *name, unsigned int namelen, |
42 | unsigned long timeout_cs); | ||
42 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 43 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
43 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in); | 44 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in, |
45 | unsigned long timeout_cs); | ||
44 | int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 46 | int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
45 | uint32_t flags, uint32_t lkid, char *lvb_in); | 47 | uint32_t flags, uint32_t lkid, char *lvb_in); |
46 | int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 48 | int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index c7612da5b617..37aad3fe8949 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -33,16 +33,17 @@ static const struct file_operations device_fops; | |||
33 | struct dlm_lock_params32 { | 33 | struct dlm_lock_params32 { |
34 | __u8 mode; | 34 | __u8 mode; |
35 | __u8 namelen; | 35 | __u8 namelen; |
36 | __u16 flags; | 36 | __u16 unused; |
37 | __u32 flags; | ||
37 | __u32 lkid; | 38 | __u32 lkid; |
38 | __u32 parent; | 39 | __u32 parent; |
39 | 40 | __u64 xid; | |
41 | __u64 timeout; | ||
40 | __u32 castparam; | 42 | __u32 castparam; |
41 | __u32 castaddr; | 43 | __u32 castaddr; |
42 | __u32 bastparam; | 44 | __u32 bastparam; |
43 | __u32 bastaddr; | 45 | __u32 bastaddr; |
44 | __u32 lksb; | 46 | __u32 lksb; |
45 | |||
46 | char lvb[DLM_USER_LVB_LEN]; | 47 | char lvb[DLM_USER_LVB_LEN]; |
47 | char name[0]; | 48 | char name[0]; |
48 | }; | 49 | }; |
@@ -68,6 +69,7 @@ struct dlm_lksb32 { | |||
68 | }; | 69 | }; |
69 | 70 | ||
70 | struct dlm_lock_result32 { | 71 | struct dlm_lock_result32 { |
72 | __u32 version[3]; | ||
71 | __u32 length; | 73 | __u32 length; |
72 | __u32 user_astaddr; | 74 | __u32 user_astaddr; |
73 | __u32 user_astparam; | 75 | __u32 user_astparam; |
@@ -102,6 +104,8 @@ static void compat_input(struct dlm_write_request *kb, | |||
102 | kb->i.lock.flags = kb32->i.lock.flags; | 104 | kb->i.lock.flags = kb32->i.lock.flags; |
103 | kb->i.lock.lkid = kb32->i.lock.lkid; | 105 | kb->i.lock.lkid = kb32->i.lock.lkid; |
104 | kb->i.lock.parent = kb32->i.lock.parent; | 106 | kb->i.lock.parent = kb32->i.lock.parent; |
107 | kb->i.lock.xid = kb32->i.lock.xid; | ||
108 | kb->i.lock.timeout = kb32->i.lock.timeout; | ||
105 | kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam; | 109 | kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam; |
106 | kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr; | 110 | kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr; |
107 | kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam; | 111 | kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam; |
@@ -115,6 +119,10 @@ static void compat_input(struct dlm_write_request *kb, | |||
115 | static void compat_output(struct dlm_lock_result *res, | 119 | static void compat_output(struct dlm_lock_result *res, |
116 | struct dlm_lock_result32 *res32) | 120 | struct dlm_lock_result32 *res32) |
117 | { | 121 | { |
122 | res32->version[0] = res->version[0]; | ||
123 | res32->version[1] = res->version[1]; | ||
124 | res32->version[2] = res->version[2]; | ||
125 | |||
118 | res32->user_astaddr = (__u32)(long)res->user_astaddr; | 126 | res32->user_astaddr = (__u32)(long)res->user_astaddr; |
119 | res32->user_astparam = (__u32)(long)res->user_astparam; | 127 | res32->user_astparam = (__u32)(long)res->user_astparam; |
120 | res32->user_lksb = (__u32)(long)res->user_lksb; | 128 | res32->user_lksb = (__u32)(long)res->user_lksb; |
@@ -252,16 +260,18 @@ static int device_user_lock(struct dlm_user_proc *proc, | |||
252 | ua->castaddr = params->castaddr; | 260 | ua->castaddr = params->castaddr; |
253 | ua->bastparam = params->bastparam; | 261 | ua->bastparam = params->bastparam; |
254 | ua->bastaddr = params->bastaddr; | 262 | ua->bastaddr = params->bastaddr; |
263 | ua->xid = params->xid; | ||
255 | 264 | ||
256 | if (params->flags & DLM_LKF_CONVERT) | 265 | if (params->flags & DLM_LKF_CONVERT) |
257 | error = dlm_user_convert(ls, ua, | 266 | error = dlm_user_convert(ls, ua, |
258 | params->mode, params->flags, | 267 | params->mode, params->flags, |
259 | params->lkid, params->lvb); | 268 | params->lkid, params->lvb, |
269 | (unsigned long) params->timeout); | ||
260 | else { | 270 | else { |
261 | error = dlm_user_request(ls, ua, | 271 | error = dlm_user_request(ls, ua, |
262 | params->mode, params->flags, | 272 | params->mode, params->flags, |
263 | params->name, params->namelen, | 273 | params->name, params->namelen, |
264 | params->parent); | 274 | (unsigned long) params->timeout); |
265 | if (!error) | 275 | if (!error) |
266 | error = ua->lksb.sb_lkid; | 276 | error = ua->lksb.sb_lkid; |
267 | } | 277 | } |
@@ -641,6 +651,9 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | |||
641 | int struct_len; | 651 | int struct_len; |
642 | 652 | ||
643 | memset(&result, 0, sizeof(struct dlm_lock_result)); | 653 | memset(&result, 0, sizeof(struct dlm_lock_result)); |
654 | result.version[0] = DLM_DEVICE_VERSION_MAJOR; | ||
655 | result.version[1] = DLM_DEVICE_VERSION_MINOR; | ||
656 | result.version[2] = DLM_DEVICE_VERSION_PATCH; | ||
644 | memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb)); | 657 | memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb)); |
645 | result.user_lksb = ua->user_lksb; | 658 | result.user_lksb = ua->user_lksb; |
646 | 659 | ||
@@ -699,6 +712,20 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | |||
699 | return error; | 712 | return error; |
700 | } | 713 | } |
701 | 714 | ||
715 | static int copy_version_to_user(char __user *buf, size_t count) | ||
716 | { | ||
717 | struct dlm_device_version ver; | ||
718 | |||
719 | memset(&ver, 0, sizeof(struct dlm_device_version)); | ||
720 | ver.version[0] = DLM_DEVICE_VERSION_MAJOR; | ||
721 | ver.version[1] = DLM_DEVICE_VERSION_MINOR; | ||
722 | ver.version[2] = DLM_DEVICE_VERSION_PATCH; | ||
723 | |||
724 | if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version))) | ||
725 | return -EFAULT; | ||
726 | return sizeof(struct dlm_device_version); | ||
727 | } | ||
728 | |||
702 | /* a read returns a single ast described in a struct dlm_lock_result */ | 729 | /* a read returns a single ast described in a struct dlm_lock_result */ |
703 | 730 | ||
704 | static ssize_t device_read(struct file *file, char __user *buf, size_t count, | 731 | 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, | |||
710 | DECLARE_WAITQUEUE(wait, current); | 737 | DECLARE_WAITQUEUE(wait, current); |
711 | int error, type=0, bmode=0, removed = 0; | 738 | int error, type=0, bmode=0, removed = 0; |
712 | 739 | ||
740 | if (count == sizeof(struct dlm_device_version)) { | ||
741 | error = copy_version_to_user(buf, count); | ||
742 | return error; | ||
743 | } | ||
744 | |||
745 | if (!proc) { | ||
746 | log_print("non-version read from control device %zu", count); | ||
747 | return -EINVAL; | ||
748 | } | ||
749 | |||
713 | #ifdef CONFIG_COMPAT | 750 | #ifdef CONFIG_COMPAT |
714 | if (count < sizeof(struct dlm_lock_result32)) | 751 | if (count < sizeof(struct dlm_lock_result32)) |
715 | #else | 752 | #else |
@@ -747,11 +784,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
747 | } | 784 | } |
748 | } | 785 | } |
749 | 786 | ||
750 | if (list_empty(&proc->asts)) { | ||
751 | spin_unlock(&proc->asts_spin); | ||
752 | return -EAGAIN; | ||
753 | } | ||
754 | |||
755 | /* there may be both completion and blocking asts to return for | 787 | /* there may be both completion and blocking asts to return for |
756 | the lkb, don't remove lkb from asts list unless no asts remain */ | 788 | the lkb, don't remove lkb from asts list unless no asts remain */ |
757 | 789 | ||
@@ -823,6 +855,7 @@ static const struct file_operations device_fops = { | |||
823 | static const struct file_operations ctl_device_fops = { | 855 | static const struct file_operations ctl_device_fops = { |
824 | .open = ctl_device_open, | 856 | .open = ctl_device_open, |
825 | .release = ctl_device_close, | 857 | .release = ctl_device_close, |
858 | .read = device_read, | ||
826 | .write = device_write, | 859 | .write = device_write, |
827 | .owner = THIS_MODULE, | 860 | .owner = THIS_MODULE, |
828 | }; | 861 | }; |