Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+89 -5
+74 -2
fs/dlm/lock.c
··· 5886 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 + 5895 + int 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 + 5889 5961 int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 5890 5962 uint32_t flags, uint32_t lkid, char *lvb_in) 5891 5963 { ··· 6101 6029 struct dlm_args args; 6102 6030 int error; 6103 6031 6104 - hold_lkb(lkb); 6032 + hold_lkb(lkb); /* reference for the ls_orphans list */ 6105 6033 mutex_lock(&ls->ls_orphans_mutex); 6106 6034 list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans); 6107 6035 mutex_unlock(&ls->ls_orphans_mutex); ··· 6289 6217 { 6290 6218 int error = 0; 6291 6219 6292 - if (nodeid != dlm_our_nodeid()) { 6220 + if (nodeid && (nodeid != dlm_our_nodeid())) { 6293 6221 error = send_purge(ls, nodeid, pid); 6294 6222 } else { 6295 6223 dlm_lock_recovery(ls);
+3
fs/dlm/lock.h
··· 49 49 int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 50 50 int mode, uint32_t flags, uint32_t lkid, char *lvb_in, 51 51 unsigned long timeout_cs); 52 + int 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); 52 55 int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 53 56 uint32_t flags, uint32_t lkid, char *lvb_in); 54 57 int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
+11 -2
fs/dlm/user.c
··· 238 238 { 239 239 struct dlm_ls *ls; 240 240 struct dlm_user_args *ua; 241 + uint32_t lkid; 241 242 int error = -ENOMEM; 242 243 243 244 ls = dlm_find_lockspace_local(proc->lockspace); ··· 261 260 ua->bastaddr = params->bastaddr; 262 261 ua->xid = params->xid; 263 262 264 - if (params->flags & DLM_LKF_CONVERT) 263 + if (params->flags & DLM_LKF_CONVERT) { 265 264 error = dlm_user_convert(ls, ua, 266 265 params->mode, params->flags, 267 266 params->lkid, params->lvb, 268 267 (unsigned long) params->timeout); 269 - else { 268 + } else if (params->flags & DLM_LKF_ORPHAN) { 269 + error = dlm_user_adopt_orphan(ls, ua, 270 + params->mode, params->flags, 271 + params->name, params->namelen, 272 + (unsigned long) params->timeout, 273 + &lkid); 274 + if (!error) 275 + error = lkid; 276 + } else { 270 277 error = dlm_user_request(ls, ua, 271 278 params->mode, params->flags, 272 279 params->name, params->namelen,
+1 -1
include/uapi/linux/dlmconstants.h
··· 114 114 * 115 115 * DLM_LKF_ORPHAN 116 116 * 117 - * not yet implemented 117 + * Acquire an orphan lock. 118 118 * 119 119 * DLM_LKF_ALTPR 120 120 *