aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2014-10-17 12:05:50 -0400
committerDavid Teigland <teigland@redhat.com>2014-11-19 15:48:02 -0500
commit2ab4bd8ea3a6954bc79a9bbeb291cd6c2d6213a7 (patch)
treec15e4590760ba76c29f2fca34c1b1edf82186cbd /fs/dlm
parent206c5f60a3d902bc4b56dab2de3e88de5eb06108 (diff)
dlm: adopt orphan locks
A process may exit, leaving an orphan lock in the lockspace. This adds the capability for another process to acquire the orphan lock. Acquiring the orphan just moves the lock from the orphan list onto the acquiring process's list of locks. An adopting process must specify the resource name and mode of the lock it wants to adopt. If a matching lock is found, the lock is moved to the caller's 's list of locks, and the lkid of the lock is returned like the lkid of a new lock. If an orphan with a different mode is found, then -EAGAIN is returned. If no orphan lock is found on the resource, then -ENOENT is returned. No async completion is used because the result is immediately available. Also, when orphans are purged, allow a zero nodeid to refer to the local nodeid so the caller does not need to look up the local nodeid. Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/lock.c76
-rw-r--r--fs/dlm/lock.h3
-rw-r--r--fs/dlm/user.c13
3 files changed, 88 insertions, 4 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 83f3d5520307..35502d4046f5 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -5886,6 +5886,78 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
5886 return error; 5886 return error;
5887} 5887}
5888 5888
5889/*
5890 * The caller asks for an orphan lock on a given resource with a given mode.
5891 * If a matching lock exists, it's moved to the owner's list of locks and
5892 * the lkid is returned.
5893 */
5894
5895int dlm_user_adopt_orphan(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
5896 int mode, uint32_t flags, void *name, unsigned int namelen,
5897 unsigned long timeout_cs, uint32_t *lkid)
5898{
5899 struct dlm_lkb *lkb;
5900 struct dlm_user_args *ua;
5901 int found_other_mode = 0;
5902 int found = 0;
5903 int rv = 0;
5904
5905 mutex_lock(&ls->ls_orphans_mutex);
5906 list_for_each_entry(lkb, &ls->ls_orphans, lkb_ownqueue) {
5907 if (lkb->lkb_resource->res_length != namelen)
5908 continue;
5909 if (memcmp(lkb->lkb_resource->res_name, name, namelen))
5910 continue;
5911 if (lkb->lkb_grmode != mode) {
5912 found_other_mode = 1;
5913 continue;
5914 }
5915
5916 found = 1;
5917 list_del_init(&lkb->lkb_ownqueue);
5918 lkb->lkb_flags &= ~DLM_IFL_ORPHAN;
5919 *lkid = lkb->lkb_id;
5920 break;
5921 }
5922 mutex_unlock(&ls->ls_orphans_mutex);
5923
5924 if (!found && found_other_mode) {
5925 rv = -EAGAIN;
5926 goto out;
5927 }
5928
5929 if (!found) {
5930 rv = -ENOENT;
5931 goto out;
5932 }
5933
5934 lkb->lkb_exflags = flags;
5935 lkb->lkb_ownpid = (int) current->pid;
5936
5937 ua = lkb->lkb_ua;
5938
5939 ua->proc = ua_tmp->proc;
5940 ua->xid = ua_tmp->xid;
5941 ua->castparam = ua_tmp->castparam;
5942 ua->castaddr = ua_tmp->castaddr;
5943 ua->bastparam = ua_tmp->bastparam;
5944 ua->bastaddr = ua_tmp->bastaddr;
5945 ua->user_lksb = ua_tmp->user_lksb;
5946
5947 /*
5948 * The lkb reference from the ls_orphans list was not
5949 * removed above, and is now considered the reference
5950 * for the proc locks list.
5951 */
5952
5953 spin_lock(&ua->proc->locks_spin);
5954 list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks);
5955 spin_unlock(&ua->proc->locks_spin);
5956 out:
5957 kfree(ua_tmp);
5958 return rv;
5959}
5960
5889int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 5961int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
5890 uint32_t flags, uint32_t lkid, char *lvb_in) 5962 uint32_t flags, uint32_t lkid, char *lvb_in)
5891{ 5963{
@@ -6029,7 +6101,7 @@ static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
6029 struct dlm_args args; 6101 struct dlm_args args;
6030 int error; 6102 int error;
6031 6103
6032 hold_lkb(lkb); 6104 hold_lkb(lkb); /* reference for the ls_orphans list */
6033 mutex_lock(&ls->ls_orphans_mutex); 6105 mutex_lock(&ls->ls_orphans_mutex);
6034 list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans); 6106 list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans);
6035 mutex_unlock(&ls->ls_orphans_mutex); 6107 mutex_unlock(&ls->ls_orphans_mutex);
@@ -6217,7 +6289,7 @@ int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
6217{ 6289{
6218 int error = 0; 6290 int error = 0;
6219 6291
6220 if (nodeid != dlm_our_nodeid()) { 6292 if (nodeid && (nodeid != dlm_our_nodeid())) {
6221 error = send_purge(ls, nodeid, pid); 6293 error = send_purge(ls, nodeid, pid);
6222 } else { 6294 } else {
6223 dlm_lock_recovery(ls); 6295 dlm_lock_recovery(ls);
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
index 5e0c72e36a9b..ed8ebd3a8593 100644
--- a/fs/dlm/lock.h
+++ b/fs/dlm/lock.h
@@ -49,6 +49,9 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
49int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 49int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
50 int mode, uint32_t flags, uint32_t lkid, char *lvb_in, 50 int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
51 unsigned long timeout_cs); 51 unsigned long timeout_cs);
52int dlm_user_adopt_orphan(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
53 int mode, uint32_t flags, void *name, unsigned int namelen,
54 unsigned long timeout_cs, uint32_t *lkid);
52int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 55int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
53 uint32_t flags, uint32_t lkid, char *lvb_in); 56 uint32_t flags, uint32_t lkid, char *lvb_in);
54int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 57int 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 142e21655eed..fb85f32e9eca 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -238,6 +238,7 @@ static int device_user_lock(struct dlm_user_proc *proc,
238{ 238{
239 struct dlm_ls *ls; 239 struct dlm_ls *ls;
240 struct dlm_user_args *ua; 240 struct dlm_user_args *ua;
241 uint32_t lkid;
241 int error = -ENOMEM; 242 int error = -ENOMEM;
242 243
243 ls = dlm_find_lockspace_local(proc->lockspace); 244 ls = dlm_find_lockspace_local(proc->lockspace);
@@ -260,12 +261,20 @@ static int device_user_lock(struct dlm_user_proc *proc,
260 ua->bastaddr = params->bastaddr; 261 ua->bastaddr = params->bastaddr;
261 ua->xid = params->xid; 262 ua->xid = params->xid;
262 263
263 if (params->flags & DLM_LKF_CONVERT) 264 if (params->flags & DLM_LKF_CONVERT) {
264 error = dlm_user_convert(ls, ua, 265 error = dlm_user_convert(ls, ua,
265 params->mode, params->flags, 266 params->mode, params->flags,
266 params->lkid, params->lvb, 267 params->lkid, params->lvb,
267 (unsigned long) params->timeout); 268 (unsigned long) params->timeout);
268 else { 269 } else if (params->flags & DLM_LKF_ORPHAN) {
270 error = dlm_user_adopt_orphan(ls, ua,
271 params->mode, params->flags,
272 params->name, params->namelen,
273 (unsigned long) params->timeout,
274 &lkid);
275 if (!error)
276 error = lkid;
277 } else {
269 error = dlm_user_request(ls, ua, 278 error = dlm_user_request(ls, ua,
270 params->mode, params->flags, 279 params->mode, params->flags,
271 params->name, params->namelen, 280 params->name, params->namelen,