static DEFINE_SPINLOCK(obd_stale_export_lock);
static atomic_t obd_stale_export_num = ATOMIC_INIT(0);
-int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
-EXPORT_SYMBOL(ptlrpc_put_connection_superhack);
-
/*
* support functions: we could use inter-module communication, but this
* is more portable to other OS's
int class_register_type(const struct obd_ops *dt_ops,
const struct md_ops *md_ops,
- bool enable_proc, struct lprocfs_vars *vars,
+ bool enable_proc, struct ldebugfs_vars *vars,
const char *name, struct lu_device_type *ldt)
{
struct obd_type *type;
return obd;
}
+EXPORT_SYMBOL(class_num2obd);
/**
* Find obd in obd_dev[] by name or uuid.
exp->exp_client_uuid.uuid, obd->obd_name);
/* "Local" exports (lctl, LOV->{mdc,osc}) have no connection. */
- if (exp->exp_connection)
- ptlrpc_put_connection_superhack(exp->exp_connection);
+ ptlrpc_connection_put(exp->exp_connection);
LASSERT(list_empty(&exp->exp_outstanding_replies));
LASSERT(list_empty(&exp->exp_uncommitted_replies));
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_nid_hash);
INIT_HLIST_NODE(&export->exp_gen_hash);
spin_lock_init(&export->exp_bl_list_lock);
INIT_LIST_HEAD(&export->exp_bl_list);
/* Import management functions */
static void obd_zombie_import_free(struct obd_import *imp)
{
- ENTRY;
+ ENTRY;
- CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp,
- imp->imp_obd->obd_name);
+ CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp,
+ imp->imp_obd->obd_name);
LASSERT(refcount_read(&imp->imp_refcount) == 0);
- ptlrpc_put_connection_superhack(imp->imp_connection);
+ ptlrpc_connection_put(imp->imp_connection);
while (!list_empty(&imp->imp_conn_list)) {
struct obd_import_conn *imp_conn;
imp_conn = list_first_entry(&imp->imp_conn_list,
struct obd_import_conn, oic_item);
list_del_init(&imp_conn->oic_item);
- ptlrpc_put_connection_superhack(imp_conn->oic_conn);
- OBD_FREE(imp_conn, sizeof(*imp_conn));
- }
+ ptlrpc_connection_put(imp_conn->oic_conn);
+ OBD_FREE(imp_conn, sizeof(*imp_conn));
+ }
- LASSERT(imp->imp_sec == NULL);
- class_decref(imp->imp_obd, "import", imp);
+ LASSERT(imp->imp_sec == NULL);
+ LASSERTF(atomic_read(&imp->imp_reqs) == 0, "%s: imp_reqs = %d\n",
+ imp->imp_obd->obd_name, atomic_read(&imp->imp_reqs));
+ class_decref(imp->imp_obd, "import", imp);
OBD_FREE_PTR(imp);
EXIT;
}
refcount_set(&imp->imp_refcount, 2);
atomic_set(&imp->imp_unregistering, 0);
+ atomic_set(&imp->imp_reqs, 0);
atomic_set(&imp->imp_inflight, 0);
atomic_set(&imp->imp_replay_inflight, 0);
+ init_waitqueue_head(&imp->imp_replay_waitq);
atomic_set(&imp->imp_inval_count, 0);
INIT_LIST_HEAD(&imp->imp_conn_list);
init_imp_at(&imp->imp_at);
spin_lock(&export->exp_lock);
already_disconnected = export->exp_disconnected;
export->exp_disconnected = 1;
+#ifdef HAVE_SERVER_SUPPORT
/* We hold references of export for uuid hash
* and nid_hash and export link at least. So
- * it is safe to call cfs_hash_del in there. */
- if (!hlist_unhashed(&export->exp_nid_hash))
- cfs_hash_del(export->exp_obd->obd_nid_hash,
- &export->exp_connection->c_peer.nid,
- &export->exp_nid_hash);
+ * it is safe to call rh*table_remove_fast in
+ * there.
+ */
+ obd_nid_del(export->exp_obd, export);
+#endif /* HAVE_SERVER_SUPPORT */
spin_unlock(&export->exp_lock);
/* class_cleanup(), abort_recovery(), and class_fail_export()
* all end up in here, and if any of them race we shouldn't
* call extra class_export_puts(). */
- if (already_disconnected) {
- LASSERT(hlist_unhashed(&export->exp_nid_hash));
+ if (already_disconnected)
GOTO(no_disconn, already_disconnected);
- }
CDEBUG(D_IOCTL, "disconnect: cookie %#llx\n",
export->exp_handle.h_cookie);
}
EXPORT_SYMBOL(class_fail_export);
-int obd_export_evict_by_nid(struct obd_device *obd, const char *nid)
+#ifdef HAVE_SERVER_SUPPORT
+
+static int take_first(struct obd_export *exp, void *data)
{
- struct cfs_hash *nid_hash;
- struct obd_export *doomed_exp = NULL;
- int exports_evicted = 0;
+ struct obd_export **expp = data;
+ if (*expp)
+ /* already have one */
+ return 0;
+ if (exp->exp_failed)
+ /* Don't want this one */
+ return 0;
+ if (!refcount_inc_not_zero(&exp->exp_handle.h_ref))
+ /* Cannot get a ref on this one */
+ return 0;
+ *expp = exp;
+ return 1;
+}
+
+int obd_export_evict_by_nid(struct obd_device *obd, const char *nid)
+{
lnet_nid_t nid_key = libcfs_str2nid((char *)nid);
+ struct obd_export *doomed_exp;
+ int exports_evicted = 0;
spin_lock(&obd->obd_dev_lock);
/* umount has run already, so evict thread should leave
spin_unlock(&obd->obd_dev_lock);
return exports_evicted;
}
- nid_hash = obd->obd_nid_hash;
- cfs_hash_getref(nid_hash);
spin_unlock(&obd->obd_dev_lock);
- do {
- doomed_exp = cfs_hash_lookup(nid_hash, &nid_key);
- if (doomed_exp == NULL)
- break;
+ doomed_exp = NULL;
+ while (obd_nid_export_for_each(obd, nid_key,
+ take_first, &doomed_exp) > 0) {
- LASSERTF(doomed_exp->exp_connection->c_peer.nid == nid_key,
- "nid %s found, wanted nid %s, requested nid %s\n",
- obd_export_nid2str(doomed_exp),
- libcfs_nid2str(nid_key), nid);
- LASSERTF(doomed_exp != obd->obd_self_export,
- "self-export is hashed by NID?\n");
- exports_evicted++;
- LCONSOLE_WARN("%s: evicting %s (at %s) by administrative "
- "request\n", obd->obd_name,
+ LASSERTF(doomed_exp != obd->obd_self_export,
+ "self-export is hashed by NID?\n");
+
+ LCONSOLE_WARN("%s: evicting %s (at %s) by administrative request\n",
+ obd->obd_name,
obd_uuid2str(&doomed_exp->exp_client_uuid),
obd_export_nid2str(doomed_exp));
- class_fail_export(doomed_exp);
- class_export_put(doomed_exp);
- } while (1);
- cfs_hash_putref(nid_hash);
+ class_fail_export(doomed_exp);
+ class_export_put(doomed_exp);
+ exports_evicted++;
+ doomed_exp = NULL;
+ }
- if (!exports_evicted)
- CDEBUG(D_HA,"%s: can't disconnect NID '%s': no exports found\n",
- obd->obd_name, nid);
- return exports_evicted;
+ if (!exports_evicted)
+ CDEBUG(D_HA,
+ "%s: can't disconnect NID '%s': no exports found\n",
+ obd->obd_name, nid);
+ return exports_evicted;
}
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 obd_export *doomed_exp = NULL;
*/
int obd_zombie_impexp_init(void)
{
- zombie_wq = alloc_workqueue("obd_zombid", 0, 0);
- if (!zombie_wq)
- return -ENOMEM;
+ zombie_wq = cfs_cpt_bind_workqueue("obd_zombid", cfs_cpt_tab,
+ 0, CFS_CPT_ANY,
+ cfs_cpt_number(cfs_cpt_tab));
- return 0;
+ return IS_ERR(zombie_wq) ? PTR_ERR(zombie_wq) : 0;
}
/**
__u32 old;
int diff;
int i;
- const char *type_name;
int rc;
if (max > OBD_MAX_RIF_MAX || max < 1)
return -ERANGE;
- type_name = cli->cl_import->imp_obd->obd_type->typ_name;
- if (strcmp(type_name, LUSTRE_MDC_NAME) == 0) {
+ CDEBUG(D_INFO, "%s: max = %hu max_mod = %u rif = %u\n",
+ cli->cl_import->imp_obd->obd_name, max,
+ cli->cl_max_mod_rpcs_in_flight, cli->cl_max_rpcs_in_flight);
+
+ if (strcmp(cli->cl_import->imp_obd->obd_type->typ_name,
+ LUSTRE_MDC_NAME) == 0) {
/* adjust max_mod_rpcs_in_flight to ensure it is always
* strictly lower that max_rpcs_in_flight */
if (max < 2) {
- CERROR("%s: cannot set max_rpcs_in_flight to 1 "
- "because it must be higher than "
- "max_mod_rpcs_in_flight value",
+ CERROR("%s: cannot set mdc.*.max_rpcs_in_flight=1\n",
cli->cl_import->imp_obd->obd_name);
return -ERANGE;
}
int obd_set_max_mod_rpcs_in_flight(struct client_obd *cli, __u16 max)
{
- struct obd_connect_data *ocd;
+ struct obd_connect_data *ocd;
__u16 maxmodrpcs;
__u16 prev;
if (max > OBD_MAX_RIF_MAX || max < 1)
return -ERANGE;
- /* cannot exceed or equal max_rpcs_in_flight */
+ ocd = &cli->cl_import->imp_connect_data;
+ CDEBUG(D_INFO, "%s: max = %hu flags = %llx, max_mod = %u rif = %u\n",
+ cli->cl_import->imp_obd->obd_name, max, ocd->ocd_connect_flags,
+ ocd->ocd_maxmodrpcs, cli->cl_max_rpcs_in_flight);
+
+ if (max == OBD_MAX_RIF_MAX)
+ max = OBD_MAX_RIF_MAX - 1;
+
+ /* Cannot exceed or equal max_rpcs_in_flight. If we are asked to
+ * increase this value, also bump up max_rpcs_in_flight to match.
+ */
if (max >= cli->cl_max_rpcs_in_flight) {
- CERROR("%s: can't set max_mod_rpcs_in_flight to a value (%hu) "
- "higher or equal to max_rpcs_in_flight value (%u)\n",
- cli->cl_import->imp_obd->obd_name,
- max, cli->cl_max_rpcs_in_flight);
- return -ERANGE;
+ CDEBUG(D_INFO,
+ "%s: increasing max_rpcs_in_flight=%hu to allow larger max_mod_rpcs_in_flight=%u\n",
+ cli->cl_import->imp_obd->obd_name, max + 1, max);
+ obd_set_max_rpcs_in_flight(cli, max + 1);
}
- /* cannot exceed max modify RPCs in flight supported by the server */
- ocd = &cli->cl_import->imp_connect_data;
- if (ocd->ocd_connect_flags & OBD_CONNECT_MULTIMODRPCS)
+ /* cannot exceed max modify RPCs in flight supported by the server,
+ * but verify ocd_connect_flags is at least initialized first. If
+ * not, allow it and fix value later in ptlrpc_connect_set_flags().
+ */
+ if (!ocd->ocd_connect_flags) {
+ maxmodrpcs = cli->cl_max_rpcs_in_flight - 1;
+ } else if (ocd->ocd_connect_flags & OBD_CONNECT_MULTIMODRPCS) {
maxmodrpcs = ocd->ocd_maxmodrpcs;
- else
+ if (maxmodrpcs == 0) { /* connection not finished yet */
+ maxmodrpcs = cli->cl_max_rpcs_in_flight - 1;
+ CDEBUG(D_INFO,
+ "%s: partial connect, assume maxmodrpcs=%hu\n",
+ cli->cl_import->imp_obd->obd_name, maxmodrpcs);
+ }
+ } else {
maxmodrpcs = 1;
+ }
if (max > maxmodrpcs) {
- CERROR("%s: can't set max_mod_rpcs_in_flight to a value (%hu) "
- "higher than max_mod_rpcs_per_client value (%hu) "
- "returned by the server at connection\n",
+ CERROR("%s: can't set max_mod_rpcs_in_flight=%hu higher than ocd_maxmodrpcs=%hu returned by the server at connection\n",
cli->cl_import->imp_obd->obd_name,
max, maxmodrpcs);
return -ERANGE;