diff options
Diffstat (limited to 'kernel/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c')
-rw-r--r-- | kernel/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 278 |
1 files changed, 10 insertions, 268 deletions
diff --git a/kernel/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/kernel/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index a4c252feb..4310154e1 100644 --- a/kernel/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/kernel/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -63,9 +63,6 @@ #include <linux/list.h> #include "ldlm_internal.h" -int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, - void *data, int flag); - /** * list_for_remaining_safe - iterate over the remaining entries in a list * and safeguard against removal of a list entry. @@ -94,40 +91,6 @@ ldlm_flocks_overlap(struct ldlm_lock *lock, struct ldlm_lock *new) lock->l_policy_data.l_flock.start)); } -static inline void ldlm_flock_blocking_link(struct ldlm_lock *req, - struct ldlm_lock *lock) -{ - /* For server only */ - if (req->l_export == NULL) - return; - - LASSERT(hlist_unhashed(&req->l_exp_flock_hash)); - - req->l_policy_data.l_flock.blocking_owner = - lock->l_policy_data.l_flock.owner; - req->l_policy_data.l_flock.blocking_export = - lock->l_export; - req->l_policy_data.l_flock.blocking_refs = 0; - - cfs_hash_add(req->l_export->exp_flock_hash, - &req->l_policy_data.l_flock.owner, - &req->l_exp_flock_hash); -} - -static inline void ldlm_flock_blocking_unlink(struct ldlm_lock *req) -{ - /* For server only */ - if (req->l_export == NULL) - return; - - check_res_locked(req->l_resource); - if (req->l_export->exp_flock_hash != NULL && - !hlist_unhashed(&req->l_exp_flock_hash)) - cfs_hash_del(req->l_export->exp_flock_hash, - &req->l_policy_data.l_flock.owner, - &req->l_exp_flock_hash); -} - static inline void ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, __u64 flags) { @@ -152,79 +115,6 @@ ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, __u64 flags) } /** - * POSIX locks deadlock detection code. - * - * Given a new lock \a req and an existing lock \a bl_lock it conflicts - * with, we need to iterate through all blocked POSIX locks for this - * export and see if there is a deadlock condition arising. (i.e. when - * one client holds a lock on something and want a lock on something - * else and at the same time another client has the opposite situation). - */ -static int -ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock) -{ - struct obd_export *req_exp = req->l_export; - struct obd_export *bl_exp = bl_lock->l_export; - __u64 req_owner = req->l_policy_data.l_flock.owner; - __u64 bl_owner = bl_lock->l_policy_data.l_flock.owner; - - /* For server only */ - if (req_exp == NULL) - return 0; - - class_export_get(bl_exp); - while (1) { - struct obd_export *bl_exp_new; - struct ldlm_lock *lock = NULL; - struct ldlm_flock *flock; - - if (bl_exp->exp_flock_hash != NULL) - lock = cfs_hash_lookup(bl_exp->exp_flock_hash, - &bl_owner); - if (lock == NULL) - break; - - LASSERT(req != lock); - flock = &lock->l_policy_data.l_flock; - LASSERT(flock->owner == bl_owner); - bl_owner = flock->blocking_owner; - bl_exp_new = class_export_get(flock->blocking_export); - class_export_put(bl_exp); - - cfs_hash_put(bl_exp->exp_flock_hash, &lock->l_exp_flock_hash); - bl_exp = bl_exp_new; - - if (bl_owner == req_owner && bl_exp == req_exp) { - class_export_put(bl_exp); - return 1; - } - } - class_export_put(bl_exp); - - return 0; -} - -static void ldlm_flock_cancel_on_deadlock(struct ldlm_lock *lock, - struct list_head *work_list) -{ - CDEBUG(D_INFO, "reprocess deadlock req=%p\n", lock); - - if ((exp_connect_flags(lock->l_export) & - OBD_CONNECT_FLOCK_DEAD) == 0) { - CERROR( - "deadlock found, but client doesn't support flock canceliation\n"); - } else { - LASSERT(lock->l_completion_ast); - LASSERT((lock->l_flags & LDLM_FL_AST_SENT) == 0); - lock->l_flags |= LDLM_FL_AST_SENT | LDLM_FL_CANCEL_ON_BLOCK | - LDLM_FL_FLOCK_DEADLOCK; - ldlm_flock_blocking_unlink(lock); - ldlm_resource_unlink_lock(lock); - ldlm_add_ast_work_item(lock, NULL, work_list); - } -} - -/** * Process a granting attempt for flock lock. * Must be called under ns lock held. * @@ -242,9 +132,9 @@ static void ldlm_flock_cancel_on_deadlock(struct ldlm_lock *lock, * - blocking ASTs have not been sent yet, so list of conflicting locks * would be collected and ASTs sent. */ -int -ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, int first_enq, - ldlm_error_t *err, struct list_head *work_list) +static int ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, + int first_enq, ldlm_error_t *err, + struct list_head *work_list) { struct ldlm_resource *res = req->l_resource; struct ldlm_namespace *ns = ldlm_res_to_ns(res); @@ -254,7 +144,6 @@ ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, int first_enq, struct ldlm_lock *new = req; struct ldlm_lock *new2 = NULL; ldlm_mode_t mode = req->l_req_mode; - int local = ns_is_client(ns); int added = (mode == LCK_NL); int overlaps = 0; int splitted = 0; @@ -269,14 +158,9 @@ ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, int first_enq, *err = ELDLM_OK; - if (local) { - /* No blocking ASTs are sent to the clients for - * Posix file & record locks */ - req->l_blocking_ast = NULL; - } else { - /* Called on the server for lock cancels. */ - req->l_blocking_ast = ldlm_flock_blocking_ast; - } + /* No blocking ASTs are sent to the clients for + * Posix file & record locks */ + req->l_blocking_ast = NULL; reprocess: if ((*flags == LDLM_FL_WAIT_NOREPROC) || (mode == LCK_NL)) { @@ -316,11 +200,6 @@ reprocess: if (!first_enq) { reprocess_failed = 1; - if (ldlm_flock_deadlock(req, lock)) { - ldlm_flock_cancel_on_deadlock(req, - work_list); - return LDLM_ITER_CONTINUE; - } continue; } @@ -343,17 +222,6 @@ reprocess: return LDLM_ITER_STOP; } - /* add lock to blocking list before deadlock - * check to prevent race */ - ldlm_flock_blocking_link(req, lock); - - if (ldlm_flock_deadlock(req, lock)) { - ldlm_flock_blocking_unlink(req); - ldlm_flock_destroy(req, mode, *flags); - *err = -EDEADLK; - return LDLM_ITER_STOP; - } - ldlm_resource_add_lock(res, &res->lr_waiting, req); *flags |= LDLM_FL_BLOCK_GRANTED; return LDLM_ITER_STOP; @@ -369,10 +237,6 @@ reprocess: return LDLM_ITER_STOP; } - /* In case we had slept on this lock request take it off of the - * deadlock detection hash list. */ - ldlm_flock_blocking_unlink(req); - /* Scan the locks owned by this process that overlap this request. * We may have to merge or split existing locks. */ @@ -523,7 +387,6 @@ reprocess: /* At this point we're granting the lock request. */ req->l_granted_mode = req->l_req_mode; - /* Add req to the granted queue before calling ldlm_reprocess_all(). */ if (!added) { list_del_init(&req->l_res_link); /* insert new lock before ownlocks in list. */ @@ -561,9 +424,7 @@ ldlm_flock_interrupted_wait(void *data) lock = ((struct ldlm_flock_wait_data *)data)->fwd_lock; - /* take lock off the deadlock detection hash list. */ lock_res_and_lock(lock); - ldlm_flock_blocking_unlink(lock); /* client side - set flag to prevent lock from being put on LRU list */ lock->l_flags |= LDLM_FL_CBPENDING; @@ -602,7 +463,7 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) { if (lock->l_req_mode == lock->l_granted_mode && lock->l_granted_mode != LCK_NL && - NULL == data) + data == NULL) ldlm_lock_decref_internal(lock, lock->l_req_mode); /* Need to wake up the waiter if we were evicted */ @@ -614,7 +475,7 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | LDLM_FL_BLOCK_CONV))) { - if (NULL == data) + if (data == NULL) /* mds granted the lock in the reply */ goto granted; /* CP AST RPC: lock get granted, wake it up */ @@ -627,10 +488,10 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) obd = class_exp2obd(lock->l_conn_export); /* if this is a local lock, there is no import */ - if (NULL != obd) + if (obd != NULL) imp = obd->u.cli.cl_import; - if (NULL != imp) { + if (imp != NULL) { spin_lock(&imp->imp_lock); fwd.fwd_generation = imp->imp_generation; spin_unlock(&imp->imp_lock); @@ -670,9 +531,6 @@ granted: lock_res_and_lock(lock); - /* take lock off the deadlock detection hash list. */ - ldlm_flock_blocking_unlink(lock); - /* ldlm_lock_enqueue() has already placed lock on the granted list. */ list_del_init(&lock->l_res_link); @@ -709,19 +567,6 @@ granted: } EXPORT_SYMBOL(ldlm_flock_completion_ast); -int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, - void *data, int flag) -{ - LASSERT(lock); - LASSERT(flag == LDLM_CB_CANCELING); - - /* take lock off the deadlock detection hash list. */ - lock_res_and_lock(lock); - ldlm_flock_blocking_unlink(lock); - unlock_res_and_lock(lock); - return 0; -} - void ldlm_flock_policy_wire18_to_local(const ldlm_wire_policy_data_t *wpolicy, ldlm_policy_data_t *lpolicy) { @@ -735,7 +580,6 @@ void ldlm_flock_policy_wire18_to_local(const ldlm_wire_policy_data_t *wpolicy, lpolicy->l_flock.owner = wpolicy->l_flock.lfw_pid; } - void ldlm_flock_policy_wire21_to_local(const ldlm_wire_policy_data_t *wpolicy, ldlm_policy_data_t *lpolicy) { @@ -755,105 +599,3 @@ void ldlm_flock_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, wpolicy->l_flock.lfw_pid = lpolicy->l_flock.pid; wpolicy->l_flock.lfw_owner = lpolicy->l_flock.owner; } - -/* - * Export handle<->flock hash operations. - */ -static unsigned -ldlm_export_flock_hash(struct cfs_hash *hs, const void *key, unsigned mask) -{ - return cfs_hash_u64_hash(*(__u64 *)key, mask); -} - -static void * -ldlm_export_flock_key(struct hlist_node *hnode) -{ - struct ldlm_lock *lock; - - lock = hlist_entry(hnode, struct ldlm_lock, l_exp_flock_hash); - return &lock->l_policy_data.l_flock.owner; -} - -static int -ldlm_export_flock_keycmp(const void *key, struct hlist_node *hnode) -{ - return !memcmp(ldlm_export_flock_key(hnode), key, sizeof(__u64)); -} - -static void * -ldlm_export_flock_object(struct hlist_node *hnode) -{ - return hlist_entry(hnode, struct ldlm_lock, l_exp_flock_hash); -} - -static void -ldlm_export_flock_get(struct cfs_hash *hs, struct hlist_node *hnode) -{ - struct ldlm_lock *lock; - struct ldlm_flock *flock; - - lock = hlist_entry(hnode, struct ldlm_lock, l_exp_flock_hash); - LDLM_LOCK_GET(lock); - - flock = &lock->l_policy_data.l_flock; - LASSERT(flock->blocking_export != NULL); - class_export_get(flock->blocking_export); - flock->blocking_refs++; -} - -static void -ldlm_export_flock_put(struct cfs_hash *hs, struct hlist_node *hnode) -{ - struct ldlm_lock *lock; - struct ldlm_flock *flock; - - lock = hlist_entry(hnode, struct ldlm_lock, l_exp_flock_hash); - LDLM_LOCK_RELEASE(lock); - - flock = &lock->l_policy_data.l_flock; - LASSERT(flock->blocking_export != NULL); - class_export_put(flock->blocking_export); - if (--flock->blocking_refs == 0) { - flock->blocking_owner = 0; - flock->blocking_export = NULL; - } -} - -static cfs_hash_ops_t ldlm_export_flock_ops = { - .hs_hash = ldlm_export_flock_hash, - .hs_key = ldlm_export_flock_key, - .hs_keycmp = ldlm_export_flock_keycmp, - .hs_object = ldlm_export_flock_object, - .hs_get = ldlm_export_flock_get, - .hs_put = ldlm_export_flock_put, - .hs_put_locked = ldlm_export_flock_put, -}; - -int ldlm_init_flock_export(struct obd_export *exp) -{ - if (strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_MDT_NAME) != 0) - return 0; - - exp->exp_flock_hash = - cfs_hash_create(obd_uuid2str(&exp->exp_client_uuid), - HASH_EXP_LOCK_CUR_BITS, - HASH_EXP_LOCK_MAX_BITS, - HASH_EXP_LOCK_BKT_BITS, 0, - CFS_HASH_MIN_THETA, CFS_HASH_MAX_THETA, - &ldlm_export_flock_ops, - CFS_HASH_DEFAULT | CFS_HASH_NBLK_CHANGE); - if (!exp->exp_flock_hash) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL(ldlm_init_flock_export); - -void ldlm_destroy_flock_export(struct obd_export *exp) -{ - if (exp->exp_flock_hash) { - cfs_hash_putref(exp->exp_flock_hash); - exp->exp_flock_hash = NULL; - } -} -EXPORT_SYMBOL(ldlm_destroy_flock_export); |