one is completed. As a result, some RPCs are stuck in the queue
and are never sent.
+Severity : normal
+Bugzilla : 15684
+Description: Procfs and llog threads access destoryed import sometimes.
+Details : Sync the import destoryed process with procfs and llog threads by
+ the import refcount and semaphore.
+
-------------------------------------------------------------------------------
* the import in a client obd_device for a lprocfs entry */
#define LPROCFS_CLIMP_CHECK(obd) do { \
typecheck(struct obd_device *, obd); \
- mutex_down(&(obd)->u.cli.cl_sem); \
+ down_read(&(obd)->u.cli.cl_sem); \
if ((obd)->u.cli.cl_import == NULL) { \
- mutex_up(&(obd)->u.cli.cl_sem); \
+ up_read(&(obd)->u.cli.cl_sem); \
return -ENODEV; \
} \
} while(0)
#define LPROCFS_CLIMP_EXIT(obd) \
- mutex_up(&(obd)->u.cli.cl_sem);
+ up_read(&(obd)->u.cli.cl_sem);
/* write the name##_seq_show function, call LPROC_SEQ_FOPS_RO for read-only
struct obd_import;
struct lustre_cache;
struct client_obd {
- struct semaphore cl_sem;
+ struct rw_semaphore cl_sem;
struct obd_uuid cl_target_uuid;
struct obd_import *cl_import; /* ptlrpc connection state */
int cl_conn_count;
RETURN(-EINVAL);
}
- sema_init(&cli->cl_sem, 1);
+ init_rwsem(&cli->cl_sem);
sema_init(&cli->cl_mgc_sem, 1);
cli->cl_conn_count = 0;
memcpy(server_uuid.uuid, lustre_cfg_buf(lcfg, 2),
int rc;
ENTRY;
- mutex_down(&cli->cl_sem);
+ down_write(&cli->cl_sem);
rc = class_connect(dlm_handle, obd, cluuid);
if (rc)
GOTO(out_sem, rc);
class_export_put(exp);
}
out_sem:
- mutex_up(&cli->cl_sem);
+ up_write(&cli->cl_sem);
if (to_be_freed)
ldlm_namespace_free_post(to_be_freed);
return rc;
cli = &obd->u.cli;
imp = cli->cl_import;
- mutex_down(&cli->cl_sem);
+ down_write(&cli->cl_sem);
if (!cli->cl_conn_count) {
CERROR("disconnecting disconnected device (%s)\n",
obd->obd_name);
if (!rc && err)
rc = err;
out_sem:
- mutex_up(&cli->cl_sem);
+ up_write(&cli->cl_sem);
if (to_be_freed)
ldlm_namespace_free_post(to_be_freed);
RETURN(rc);
{
struct ptlrpc_request *req;
struct obd_statfs *msfs;
+ struct obd_import *imp = NULL;
int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*msfs) };
ENTRY;
+ /*Since the request might also come from lprocfs, so we need
+ *sync this with client_disconnect_export Bug15684*/
+ down_read(&obd->u.cli.cl_sem);
+ if (obd->u.cli.cl_import)
+ imp = class_import_get(obd->u.cli.cl_import);
+ up_read(&obd->u.cli.cl_sem);
+ if (!imp)
+ RETURN(-ENODEV);
+
+
/* We could possibly pass max_age in the request (as an absolute
* timestamp or a "seconds.usec ago") so the target can avoid doing
* extra calls into the filesystem if that isn't necessary (e.g.
* during mount that would help a bit). Having relative timestamps
* is not so great if request processing is slow, while absolute
* timestamps are not ideal because they need time synchronization. */
- req = ptlrpc_prep_req(obd->u.cli.cl_import, LUSTRE_MDS_VERSION,
- MDS_STATFS, 1, NULL, NULL);
+ req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION, MDS_STATFS, 1, NULL,
+ NULL);
if (!req)
- RETURN(-ENOMEM);
+ GOTO(output, rc = -ENOMEM);
ptlrpc_req_set_repsize(req, 2, size);
EXIT;
out:
ptlrpc_req_finished(req);
-
+output:
+ class_import_put(imp);
return rc;
}
class_destroy_import(imp);
obd->u.cli.cl_import = NULL;
}
- break;
- case OBD_CLEANUP_SELF_EXP:
rc = obd_llog_finish(obd, 0);
if (rc != 0)
CERROR("failed to cleanup llogging subsystems\n");
+ break;
+ case OBD_CLEANUP_SELF_EXP:
+ break;
case OBD_CLEANUP_OBD:
break;
}
&llog_client_ops);
if (rc == 0) {
ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
- ctxt->loc_imp = obd->u.cli.cl_import;
+ llog_initiator_connect(ctxt);
llog_ctxt_put(ctxt);
}
&llog_client_ops);
if (rc == 0) {
ctxt = llog_get_context(obd, LLOG_LOVEA_REPL_CTXT);
- ctxt->loc_imp = obd->u.cli.cl_import;
+ llog_initiator_connect(ctxt);
llog_ctxt_put(ctxt);
}
&llog_client_ops);
if (rc == 0) {
ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
- ctxt->loc_imp = obd->u.cli.cl_import;
+ llog_initiator_connect(ctxt);
llog_ctxt_put(ctxt);
}
spin_unlock(&config_list_lock);
cfs_waitq_signal(&rq_waitq);
}
- break;
- case OBD_CLEANUP_SELF_EXP:
rc = obd_llog_finish(obd, 0);
if (rc != 0)
CERROR("failed to cleanup llogging subsystems\n");
break;
+ case OBD_CLEANUP_SELF_EXP:
+ break;
case OBD_CLEANUP_OBD:
break;
}
&llog_client_ops);
if (rc == 0) {
ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
- ctxt->loc_imp = obd->u.cli.cl_import;
+ llog_initiator_connect(ctxt);
llog_ctxt_put(ctxt);
}
{
if (ctxt->loc_exp)
class_export_put(ctxt->loc_exp);
+ if (ctxt->loc_imp) {
+ class_import_put(ctxt->loc_imp);
+ ctxt->loc_imp = NULL;
+ }
OBD_FREE(ctxt, sizeof(*ctxt));
return;
}
{
struct obd_statfs *msfs;
struct ptlrpc_request *req;
+ struct obd_import *imp = NULL;
int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*osfs) };
ENTRY;
+ /*Since the request might also come from lprocfs, so we need
+ *sync this with client_disconnect_export Bug15684*/
+ down_read(&obd->u.cli.cl_sem);
+ if (obd->u.cli.cl_import)
+ imp = class_import_get(obd->u.cli.cl_import);
+ up_read(&obd->u.cli.cl_sem);
+ if (!imp)
+ RETURN(-ENODEV);
+
/* We could possibly pass max_age in the request (as an absolute
* timestamp or a "seconds.usec ago") so the target can avoid doing
* extra calls into the filesystem if that isn't necessary (e.g.
* during mount that would help a bit). Having relative timestamps
* is not so great if request processing is slow, while absolute
* timestamps are not ideal because they need time synchronization. */
- req = ptlrpc_prep_req(obd->u.cli.cl_import, LUSTRE_OST_VERSION,
+ req = ptlrpc_prep_req(imp, LUSTRE_OST_VERSION,
OST_STATFS, 1, NULL, NULL);
+
+ class_import_put(imp);
if (!req)
RETURN(-ENOMEM);
oscc->oscc_flags &= ~OSCC_FLAG_NOSPC;
spin_unlock(&oscc->oscc_lock);
}
+ CDEBUG(D_INFO, "notify server \n");
rc = obd_notify_observer(obd, obd, OBD_NOTIFY_ACTIVE, NULL);
break;
}
class_destroy_import(imp);
obd->u.cli.cl_import = NULL;
}
- break;
- }
- case OBD_CLEANUP_SELF_EXP:
rc = obd_llog_finish(obd, 0);
if (rc != 0)
CERROR("failed to cleanup llogging subsystems\n");
break;
+ }
+ case OBD_CLEANUP_SELF_EXP:
+ break;
case OBD_CLEANUP_OBD:
break;
}
#include <lustre_net.h>
#include <libcfs/list.h>
+#define LLOG_CLIENT_ENTRY(ctxt, imp) do { \
+ mutex_down(&ctxt->loc_sem); \
+ if (ctxt->loc_imp) { \
+ imp = class_import_get(ctxt->loc_imp); \
+ } else { \
+ CERROR("ctxt->loc_imp == NULL for context idx %d." \
+ "Unable to complete MDS/OSS recovery," \
+ "but I'll try again next time. Not fatal.\n", \
+ ctxt->loc_idx); \
+ imp = NULL; \
+ mutex_up(&ctxt->loc_sem); \
+ return (-EINVAL); \
+ } \
+ mutex_up(&ctxt->loc_sem); \
+} while(0)
+
+#define LLOG_CLIENT_EXIT(ctxt, imp) do { \
+ mutex_down(&ctxt->loc_sem); \
+ if (ctxt->loc_imp != imp) \
+ CWARN("loc_imp has changed from %p to %p", \
+ ctxt->loc_imp, imp); \
+ class_import_put(imp); \
+ mutex_up(&ctxt->loc_sem); \
+} while(0)
+
/* This is a callback from the llog_* functions.
* Assumes caller has already pushed us into the kernel context. */
static int llog_client_create(struct llog_ctxt *ctxt, struct llog_handle **res,
int rc;
ENTRY;
- if (ctxt->loc_imp == NULL) {
- /* This used to be an assert; bug 6200 */
- CERROR("ctxt->loc_imp == NULL for context idx %d. Unable to "
- "complete MDS/OSS recovery, but I'll try again next "
- "time. Not fatal.\n", ctxt->loc_idx);
- RETURN(-EINVAL);
- }
- imp = ctxt->loc_imp;
+ LLOG_CLIENT_ENTRY(ctxt, imp);
handle = llog_alloc_handle();
if (handle == NULL)
- RETURN(-ENOMEM);
+ GOTO(out, rc = -ENOMEM);
*res = handle;
memset(&req_body, 0, sizeof(req_body));
out:
if (req)
ptlrpc_req_finished(req);
+ LLOG_CLIENT_EXIT(ctxt, imp);
RETURN(rc);
err_free:
static int llog_client_destroy(struct llog_handle *loghandle)
{
- struct obd_import *imp = loghandle->lgh_ctxt->loc_imp;
+ struct obd_import *imp;
struct ptlrpc_request *req = NULL;
struct llogd_body *body;
int size[] = { sizeof(struct ptlrpc_body), sizeof(*body) };
int rc;
ENTRY;
+ LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
LLOG_ORIGIN_HANDLE_DESTROY, 2, size, NULL);
if (!req)
- RETURN(-ENOMEM);
+ GOTO(out, rc = -ENOMEM);
body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
body->lgd_logid = loghandle->lgh_id;
rc = ptlrpc_queue_wait(req);
ptlrpc_req_finished(req);
+out:
+ LLOG_CLIENT_EXIT(loghandle->lgh_ctxt, imp);
RETURN(rc);
}
int *cur_idx, int next_idx,
__u64 *cur_offset, void *buf, int len)
{
- struct obd_import *imp = loghandle->lgh_ctxt->loc_imp;
+ struct obd_import *imp;
struct ptlrpc_request *req = NULL;
struct llogd_body *body;
void * ptr;
int rc;
ENTRY;
+ LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
LLOG_ORIGIN_HANDLE_NEXT_BLOCK, 2, size, NULL);
if (!req)
- GOTO(out, rc = -ENOMEM);
+ GOTO(out, rc =-ENOMEM);
body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
body->lgd_logid = loghandle->lgh_id;
out:
if (req)
ptlrpc_req_finished(req);
+ LLOG_CLIENT_EXIT(loghandle->lgh_ctxt, imp);
RETURN(rc);
}
static int llog_client_prev_block(struct llog_handle *loghandle,
int prev_idx, void *buf, int len)
{
- struct obd_import *imp = loghandle->lgh_ctxt->loc_imp;
+ struct obd_import *imp;
struct ptlrpc_request *req = NULL;
struct llogd_body *body;
void * ptr;
int rc;
ENTRY;
+ LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp);
req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
LLOG_ORIGIN_HANDLE_PREV_BLOCK, 2, size, NULL);
if (!req)
out:
if (req)
ptlrpc_req_finished(req);
+ LLOG_CLIENT_EXIT(loghandle->lgh_ctxt, imp);
RETURN(rc);
}
static int llog_client_read_header(struct llog_handle *handle)
{
- struct obd_import *imp = handle->lgh_ctxt->loc_imp;
+ struct obd_import *imp;
struct ptlrpc_request *req = NULL;
struct llogd_body *body;
struct llog_log_hdr *hdr;
int rc;
ENTRY;
+ LLOG_CLIENT_ENTRY(handle->lgh_ctxt, imp);
req = ptlrpc_prep_req(imp, LUSTRE_LOG_VERSION,
LLOG_ORIGIN_HANDLE_READ_HEADER, 2, size, NULL);
if (!req)
out:
if (req)
ptlrpc_req_finished(req);
+ LLOG_CLIENT_EXIT(handle->lgh_ctxt, imp);
RETURN(rc);
}
{
ENTRY;
LASSERT(ctxt);
- ctxt->loc_imp = imp;
+ mutex_down(&ctxt->loc_sem);
+ if (ctxt->loc_imp != imp) {
+ CWARN("changing the import %p - %p\n", ctxt->loc_imp, imp);
+ if (ctxt->loc_imp)
+ class_import_put(ctxt->loc_imp);
+ ctxt->loc_imp = class_import_get(imp);
+ }
+ mutex_up(&ctxt->loc_sem);
RETURN(0);
}
EXPORT_SYMBOL(llog_receptor_accept);
int llog_initiator_connect(struct llog_ctxt *ctxt)
{
+ struct obd_import *new_imp;
ENTRY;
LASSERT(ctxt);
- ctxt->loc_imp = ctxt->loc_obd->u.cli.cl_import;
+ new_imp = ctxt->loc_obd->u.cli.cl_import;
+ mutex_down(&ctxt->loc_sem);
+ if (ctxt->loc_imp != new_imp) {
+ if (ctxt->loc_imp)
+ class_import_put(ctxt->loc_imp);
+ ctxt->loc_imp = class_import_get(new_imp);
+ }
+ mutex_up(&ctxt->loc_sem);
RETURN(0);
}
EXPORT_SYMBOL(llog_initiator_connect);
llcd_put(ctxt->loc_llcd);
ctxt->loc_llcd = NULL;
}
- ctxt->loc_imp = NULL;
+ if (ctxt->loc_imp) {
+ class_import_put(ctxt->loc_imp);
+ ctxt->loc_imp = NULL;
+ }
mutex_up(&ctxt->loc_sem);
}