X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fldlm%2Fldlm_flock.c;h=b3b2cb1cff545429cb8f07bcf5d162ed3e56bc75;hb=510b04494f3271675da53048f5987867e507f083;hp=d38cfdff86645296bf1d52f0e0ab72bc9d1ba1d8;hpb=c83c2bee2dfa881007fa697ed912dd64574a0c3e;p=fs%2Flustre-release.git diff --git a/lustre/ldlm/ldlm_flock.c b/lustre/ldlm/ldlm_flock.c index d38cfdf..b3b2cb1 100644 --- a/lustre/ldlm/ldlm_flock.c +++ b/lustre/ldlm/ldlm_flock.c @@ -71,10 +71,10 @@ int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, /** * list_for_remaining_safe - iterate over the remaining entries in a list * and safeguard against removal of a list entry. - * @pos: the &struct list_head to use as a loop counter. pos MUST + * \param pos the &struct list_head to use as a loop counter. pos MUST * have been initialized prior to using it in this macro. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. + * \param n another &struct list_head to use as temporary storage + * \param head the head for your list. */ #define list_for_remaining_safe(pos, n, head) \ for (n = pos->next; pos != (head); pos = n, n = pos->next) @@ -108,11 +108,12 @@ ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, int flags) LASSERT(list_empty(&lock->l_flock_waitq)); list_del_init(&lock->l_res_link); - if (flags == LDLM_FL_WAIT_NOREPROC) { + if (flags == LDLM_FL_WAIT_NOREPROC && + !(lock->l_flags & LDLM_FL_FAILED)) { /* client side - set a flag to prevent sending a CANCEL */ lock->l_flags |= LDLM_FL_LOCAL_ONLY | LDLM_FL_CBPENDING; - /* when reaching here, it is under lock_res_and_lock(). Thus, + /* when reaching here, it is under lock_res_and_lock(). Thus, need call the nolock version of ldlm_lock_decref_internal*/ ldlm_lock_decref_internal_nolock(lock, mode); } @@ -378,7 +379,8 @@ reprocess: NULL, 0); lock_res_and_lock(req); if (!new2) { - ldlm_flock_destroy(req, lock->l_granted_mode, *flags); + ldlm_flock_destroy(req, lock->l_granted_mode, + *flags); *err = -ENOLCK; RETURN(LDLM_ITER_STOP); } @@ -398,15 +400,16 @@ reprocess: new->l_policy_data.l_flock.end + 1; new2->l_conn_export = lock->l_conn_export; if (lock->l_export != NULL) { - new2->l_export = class_export_get(lock->l_export); - if (new2->l_export->exp_lock_hash && + new2->l_export = class_export_lock_get(lock->l_export); + if (new2->l_export->exp_lock_hash && hlist_unhashed(&new2->l_exp_hash)) lustre_hash_add(new2->l_export->exp_lock_hash, &new2->l_remote_handle, &new2->l_exp_hash); } if (*flags == LDLM_FL_WAIT_NOREPROC) - ldlm_lock_addref_internal_nolock(new2, lock->l_granted_mode); + ldlm_lock_addref_internal_nolock(new2, + lock->l_granted_mode); /* insert new2 at lock */ ldlm_resource_add_lock(res, ownlocks, new2); @@ -502,17 +505,26 @@ ldlm_flock_interrupted_wait(void *data) EXIT; } +/** + * Flock completion calback function. + * + * \param lock [in,out]: A lock to be handled + * \param flags [in]: flags + * \param *data [in]: ldlm_work_cp_ast_lock() will use ldlm_cb_set_arg + * + * \retval 0 : success + * \retval <0 : failure + */ int ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data) { - struct ldlm_namespace *ns; - cfs_flock_t *getlk = lock->l_ast_data; - struct ldlm_flock_wait_data fwd; - struct obd_device *obd; - struct obd_import *imp = NULL; - ldlm_error_t err; - int rc = 0; - struct l_wait_info lwi; + cfs_flock_t *getlk = lock->l_ast_data; + struct obd_device *obd; + struct obd_import *imp = NULL; + struct ldlm_flock_wait_data fwd; + struct l_wait_info lwi; + ldlm_error_t err; + int rc = 0; ENTRY; CDEBUG(D_DLMTRACE, "flags: 0x%x data: %p getlk: %p\n", @@ -523,11 +535,12 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data) * holding the lock even if app still believes it has it, since * server already dropped it anyway. Only for granted locks too. */ lock_res_and_lock(lock); - if ((lock->l_flags & (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) == + if ((lock->l_flags & (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) == (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) { unlock_res_and_lock(lock); if (lock->l_req_mode == lock->l_granted_mode && - lock->l_granted_mode != LCK_NL) + lock->l_granted_mode != LCK_NL && + NULL == data) ldlm_lock_decref_internal(lock, lock->l_req_mode); RETURN(0); } @@ -536,20 +549,25 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data) LASSERT(flags != LDLM_FL_WAIT_NOREPROC); if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) - goto granted; + LDLM_FL_BLOCK_CONV))) { + if (NULL == data) + /* mds granted the lock in the reply */ + goto granted; + /* CP AST RPC: lock get granted, wake it up */ + cfs_waitq_signal(&lock->l_waitq); + RETURN(0); + } LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, " "sleeping"); - fwd.fwd_lock = lock; obd = class_exp2obd(lock->l_conn_export); - /* if this is a local lock, then there is no import */ - if (obd != NULL) + /* if this is a local lock, there is no import */ + if (NULL != obd) imp = obd->u.cli.cl_import; - if (imp != NULL) { + if (NULL != imp) { spin_lock(&imp->imp_lock); fwd.fwd_generation = imp->imp_generation; spin_unlock(&imp->imp_lock); @@ -558,27 +576,31 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data) lwi = LWI_TIMEOUT_INTR(0, NULL, ldlm_flock_interrupted_wait, &fwd); /* Go to sleep until the lock is granted. */ - rc = l_wait_event(lock->l_waitq, - ((lock->l_req_mode == lock->l_granted_mode) || - lock->l_destroyed), &lwi); + rc = l_wait_event(lock->l_waitq, is_granted_or_cancelled(lock), &lwi); - LDLM_DEBUG(lock, "client-side enqueue waking up: rc = %d", rc); - RETURN(rc); + if (rc) { + LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)", + rc); + RETURN(rc); + } granted: OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT, 10); - LDLM_DEBUG(lock, "client-side enqueue granted"); - ns = lock->l_resource->lr_namespace; - lock_res_and_lock(lock); - /* before flock's complete ast gets here, the flock - * can possibly be freed by another thread - */ - if (lock->l_destroyed) { - LDLM_DEBUG(lock, "already destroyed by another thread"); + lock_res_and_lock(lock); + if (lock->l_destroyed || lock->l_flags & LDLM_FL_FAILED) { + LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed"); unlock_res(lock->l_resource); - RETURN(0); + RETURN(-EIO); } + if (rc) { + LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)", + rc); + unlock_res_and_lock(lock); + RETURN(rc); + } + + LDLM_DEBUG(lock, "client-side enqueue granted"); /* take lock off the deadlock detection waitq. */ spin_lock(&ldlm_flock_waitq_lock); @@ -591,8 +613,9 @@ granted: if (flags & LDLM_FL_TEST_LOCK) { /* fcntl(F_GETLK) request */ /* The old mode was saved in getlk->fl_type so that if the mode - * in the lock changes we can decref the approprate refcount. */ - ldlm_flock_destroy(lock, cfs_flock_type(getlk), LDLM_FL_WAIT_NOREPROC); + * in the lock changes we can decref the appropriate refcount.*/ + ldlm_flock_destroy(lock, cfs_flock_type(getlk), + LDLM_FL_WAIT_NOREPROC); switch (lock->l_granted_mode) { case LCK_PR: cfs_flock_set_type(getlk, F_RDLCK); @@ -603,17 +626,18 @@ granted: default: cfs_flock_set_type(getlk, F_UNLCK); } - cfs_flock_set_pid(getlk, (pid_t)lock->l_policy_data.l_flock.pid); - cfs_flock_set_start(getlk, (loff_t)lock->l_policy_data.l_flock.start); - cfs_flock_set_end(getlk, (loff_t)lock->l_policy_data.l_flock.end); + cfs_flock_set_pid(getlk, + (pid_t)lock->l_policy_data.l_flock.pid); + cfs_flock_set_start(getlk, + (loff_t)lock->l_policy_data.l_flock.start); + cfs_flock_set_end(getlk, + (loff_t)lock->l_policy_data.l_flock.end); } else { int noreproc = LDLM_FL_WAIT_NOREPROC; /* We need to reprocess the lock to do merges or splits * with existing locks owned by this process. */ ldlm_process_flock_lock(lock, &noreproc, 1, &err, NULL); - if (flags == 0) - cfs_waitq_signal(&lock->l_waitq); } unlock_res_and_lock(lock); RETURN(0);