X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fobdclass%2Fgenops.c;h=aca1fec8ec7bd287e56160135bec6292b2fef300;hp=df1a31dc05689a6dec22a21fe8a49443974cf9b4;hb=0098396983e1075668414aa5298a4990e61ffbda;hpb=23773b32bfe15fccc9c029d722dc1bd5b0144779 diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index df1a31d..aca1fec 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -46,13 +46,11 @@ #include #include -static DEFINE_SPINLOCK(obd_types_lock); -static LIST_HEAD(obd_types); DEFINE_RWLOCK(obd_dev_lock); static struct obd_device *obd_devs[MAX_OBD_DEVICES]; static struct kmem_cache *obd_device_cachep; - +static struct kobj_type class_ktype; static struct workqueue_struct *zombie_wq; static void obd_zombie_export_add(struct obd_export *exp); @@ -98,30 +96,26 @@ static void obd_device_free(struct obd_device *obd) struct obd_type *class_search_type(const char *name) { - struct list_head *tmp; - struct obd_type *type; + struct kobject *kobj = kset_find_obj(lustre_kset, name); - spin_lock(&obd_types_lock); - list_for_each(tmp, &obd_types) { - type = list_entry(tmp, struct obd_type, typ_chain); - if (strcmp(type->typ_name, name) == 0) { - spin_unlock(&obd_types_lock); - return type; - } - } - spin_unlock(&obd_types_lock); + if (kobj && kobj->ktype == &class_ktype) + return container_of(kobj, struct obd_type, typ_kobj); + + kobject_put(kobj); return NULL; } EXPORT_SYMBOL(class_search_type); struct obd_type *class_get_type(const char *name) { - struct obd_type *type = class_search_type(name); + struct obd_type *type; + type = class_search_type(name); #ifdef HAVE_MODULE_LOADING_SUPPORT if (!type) { const char *modname = name; +#ifdef HAVE_SERVER_SUPPORT if (strcmp(modname, "obdfilter") == 0) modname = "ofd"; @@ -130,6 +124,7 @@ struct obd_type *class_get_type(const char *name) if (!strncmp(modname, LUSTRE_MDS_NAME, strlen(LUSTRE_MDS_NAME))) modname = LUSTRE_MDT_NAME; +#endif /* HAVE_SERVER_SUPPORT */ if (!request_module("%s", modname)) { CDEBUG(D_INFO, "Loaded module '%s'\n", modname); @@ -141,10 +136,17 @@ struct obd_type *class_get_type(const char *name) } #endif if (type) { - spin_lock(&type->obd_type_lock); - type->typ_refcnt++; - try_module_get(type->typ_dt_ops->o_owner); - spin_unlock(&type->obd_type_lock); + if (try_module_get(type->typ_dt_ops->o_owner)) { + atomic_inc(&type->typ_refcnt); + /* class_search_type() returned a counted reference, + * but we don't need that count any more as + * we have one through typ_refcnt. + */ + kobject_put(&type->typ_kobj); + } else { + kobject_put(&type->typ_kobj); + type = NULL; + } } return type; } @@ -152,39 +154,24 @@ struct obd_type *class_get_type(const char *name) void class_put_type(struct obd_type *type) { LASSERT(type); - spin_lock(&type->obd_type_lock); - type->typ_refcnt--; module_put(type->typ_dt_ops->o_owner); - spin_unlock(&type->obd_type_lock); + atomic_dec(&type->typ_refcnt); } static void class_sysfs_release(struct kobject *kobj) { struct obd_type *type = container_of(kobj, struct obd_type, typ_kobj); -#ifdef HAVE_SERVER_SUPPORT - if (type->typ_sym_filter) - type->typ_debugfs_entry = NULL; -#endif debugfs_remove_recursive(type->typ_debugfs_entry); type->typ_debugfs_entry = NULL; if (type->typ_lu) lu_device_type_fini(type->typ_lu); - spin_lock(&obd_types_lock); - list_del(&type->typ_chain); - spin_unlock(&obd_types_lock); - #ifdef CONFIG_PROC_FS if (type->typ_name && type->typ_procroot) remove_proc_subtree(type->typ_name, proc_lustre_root); #endif - if (type->typ_md_ops) - OBD_FREE_PTR(type->typ_md_ops); - if (type->typ_dt_ops) - OBD_FREE_PTR(type->typ_dt_ops); - OBD_FREE(type, sizeof(*type)); } @@ -198,12 +185,11 @@ struct obd_type *class_add_symlinks(const char *name, bool enable_proc) { struct dentry *symlink; struct obd_type *type; - struct kobject *kobj; int rc; - kobj = kset_find_obj(lustre_kset, name); - if (kobj) { - kobject_put(kobj); + type = class_search_type(name); + if (type) { + kobject_put(&type->typ_kobj); return ERR_PTR(-EEXIST); } @@ -211,8 +197,6 @@ struct obd_type *class_add_symlinks(const char *name, bool enable_proc) if (!type) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&type->typ_chain); - type->typ_kobj.kset = lustre_kset; rc = kobject_init_and_add(&type->typ_kobj, &class_ktype, &lustre_kset->kobj, "%s", name); @@ -245,7 +229,8 @@ EXPORT_SYMBOL(class_add_symlinks); #define CLASS_MAX_NAME 1024 -int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, +int class_register_type(const struct obd_ops *dt_ops, + const struct md_ops *md_ops, bool enable_proc, struct lprocfs_vars *vars, const char *name, struct lu_device_type *ldt) { @@ -256,20 +241,13 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, /* sanity check */ LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME); - if (class_search_type(name)) { + type = class_search_type(name); + if (type) { #ifdef HAVE_SERVER_SUPPORT - if (strcmp(name, LUSTRE_LOV_NAME) == 0 || - strcmp(name, LUSTRE_OSC_NAME) == 0) { - struct kobject *kobj; - - kobj = kset_find_obj(lustre_kset, name); - if (kobj) { - type = container_of(kobj, struct obd_type, - typ_kobj); - goto dir_exist; - } - } + if (type->typ_sym_filter) + goto dir_exist; #endif /* HAVE_SERVER_SUPPORT */ + kobject_put(&type->typ_kobj); CDEBUG(D_IOCTL, "Type %s already registered\n", name); RETURN(-EEXIST); } @@ -278,28 +256,21 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, if (type == NULL) RETURN(-ENOMEM); - INIT_LIST_HEAD(&type->typ_chain); type->typ_kobj.kset = lustre_kset; kobject_init(&type->typ_kobj, &class_ktype); #ifdef HAVE_SERVER_SUPPORT dir_exist: #endif /* HAVE_SERVER_SUPPORT */ - OBD_ALLOC_PTR(type->typ_dt_ops); - OBD_ALLOC_PTR(type->typ_md_ops); - if (type->typ_dt_ops == NULL || - type->typ_md_ops == NULL) - GOTO (failed, rc = -ENOMEM); - - *(type->typ_dt_ops) = *dt_ops; - /* md_ops is optional */ - if (md_ops) - *(type->typ_md_ops) = *md_ops; - spin_lock_init(&type->obd_type_lock); + type->typ_dt_ops = dt_ops; + type->typ_md_ops = md_ops; #ifdef HAVE_SERVER_SUPPORT - if (type->typ_sym_filter) + if (type->typ_sym_filter) { + type->typ_sym_filter = false; + kobject_put(&type->typ_kobj); goto setup_ldt; + } #endif #ifdef CONFIG_PROC_FS if (enable_proc && !type->typ_procroot) { @@ -335,10 +306,6 @@ setup_ldt: GOTO(failed, rc); } - spin_lock(&obd_types_lock); - list_add(&type->typ_chain, &obd_types); - spin_unlock(&obd_types_lock); - RETURN(0); failed: @@ -351,6 +318,7 @@ EXPORT_SYMBOL(class_register_type); int class_unregister_type(const char *name) { struct obd_type *type = class_search_type(name); + int rc = 0; ENTRY; if (!type) { @@ -358,18 +326,23 @@ int class_unregister_type(const char *name) RETURN(-EINVAL); } - if (type->typ_refcnt) { - CERROR("type %s has refcount (%d)\n", name, type->typ_refcnt); + if (atomic_read(&type->typ_refcnt)) { + CERROR("type %s has refcount (%d)\n", name, + atomic_read(&type->typ_refcnt)); /* This is a bad situation, let's make the best of it */ /* Remove ops, but leave the name for debugging */ - OBD_FREE_PTR(type->typ_dt_ops); - OBD_FREE_PTR(type->typ_md_ops); - RETURN(-EBUSY); + type->typ_dt_ops = NULL; + type->typ_md_ops = NULL; + GOTO(out_put, rc = -EBUSY); } + /* Put the final ref */ + kobject_put(&type->typ_kobj); +out_put: + /* Put the ref returned by class_search_type() */ kobject_put(&type->typ_kobj); - RETURN(0); + RETURN(rc); } /* class_unregister_type */ EXPORT_SYMBOL(class_unregister_type); @@ -782,7 +755,6 @@ void class_obd_list(void) atomic_read(&obd->obd_refcount)); } read_unlock(&obd_dev_lock); - return; } /* Search for a client OBD connected to tgt_uuid. If grp_uuid is @@ -927,7 +899,7 @@ out: RETURN(rc); } -static struct portals_handle_ops export_handle_ops; +static const char export_handle_owner[] = "export"; /* map connection to client */ struct obd_export *class_conn2export(struct lustre_handle *conn) @@ -946,7 +918,7 @@ struct obd_export *class_conn2export(struct lustre_handle *conn) } CDEBUG(D_INFO, "looking for export cookie %#llx\n", conn->cookie); - export = class_handle2object(conn->cookie, &export_handle_ops); + export = class_handle2object(conn->cookie, export_handle_owner); RETURN(export); } EXPORT_SYMBOL(class_conn2export); @@ -974,7 +946,7 @@ static void class_export_destroy(struct obd_export *exp) struct obd_device *obd = exp->exp_obd; ENTRY; - LASSERT_ATOMIC_ZERO(&exp->exp_refcount); + LASSERT(refcount_read(&exp->exp_handle.h_ref) == 0); LASSERT(obd != NULL); CDEBUG(D_IOCTL, "destroying export %p/%s for %s\n", exp, @@ -994,25 +966,16 @@ static void class_export_destroy(struct obd_export *exp) if (exp != obd->obd_self_export) class_decref(obd, "export", exp); - OBD_FREE_RCU(exp, sizeof(*exp), &exp->exp_handle); + OBD_FREE_PRE(exp, sizeof(*exp), "rcu"); + kfree_rcu(exp, exp_handle.h_rcu); EXIT; } -static void export_handle_addref(void *export) -{ - class_export_get(export); -} - -static struct portals_handle_ops export_handle_ops = { - .hop_addref = export_handle_addref, - .hop_free = NULL, -}; - struct obd_export *class_export_get(struct obd_export *exp) { - atomic_inc(&exp->exp_refcount); - CDEBUG(D_INFO, "GETting export %p : new refcount %d\n", exp, - atomic_read(&exp->exp_refcount)); + refcount_inc(&exp->exp_handle.h_ref); + CDEBUG(D_INFO, "GET export %p refcount=%d\n", exp, + refcount_read(&exp->exp_handle.h_ref)); return exp; } EXPORT_SYMBOL(class_export_get); @@ -1020,11 +983,12 @@ EXPORT_SYMBOL(class_export_get); void class_export_put(struct obd_export *exp) { LASSERT(exp != NULL); - LASSERT_ATOMIC_GT_LT(&exp->exp_refcount, 0, LI_POISON); + LASSERT(refcount_read(&exp->exp_handle.h_ref) > 0); + LASSERT(refcount_read(&exp->exp_handle.h_ref) < LI_POISON); CDEBUG(D_INFO, "PUTting export %p : new refcount %d\n", exp, - atomic_read(&exp->exp_refcount) - 1); + refcount_read(&exp->exp_handle.h_ref) - 1); - if (atomic_dec_and_test(&exp->exp_refcount)) { + if (refcount_dec_and_test(&exp->exp_handle.h_ref)) { struct obd_device *obd = exp->exp_obd; CDEBUG(D_IOCTL, "final put %p/%s\n", @@ -1067,7 +1031,6 @@ struct obd_export *__class_new_export(struct obd_device *obd, struct obd_uuid *cluuid, bool is_self) { struct obd_export *export; - struct cfs_hash *hash = NULL; int rc = 0; ENTRY; @@ -1079,7 +1042,7 @@ struct obd_export *__class_new_export(struct obd_device *obd, export->exp_lock_hash = NULL; export->exp_flock_hash = NULL; /* 2 = class_handle_hash + last */ - atomic_set(&export->exp_refcount, 2); + refcount_set(&export->exp_handle.h_ref, 2); atomic_set(&export->exp_rpc_count, 0); atomic_set(&export->exp_cb_count, 0); atomic_set(&export->exp_locks_count, 0); @@ -1093,14 +1056,13 @@ struct obd_export *__class_new_export(struct obd_device *obd, spin_lock_init(&export->exp_uncommitted_replies_lock); INIT_LIST_HEAD(&export->exp_uncommitted_replies); INIT_LIST_HEAD(&export->exp_req_replay_queue); - INIT_LIST_HEAD_RCU(&export->exp_handle.h_link); + INIT_HLIST_NODE(&export->exp_handle.h_link); INIT_LIST_HEAD(&export->exp_hp_rpcs); INIT_LIST_HEAD(&export->exp_reg_rpcs); - class_handle_hash(&export->exp_handle, &export_handle_ops); + class_handle_hash(&export->exp_handle, export_handle_owner); export->exp_last_request_time = ktime_get_real_seconds(); spin_lock_init(&export->exp_lock); spin_lock_init(&export->exp_rpc_lock); - INIT_HLIST_NODE(&export->exp_uuid_hash); INIT_HLIST_NODE(&export->exp_nid_hash); INIT_HLIST_NODE(&export->exp_gen_hash); spin_lock_init(&export->exp_bl_list_lock); @@ -1113,33 +1075,22 @@ struct obd_export *__class_new_export(struct obd_device *obd, export->exp_client_uuid = *cluuid; obd_init_export(export); + at_init(&export->exp_bl_lock_at, obd_timeout, 0); + + spin_lock(&obd->obd_dev_lock); if (!obd_uuid_equals(cluuid, &obd->obd_uuid)) { - spin_lock(&obd->obd_dev_lock); /* shouldn't happen, but might race */ if (obd->obd_stopping) GOTO(exit_unlock, rc = -ENODEV); - hash = cfs_hash_getref(obd->obd_uuid_hash); - if (hash == NULL) - GOTO(exit_unlock, rc = -ENODEV); - spin_unlock(&obd->obd_dev_lock); - - rc = cfs_hash_add_unique(hash, cluuid, &export->exp_uuid_hash); + rc = obd_uuid_add(obd, export); if (rc != 0) { - LCONSOLE_WARN("%s: denying duplicate export for %s, %d\n", + LCONSOLE_WARN("%s: denying duplicate export for %s: rc = %d\n", obd->obd_name, cluuid->uuid, rc); - GOTO(exit_err, rc = -EALREADY); + GOTO(exit_unlock, rc = -EALREADY); } } - at_init(&export->exp_bl_lock_at, obd_timeout, 0); - spin_lock(&obd->obd_dev_lock); - if (obd->obd_stopping) { - if (hash) - cfs_hash_del(hash, cluuid, &export->exp_uuid_hash); - GOTO(exit_unlock, rc = -ESHUTDOWN); - } - if (!is_self) { class_incref(obd, "export", export); list_add_tail(&export->exp_obd_chain_timed, @@ -1151,17 +1102,11 @@ struct obd_export *__class_new_export(struct obd_device *obd, INIT_LIST_HEAD(&export->exp_obd_chain); } spin_unlock(&obd->obd_dev_lock); - if (hash) - cfs_hash_putref(hash); RETURN(export); exit_unlock: spin_unlock(&obd->obd_dev_lock); -exit_err: - if (hash) - cfs_hash_putref(hash); class_handle_unhash(&export->exp_handle); - LASSERT(hlist_unhashed(&export->exp_uuid_hash)); obd_destroy_export(export); OBD_FREE_PTR(export); return ERR_PTR(rc); @@ -1191,10 +1136,8 @@ void class_unlink_export(struct obd_export *exp) spin_lock(&exp->exp_obd->obd_dev_lock); /* delete an uuid-export hashitem from hashtables */ - if (!hlist_unhashed(&exp->exp_uuid_hash)) - cfs_hash_del(exp->exp_obd->obd_uuid_hash, - &exp->exp_client_uuid, - &exp->exp_uuid_hash); + if (exp != exp->exp_obd->obd_self_export) + obd_uuid_del(exp->exp_obd, exp); #ifdef HAVE_SERVER_SUPPORT if (!hlist_unhashed(&exp->exp_gen_hash)) { @@ -1275,8 +1218,6 @@ void class_import_put(struct obd_import *imp) obd_zombie_import_add(imp); } - /* catch possible import put race */ - LASSERT_ATOMIC_GE_LT(&imp->imp_refcount, 0, LI_POISON); EXIT; } EXPORT_SYMBOL(class_import_put); @@ -1326,7 +1267,7 @@ struct obd_import *class_new_import(struct obd_device *obd) init_waitqueue_head(&imp->imp_recovery_waitq); INIT_WORK(&imp->imp_zombie_work, obd_zombie_imp_cull); - if (curr_pid_ns->child_reaper) + if (curr_pid_ns && curr_pid_ns->child_reaper) imp->imp_sec_refpid = curr_pid_ns->child_reaper->pid; else imp->imp_sec_refpid = 1; @@ -1579,11 +1520,10 @@ static void class_disconnect_export_list(struct list_head *list, void class_disconnect_exports(struct obd_device *obd) { - struct list_head work_list; + LIST_HEAD(work_list); ENTRY; /* Move all of the exports from obd_exports to a work list, en masse. */ - INIT_LIST_HEAD(&work_list); spin_lock(&obd->obd_dev_lock); list_splice_init(&obd->obd_exports, &work_list); list_splice_init(&obd->obd_delayed_exports, &work_list); @@ -1606,12 +1546,11 @@ EXPORT_SYMBOL(class_disconnect_exports); void class_disconnect_stale_exports(struct obd_device *obd, int (*test_export)(struct obd_export *)) { - struct list_head work_list; + LIST_HEAD(work_list); struct obd_export *exp, *n; - int evicted = 0; - ENTRY; + int evicted = 0; + ENTRY; - INIT_LIST_HEAD(&work_list); spin_lock(&obd->obd_dev_lock); list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) { @@ -1738,9 +1677,9 @@ int obd_export_evict_by_nid(struct obd_device *obd, const char *nid) } EXPORT_SYMBOL(obd_export_evict_by_nid); +#ifdef HAVE_SERVER_SUPPORT int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid) { - struct cfs_hash *uuid_hash; struct obd_export *doomed_exp = NULL; struct obd_uuid doomed_uuid; int exports_evicted = 0; @@ -1750,19 +1689,15 @@ int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid) spin_unlock(&obd->obd_dev_lock); return exports_evicted; } - uuid_hash = obd->obd_uuid_hash; - cfs_hash_getref(uuid_hash); spin_unlock(&obd->obd_dev_lock); obd_str2uuid(&doomed_uuid, uuid); if (obd_uuid_equals(&doomed_uuid, &obd->obd_uuid)) { CERROR("%s: can't evict myself\n", obd->obd_name); - cfs_hash_putref(uuid_hash); return exports_evicted; } - doomed_exp = cfs_hash_lookup(uuid_hash, &doomed_uuid); - + doomed_exp = obd_uuid_lookup(obd, &doomed_uuid); if (doomed_exp == NULL) { CERROR("%s: can't disconnect %s: no exports found\n", obd->obd_name, uuid); @@ -1771,12 +1706,13 @@ int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid) obd->obd_name, doomed_exp->exp_client_uuid.uuid); class_fail_export(doomed_exp); class_export_put(doomed_exp); + obd_uuid_del(obd, doomed_exp); exports_evicted++; } - cfs_hash_putref(uuid_hash); return exports_evicted; } +#endif /* HAVE_SERVER_SUPPORT */ #if LUSTRE_TRACKS_LOCK_EXP_REFS void (*class_export_dump_hook)(struct obd_export*) = NULL; @@ -1802,7 +1738,8 @@ static void print_export_data(struct obd_export *exp, const char *status, CDEBUG(debug_level, "%s: %s %p %s %s %d (%d %d %d) %d %d %d %d: " "%p %s %llu stale:%d\n", exp->exp_obd->obd_name, status, exp, exp->exp_client_uuid.uuid, - obd_export_nid2str(exp), atomic_read(&exp->exp_refcount), + obd_export_nid2str(exp), + refcount_read(&exp->exp_handle.h_ref), atomic_read(&exp->exp_rpc_count), atomic_read(&exp->exp_cb_count), atomic_read(&exp->exp_locks_count), @@ -2305,15 +2242,6 @@ static inline bool obd_mod_rpc_slot_avail(struct client_obd *cli, return avail; } -static inline bool obd_skip_mod_rpc_slot(const struct lookup_intent *it) -{ - if (it != NULL && - (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || - it->it_op == IT_READDIR || - (it->it_op == IT_LAYOUT && !(it->it_flags & MDS_FMODE_WRITE)))) - return true; - return false; -} /* Get a modify RPC slot from the obd client @cli according * to the kind of operation @opc that is going to be sent @@ -2323,19 +2251,11 @@ static inline bool obd_skip_mod_rpc_slot(const struct lookup_intent *it) * Returns the tag to be set in the request message. Tag 0 * is reserved for non-modifying requests. */ -__u16 obd_get_mod_rpc_slot(struct client_obd *cli, __u32 opc, - struct lookup_intent *it) +__u16 obd_get_mod_rpc_slot(struct client_obd *cli, __u32 opc) { - struct l_wait_info lwi = LWI_INTR(NULL, NULL); bool close_req = false; __u16 i, max; - /* read-only metadata RPCs don't consume a slot on MDT - * for reply reconstruction - */ - if (obd_skip_mod_rpc_slot(it)) - return 0; - if (opc == MDS_CLOSE) close_req = true; @@ -2357,8 +2277,8 @@ __u16 obd_get_mod_rpc_slot(struct client_obd *cli, __u32 opc, spin_unlock(&cli->cl_mod_rpcs_lock); /* tag 0 is reserved for non-modify RPCs */ - CDEBUG(D_RPCTRACE, "%s: modify RPC slot %u is allocated" - "opc %u, max %hu\n", + CDEBUG(D_RPCTRACE, + "%s: modify RPC slot %u is allocated opc %u, max %hu\n", cli->cl_import->imp_obd->obd_name, i + 1, opc, max); @@ -2370,23 +2290,21 @@ __u16 obd_get_mod_rpc_slot(struct client_obd *cli, __u32 opc, "opc %u, max %hu\n", cli->cl_import->imp_obd->obd_name, opc, max); - l_wait_event_exclusive(cli->cl_mod_rpcs_waitq, - obd_mod_rpc_slot_avail(cli, close_req), - &lwi); + wait_event_idle_exclusive(cli->cl_mod_rpcs_waitq, + obd_mod_rpc_slot_avail(cli, + close_req)); } while (true); } EXPORT_SYMBOL(obd_get_mod_rpc_slot); /* Put a modify RPC slot from the obd client @cli according - * to the kind of operation @opc that has been sent and the - * intent @it of the operation if it applies. + * to the kind of operation @opc that has been sent. */ -void obd_put_mod_rpc_slot(struct client_obd *cli, __u32 opc, - struct lookup_intent *it, __u16 tag) +void obd_put_mod_rpc_slot(struct client_obd *cli, __u32 opc, __u16 tag) { bool close_req = false; - if (obd_skip_mod_rpc_slot(it)) + if (tag == 0) return; if (opc == MDS_CLOSE)