[LCK_GROUP] "GROUP",
[LCK_COS] "COS"
};
+EXPORT_SYMBOL(ldlm_lockname);
char *ldlm_typename[] = {
[LDLM_PLAIN] "PLN",
[LDLM_FLOCK] "FLK",
[LDLM_IBITS] "IBT",
};
+EXPORT_SYMBOL(ldlm_typename);
static ldlm_policy_wire_to_local_t ldlm_policy_wire18_to_local[] = {
[LDLM_PLAIN - LDLM_MIN_TYPE] ldlm_plain_policy_wire_to_local,
return "UNKNOWN";
}
}
+EXPORT_SYMBOL(ldlm_it2str);
extern cfs_mem_cache_t *ldlm_lock_slab;
{
return ldlm_processing_policy_table[res->lr_type];
}
+EXPORT_SYMBOL(ldlm_get_processing_policy);
#endif /* HAVE_SERVER_SUPPORT */
void ldlm_register_intent(struct ldlm_namespace *ns, ldlm_res_policy arg)
{
ns->ns_policy = arg;
}
+EXPORT_SYMBOL(ldlm_register_intent);
/*
* REFCOUNTED LOCK OBJECTS
cfs_atomic_inc(&lock->l_refc);
return lock;
}
+EXPORT_SYMBOL(ldlm_lock_get);
void ldlm_lock_put(struct ldlm_lock *lock)
{
EXIT;
}
+EXPORT_SYMBOL(ldlm_lock_put);
int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock)
{
}
lock->l_destroyed = 1;
- if (lock->l_export && lock->l_export->exp_lock_hash &&
- !cfs_hlist_unhashed(&lock->l_exp_hash))
- cfs_hash_del(lock->l_export->exp_lock_hash,
- &lock->l_remote_handle, &lock->l_exp_hash);
+ if (lock->l_export && lock->l_export->exp_lock_hash) {
+ /* NB: it's safe to call cfs_hash_del() even lock isn't
+ * in exp_lock_hash. */
+ /* In the function below, .hs_keycmp resolves to
+ * ldlm_export_lock_keycmp() */
+ /* coverity[overrun-buffer-val] */
+ cfs_hash_del(lock->l_export->exp_lock_hash,
+ &lock->l_remote_handle, &lock->l_exp_hash);
+ }
ldlm_lock_remove_from_lru(lock);
class_handle_unhash(&lock->l_handle);
CFS_INIT_LIST_HEAD(&lock->l_sl_mode);
CFS_INIT_LIST_HEAD(&lock->l_sl_policy);
CFS_INIT_HLIST_NODE(&lock->l_exp_hash);
+ CFS_INIT_HLIST_NODE(&lock->l_exp_flock_hash);
lprocfs_counter_incr(ldlm_res_to_ns(resource)->ns_stats,
LDLM_NSS_LOCKS);
RETURN(0);
}
+EXPORT_SYMBOL(ldlm_lock_change_resource);
/*
* HANDLES
{
lockh->cookie = lock->l_handle.h_cookie;
}
+EXPORT_SYMBOL(ldlm_lock2handle);
/* if flags: atomically get the lock and set the flags.
* Return NULL if flag already set
unlock_res_and_lock(lock);
RETURN(lock);
}
+EXPORT_SYMBOL(__ldlm_handle2lock);
void ldlm_lock2desc(struct ldlm_lock *lock, struct ldlm_lock_desc *desc)
{
&desc->l_policy_data);
}
}
+EXPORT_SYMBOL(ldlm_lock2desc);
void ldlm_add_bl_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
cfs_list_t *work_list)
ldlm_lock_addref_internal(lock, mode);
LDLM_LOCK_PUT(lock);
}
+EXPORT_SYMBOL(ldlm_lock_addref);
void ldlm_lock_addref_internal_nolock(struct ldlm_lock *lock, __u32 mode)
{
}
return result;
}
+EXPORT_SYMBOL(ldlm_lock_addref_try);
/* only called for local locks */
void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode)
ldlm_lock_decref_internal(lock, mode);
LDLM_LOCK_PUT(lock);
}
+EXPORT_SYMBOL(ldlm_lock_decref);
/* This will drop a lock reference and mark it for destruction, but will not
* necessarily cancel the lock before returning. */
ldlm_lock_decref_internal(lock, mode);
LDLM_LOCK_PUT(lock);
}
+EXPORT_SYMBOL(ldlm_lock_decref_and_cancel);
struct sl_insert_point {
cfs_list_t *res_link;
lock->l_flags |= LDLM_FL_LVB_READY;
cfs_waitq_broadcast(&lock->l_waitq);
}
+EXPORT_SYMBOL(ldlm_lock_allow_match_locked);
void ldlm_lock_allow_match(struct ldlm_lock *lock)
{
ldlm_lock_allow_match_locked(lock);
unlock_res_and_lock(lock);
}
+EXPORT_SYMBOL(ldlm_lock_allow_match);
/* Can be called in two ways:
*
return rc ? mode : 0;
}
+EXPORT_SYMBOL(ldlm_lock_match);
ldlm_mode_t ldlm_revalidate_lock_handle(struct lustre_handle *lockh,
__u64 *bits)
RETURN(rc);
}
+int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
+{
+ struct ldlm_cb_set_arg *arg = opaq;
+ struct ldlm_glimpse_work *gl_work;
+ struct ldlm_lock *lock;
+ int rc = 0;
+ ENTRY;
+
+ if (cfs_list_empty(arg->list))
+ RETURN(-ENOENT);
+
+ gl_work = cfs_list_entry(arg->list->next, struct ldlm_glimpse_work,
+ gl_list);
+ cfs_list_del_init(&gl_work->gl_list);
+
+ lock = gl_work->gl_lock;
+
+ /* transfer the glimpse descriptor to ldlm_cb_set_arg */
+ arg->gl_desc = gl_work->gl_desc;
+
+ /* invoke the actual glimpse callback */
+ if (lock->l_glimpse_ast(lock, (void*)arg) == 0)
+ rc = 1;
+
+ LDLM_LOCK_RELEASE(lock);
+
+ if ((gl_work->gl_flags & LDLM_GL_WORK_NOFREE) == 0)
+ OBD_FREE_PTR(gl_work);
+
+ RETURN(rc);
+}
+
int ldlm_run_ast_work(struct ldlm_namespace *ns, cfs_list_t *rpc_list,
ldlm_desc_ast_t ast_type)
{
arg->type = LDLM_BL_CALLBACK;
work_ast_lock = ldlm_work_revoke_ast_lock;
break;
+ case LDLM_WORK_GL_AST:
+ arg->type = LDLM_GL_CALLBACK;
+ work_ast_lock = ldlm_work_gl_ast_lock;
+ break;
default:
LBUG();
}
}
EXIT;
}
+EXPORT_SYMBOL(ldlm_reprocess_all_ns);
void ldlm_reprocess_all(struct ldlm_resource *res)
{
LBUG();
}
- ldlm_del_waiting_lock(lock);
+ if (lock->l_waited)
+ ldlm_del_waiting_lock(lock);
/* Releases cancel callback. */
ldlm_cancel_callback(lock);
/* Yes, second time, just in case it was added again while we were
running with no res lock in ldlm_cancel_callback */
- ldlm_del_waiting_lock(lock);
+ if (lock->l_waited)
+ ldlm_del_waiting_lock(lock);
+
ldlm_resource_unlink_lock(lock);
ldlm_lock_destroy_nolock(lock);
EXIT;
}
+EXPORT_SYMBOL(ldlm_lock_cancel);
int ldlm_lock_set_data(struct lustre_handle *lockh, void *data)
{
}
EXPORT_SYMBOL(ldlm_lock_set_data);
+struct export_cl_data {
+ struct obd_export *ecl_exp;
+ int ecl_loop;
+};
+
int ldlm_cancel_locks_for_export_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
cfs_hlist_node_t *hnode, void *data)
{
- struct obd_export *exp = data;
+ struct export_cl_data *ecl = (struct export_cl_data *)data;
+ struct obd_export *exp = ecl->ecl_exp;
struct ldlm_lock *lock = cfs_hash_object(hs, hnode);
struct ldlm_resource *res;
ldlm_reprocess_all(res);
ldlm_resource_putref(res);
LDLM_LOCK_RELEASE(lock);
- return 0;
+
+ ecl->ecl_loop++;
+ if ((ecl->ecl_loop & -ecl->ecl_loop) == ecl->ecl_loop) {
+ CDEBUG(D_INFO,
+ "Cancel lock %p for export %p (loop %d), still have "
+ "%d locks left on hash table.\n",
+ lock, exp, ecl->ecl_loop,
+ cfs_atomic_read(&hs->hs_count));
+ }
+
+ return 0;
}
void ldlm_cancel_locks_for_export(struct obd_export *exp)
{
- cfs_hash_for_each_empty(exp->exp_lock_hash,
- ldlm_cancel_locks_for_export_cb, exp);
+ struct export_cl_data ecl = {
+ .ecl_exp = exp,
+ .ecl_loop = 0,
+ };
+
+ cfs_hash_for_each_empty(exp->exp_lock_hash,
+ ldlm_cancel_locks_for_export_cb, &ecl);
}
/**
EXIT;
}
+EXPORT_SYMBOL(ldlm_lock_downgrade);
struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
__u32 *flags)
OBD_SLAB_FREE(node, ldlm_interval_slab, sizeof(*node));
RETURN(res);
}
+EXPORT_SYMBOL(ldlm_lock_convert);
void ldlm_lock_dump_handle(int level, struct lustre_handle *lockh)
{
LDLM_LOCK_PUT(lock);
}
+EXPORT_SYMBOL(ldlm_lock_dump_handle);
void _ldlm_lock_debug(struct ldlm_lock *lock,
struct libcfs_debug_msg_data *msgdata,