Exemple #1
0
/* Test named-log create/open, close */
static int llog_test_1(struct obd_device *obd, char *name)
{
        struct llog_handle *llh;
        struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
        int rc;
        int rc2;
        ENTRY;

        CWARN("1a: create a log with name: %s\n", name);
        LASSERT(ctxt);

        rc = llog_create(ctxt, &llh, NULL, name);
        if (rc) {
                CERROR("1a: llog_create with name %s failed: %d\n", name, rc);
                llog_ctxt_put(ctxt);
                RETURN(rc);
        }
        llog_init_handle(llh, LLOG_F_IS_PLAIN, &uuid);

        if ((rc = verify_handle("1", llh, 1)))
                GOTO(out, rc);

 out:
        CWARN("1b: close newly-created log\n");
        rc2 = llog_close(llh);
        llog_ctxt_put(ctxt);
        if (rc2) {
                CERROR("1b: close log %s failed: %d\n", name, rc2);
                if (rc == 0)
                        rc = rc2;
        }
        RETURN(rc);
}
Exemple #2
0
static int mdd_changelog_users_seq_show(struct seq_file *m, void *data)
{
    struct lu_env		 env;
    struct mdd_device	*mdd = m->private;
    struct llog_ctxt	*ctxt;
    __u64			 cur;
    int			 rc;

    ctxt = llog_get_context(mdd2obd_dev(mdd),
                            LLOG_CHANGELOG_USER_ORIG_CTXT);
    if (ctxt == NULL)
        return -ENXIO;
    LASSERT(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT);

    rc = lu_env_init(&env, LCT_LOCAL);
    if (rc) {
        llog_ctxt_put(ctxt);
        return rc;
    }

    spin_lock(&mdd->mdd_cl.mc_lock);
    cur = mdd->mdd_cl.mc_index;
    spin_unlock(&mdd->mdd_cl.mc_lock);

    seq_printf(m, "current index: %llu\n", cur);
    seq_printf(m, "%-5s %s\n", "ID", "index");

    llog_cat_process(&env, ctxt->loc_handle, lprocfs_changelog_users_cb,
                     m, 0, 0);

    lu_env_fini(&env);
    llog_ctxt_put(ctxt);
    return 0;
}
Exemple #3
0
/* Add log records for each OSC that this object is striped over, and return
 * cookies for each one.  We _would_ have nice abstraction here, except that
 * we need to keep cookies in stripe order, even if some are NULL, so that
 * the right cookies are passed back to the right OSTs at the client side.
 * Unset cookies should be all-zero (which will never occur naturally). */
static int lov_llog_origin_add(const struct lu_env *env,
			       struct llog_ctxt *ctxt,
			       struct llog_rec_hdr *rec,
			       struct lov_stripe_md *lsm,
			       struct llog_cookie *logcookies, int numcookies)
{
        struct obd_device *obd = ctxt->loc_obd;
        struct lov_obd *lov = &obd->u.lov;
        int i, rc = 0, cookies = 0;
        ENTRY;

        LASSERTF(logcookies && numcookies >= lsm->lsm_stripe_count,
                 "logcookies %p, numcookies %d lsm->lsm_stripe_count %d \n",
                 logcookies, numcookies, lsm->lsm_stripe_count);

        for (i = 0; i < lsm->lsm_stripe_count; i++) {
                struct lov_oinfo *loi = lsm->lsm_oinfo[i];
                struct obd_device *child =
                        lov->lov_tgts[loi->loi_ost_idx]->ltd_exp->exp_obd;
                struct llog_ctxt *cctxt = llog_get_context(child, ctxt->loc_idx);

                /* fill mds unlink/setattr log record */
                switch (rec->lrh_type) {
                case MDS_UNLINK_REC: {
                        struct llog_unlink_rec *lur = (struct llog_unlink_rec *)rec;
                        lur->lur_oid = ostid_id(&loi->loi_oi);
                        lur->lur_oseq = (__u32)ostid_seq(&loi->loi_oi);
                        break;
                }
                case MDS_SETATTR64_REC: {
                        struct llog_setattr64_rec *lsr = (struct llog_setattr64_rec *)rec;
                        lsr->lsr_oi = loi->loi_oi;
                        break;
                }
                default:
                        break;
                }

		/* inject error in llog_obd_add() below */
		if (OBD_FAIL_CHECK(OBD_FAIL_MDS_FAIL_LOV_LOG_ADD)) {
			llog_ctxt_put(cctxt);
			cctxt = NULL;
		}
		rc = llog_obd_add(env, cctxt, rec, NULL, logcookies + cookies,
				  numcookies - cookies);
                llog_ctxt_put(cctxt);
                if (rc < 0) {
                        CERROR("Can't add llog (rc = %d) for stripe %d\n",
                               rc, cookies);
                        memset(logcookies + cookies, 0,
                               sizeof(struct llog_cookie));
                        rc = 1; /* skip this cookie */
                }
		/* Note that rc is always 1 if llog_obd_add was successful */
                cookies += rc;
        }
        RETURN(cookies);
}
int llog_origin_handle_next_block(struct ptlrpc_request *req)
{
	struct llog_handle	*loghandle;
	struct llogd_body	*body;
	struct llogd_body	*repbody;
	struct llog_ctxt	*ctxt;
	__u32			 flags;
	void			*ptr;
	int			 rc;

	ENTRY;

	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
	if (body == NULL)
		RETURN(err_serious(-EFAULT));

	req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER,
			     LLOG_MIN_CHUNK_SIZE);
	rc = req_capsule_server_pack(&req->rq_pill);
	if (rc)
		RETURN(err_serious(-ENOMEM));

	if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
		CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d\n",
		       req->rq_export->exp_obd->obd_name, body->lgd_ctxt_idx);
		RETURN(-EPROTO);
	}

	ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
	if (ctxt == NULL)
		RETURN(-ENODEV);

	rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle,
		       &body->lgd_logid, NULL, LLOG_OPEN_EXISTS);
	if (rc)
		GOTO(out_ctxt, rc);

	flags = body->lgd_llh_flags;
	rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags,
			      NULL);
	if (rc)
		GOTO(out_close, rc);

	repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
	*repbody = *body;

	ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA);
	rc = llog_next_block(req->rq_svc_thread->t_env, loghandle,
			     &repbody->lgd_saved_index, repbody->lgd_index,
			     &repbody->lgd_cur_offset, ptr,
			     LLOG_MIN_CHUNK_SIZE);
	if (rc)
		GOTO(out_close, rc);
	EXIT;
out_close:
	llog_origin_close(req->rq_svc_thread->t_env, loghandle);
out_ctxt:
	llog_ctxt_put(ctxt);
	return rc;
}
Exemple #5
0
static int mds_llog_add_unlink(struct obd_device *obd,
                               struct lov_stripe_md *lsm, obd_count count,
                               struct llog_cookie *logcookie, int cookies)
{
        struct llog_unlink_rec *lur;
        struct llog_ctxt *ctxt;
        int rc;

        if (cookies < lsm->lsm_stripe_count)
                RETURN(rc = -EFBIG);

        /* first prepare unlink log record */
        OBD_ALLOC_PTR(lur);
        if (!lur)
                RETURN(rc = -ENOMEM);
        lur->lur_hdr.lrh_len = lur->lur_tail.lrt_len = sizeof(*lur);
        lur->lur_hdr.lrh_type = MDS_UNLINK_REC;
        lur->lur_count = count;

        ctxt = llog_get_context(obd, LLOG_MDS_OST_ORIG_CTXT);
        rc = llog_add(ctxt, &lur->lur_hdr, lsm, logcookie, cookies);
        llog_ctxt_put(ctxt);

        OBD_FREE_PTR(lur);
        RETURN(rc);
}
Exemple #6
0
int llog_origin_handle_destroy(struct ptlrpc_request *req)
{
	struct llogd_body	*body;
	struct llog_logid	*logid = NULL;
	struct llog_ctxt	*ctxt;
	int			 rc;

	ENTRY;

	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
	if (body == NULL)
		RETURN(err_serious(-EFAULT));

	rc = req_capsule_server_pack(&req->rq_pill);
	if (rc < 0)
		RETURN(err_serious(-ENOMEM));

	if (ostid_id(&body->lgd_logid.lgl_oi) > 0)
		logid = &body->lgd_logid;

	if (!(body->lgd_llh_flags & LLOG_F_IS_PLAIN))
		CERROR("%s: wrong llog flags %x\n",
		       req->rq_export->exp_obd->obd_name, body->lgd_llh_flags);

	ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
	if (ctxt == NULL)
		RETURN(-ENODEV);

	rc = llog_erase(req->rq_svc_thread->t_env, ctxt, logid, NULL);
	llog_ctxt_put(ctxt);
	RETURN(rc);
}
Exemple #7
0
static int llog_osd_setup(const struct lu_env *env, struct obd_device *obd,
			  struct obd_llog_group *olg, int ctxt_idx,
			  struct obd_device *disk_obd)
{
	struct local_oid_storage	*los;
	struct llog_thread_info		*lgi = llog_info(env);
	struct llog_ctxt		*ctxt;
	int				 rc = 0;

	ENTRY;

	LASSERT(obd);
	LASSERT(olg->olg_ctxts[ctxt_idx]);

	ctxt = llog_ctxt_get(olg->olg_ctxts[ctxt_idx]);
	LASSERT(ctxt);

	/* initialize data allowing to generate new fids,
	 * literally we need a sequece */
	lgi->lgi_fid.f_seq = FID_SEQ_LLOG;
	lgi->lgi_fid.f_oid = 1;
	lgi->lgi_fid.f_ver = 0;
	rc = local_oid_storage_init(env, disk_obd->obd_lvfs_ctxt.dt,
				    &lgi->lgi_fid, &los);
	llog_ctxt_put(ctxt);
	return rc;
}
Exemple #8
0
static int lov_llog_origin_connect(struct llog_ctxt *ctxt,
                                   struct llog_logid *logid,
                                   struct llog_gen *gen,
                                   struct obd_uuid *uuid)
{
        struct obd_device *obd = ctxt->loc_obd;
        struct lov_obd *lov = &obd->u.lov;
        int i, rc = 0, err = 0;
        ENTRY;

        obd_getref(obd);
        for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                struct obd_device *child;
                struct llog_ctxt *cctxt;

                if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                        continue;
                if (uuid && !obd_uuid_equals(uuid, &lov->lov_tgts[i]->ltd_uuid))
                        continue;
                CDEBUG(D_CONFIG, "connect %d/%d\n", i, lov->desc.ld_tgt_count);
                child = lov->lov_tgts[i]->ltd_exp->exp_obd;
                cctxt = llog_get_context(child, ctxt->loc_idx);
                rc = llog_connect(cctxt, logid, gen, uuid);
                llog_ctxt_put(cctxt);

                if (rc) {
                        CERROR("error osc_llog_connect tgt %d (%d)\n", i, rc);
                        if (!err)
                                err = rc;
                }
        }
        obd_putref(obd);

        RETURN(err);
}
Exemple #9
0
int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
{
	struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
	struct obd_llog_group *olg;
	int rc, idx;

	LASSERT(ctxt != NULL);
	LASSERT(ctxt != LP_POISON);

	olg = ctxt->loc_olg;
	LASSERT(olg != NULL);
	LASSERT(olg != LP_POISON);

	idx = ctxt->loc_idx;

	/*
	 * Banlance the ctxt get when calling llog_cleanup()
	 */
	LASSERT(atomic_read(&ctxt->loc_refcount) < LI_POISON);
	LASSERT(atomic_read(&ctxt->loc_refcount) > 1);
	llog_ctxt_put(ctxt);

	/*
	 * Try to free the ctxt.
	 */
	rc = __llog_ctxt_put(env, ctxt);
	if (rc)
		CERROR("Error %d while cleaning up ctxt %p\n",
		       rc, ctxt);

	l_wait_event(olg->olg_waitq,
		     llog_group_ctxt_null(olg, idx), &lwi);

	return rc;
}
Exemple #10
0
static int mdd_changelog_user_purge(const struct lu_env *env,
                                    struct mdd_device *mdd, int id,
                                    long long endrec)
{
        struct mdd_changelog_user_data data;
        struct llog_ctxt *ctxt;
        int rc;
        ENTRY;

        CDEBUG(D_IOCTL, "Purge request: id=%d, endrec=%lld\n", id, endrec);

        data.mcud_id = id;
        data.mcud_minid = 0;
        data.mcud_minrec = 0;
        data.mcud_usercount = 0;
        data.mcud_endrec = endrec;
	spin_lock(&mdd->mdd_cl.mc_lock);
	endrec = mdd->mdd_cl.mc_index;
	spin_unlock(&mdd->mdd_cl.mc_lock);
        if ((data.mcud_endrec == 0) ||
            ((data.mcud_endrec > endrec) &&
             (data.mcud_endrec != MCUD_UNREGISTER)))
                data.mcud_endrec = endrec;

        ctxt = llog_get_context(mdd2obd_dev(mdd),
				LLOG_CHANGELOG_USER_ORIG_CTXT);
        if (ctxt == NULL)
                return -ENXIO;

        LASSERT(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT);

	rc = llog_cat_process(env, ctxt->loc_handle,
			      mdd_changelog_user_purge_cb, (void *)&data,
			      0, 0);
        if ((rc >= 0) && (data.mcud_minrec > 0)) {
                CDEBUG(D_IOCTL, "Purging changelog entries up to "LPD64
                       ", referenced by "CHANGELOG_USER_PREFIX"%d\n",
                       data.mcud_minrec, data.mcud_minid);
		rc = mdd_changelog_llog_cancel(env, mdd, data.mcud_minrec);
        } else {
                CWARN("Could not determine changelog records to purge; rc=%d\n",
                      rc);
        }

        llog_ctxt_put(ctxt);

        if (!data.mcud_found) {
                CWARN("No entry for user %d.  Last changelog reference is "
                      LPD64" by changelog user %d\n", data.mcud_id,
                      data.mcud_minrec, data.mcud_minid);
               rc = -ENOENT;
        }

        if (!rc && data.mcud_usercount == 0)
                /* No more users; turn changelogs off */
                rc = mdd_changelog_on(env, mdd, 0);

        RETURN (rc);
}
Exemple #11
0
int llog_origin_handle_create(struct ptlrpc_request *req)
{
        struct obd_export    *exp = req->rq_export;
        struct obd_device    *obd = exp->exp_obd;
        struct obd_device    *disk_obd;
        struct llog_handle   *loghandle;
        struct llogd_body    *body;
        struct lvfs_run_ctxt  saved;
        struct llog_logid    *logid = NULL;
        struct llog_ctxt     *ctxt;
        char                 *name = NULL;
        int                   rc, rc2;
        ENTRY;

        body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
        if (body == NULL)
                RETURN(-EFAULT);

        if (body->lgd_logid.lgl_oid > 0)
                logid = &body->lgd_logid;

        if (req_capsule_field_present(&req->rq_pill, &RMF_NAME, RCL_CLIENT)) {
                name = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
                if (name == NULL)
                        RETURN(-EFAULT);
                CDEBUG(D_INFO, "%s: opening log %s\n", obd->obd_name, name);
        }

        ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
        if (ctxt == NULL) {
                CDEBUG(D_WARNING, "%s: no ctxt. group=%p idx=%d name=%s\n",
                       obd->obd_name, &obd->obd_olg, body->lgd_ctxt_idx, name);
                RETURN(-ENODEV);
        }
        disk_obd = ctxt->loc_exp->exp_obd;
        push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);

        rc = llog_create(ctxt, &loghandle, logid, name);
        if (rc)
                GOTO(out_pop, rc);

        rc = req_capsule_server_pack(&req->rq_pill);
        if (rc)
                GOTO(out_close, rc = -ENOMEM);

        body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
        body->lgd_logid = loghandle->lgh_id;

        GOTO(out_close, rc);
out_close:
        rc2 = llog_close(loghandle);
        if (!rc)
                rc = rc2;
out_pop:
        pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
        llog_ctxt_put(ctxt);
        return rc;
}
/* Only open is supported, no new llog can be created remotely */
int llog_origin_handle_open(struct ptlrpc_request *req)
{
	struct obd_export	*exp = req->rq_export;
	struct obd_device	*obd = exp->exp_obd;
	struct llog_handle	*loghandle;
	struct llogd_body	*body;
	struct llog_logid	*logid = NULL;
	struct llog_ctxt	*ctxt;
	char			*name = NULL;
	int			 rc;

	ENTRY;

	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
	if (body == NULL)
		RETURN(err_serious(-EFAULT));

	rc = req_capsule_server_pack(&req->rq_pill);
	if (rc)
		RETURN(err_serious(-ENOMEM));

	if (ostid_id(&body->lgd_logid.lgl_oi) > 0)
		logid = &body->lgd_logid;

	if (req_capsule_field_present(&req->rq_pill, &RMF_NAME, RCL_CLIENT)) {
		name = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
		if (name == NULL)
			RETURN(-EFAULT);
		CDEBUG(D_INFO, "%s: opening log %s\n", obd->obd_name, name);
	}

	if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
		CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d name=%s\n",
		       obd->obd_name, body->lgd_ctxt_idx, name);
		RETURN(-EPROTO);
	}

	ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
	if (ctxt == NULL) {
		CDEBUG(D_WARNING, "%s: no ctxt. group=%p idx=%d name=%s\n",
		       obd->obd_name, &obd->obd_olg, body->lgd_ctxt_idx, name);
		RETURN(-ENODEV);
	}

	rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle, logid,
		       name, LLOG_OPEN_EXISTS);
	if (rc)
		GOTO(out_ctxt, rc);

	body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
	body->lgd_logid = loghandle->lgh_id;

	llog_origin_close(req->rq_svc_thread->t_env, loghandle);
	EXIT;
out_ctxt:
	llog_ctxt_put(ctxt);
	return rc;
}
Exemple #13
0
static int lprocfs_rd_changelog_users(char *page, char **start, off_t off,
                                      int count, int *eof, void *data)
{
	struct lu_env		 env;
	struct mdd_device	*mdd = data;
	struct llog_ctxt	*ctxt;
	struct cucb_data	 cucb;
	__u64			 cur;
	int			 rc;

        *eof = 1;

        ctxt = llog_get_context(mdd2obd_dev(mdd),
				LLOG_CHANGELOG_USER_ORIG_CTXT);
        if (ctxt == NULL)
                return -ENXIO;
        LASSERT(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT);

	rc = lu_env_init(&env, LCT_LOCAL);
	if (rc) {
		llog_ctxt_put(ctxt);
		return rc;
	}

	spin_lock(&mdd->mdd_cl.mc_lock);
	cur = mdd->mdd_cl.mc_index;
	spin_unlock(&mdd->mdd_cl.mc_lock);

        cucb.count = count;
        cucb.page = page;
        cucb.idx = 0;

        cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx,
                              "current index: "LPU64"\n", cur);

        cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx,
                              "%-5s %s\n", "ID", "index");

	llog_cat_process(&env, ctxt->loc_handle, lprocfs_changelog_users_cb,
			 &cucb, 0, 0);

	lu_env_fini(&env);
	llog_ctxt_put(ctxt);
	return cucb.idx;
}
Exemple #14
0
static int llog_catinfo_config(struct obd_device *obd, char *buf, int buf_len,
                               char *client)
{
        struct mds_obd       *mds = &obd->u.mds;
        struct llog_ctxt     *ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
        struct lvfs_run_ctxt  saved;
        struct llog_handle   *handle = NULL;
        char                  name[4][64];
        int                   rc, i, l, remains = buf_len;
        char                 *out = buf;
        ENTRY;

        if (ctxt == NULL || mds == NULL)
                GOTO(release_ctxt, rc = -ENODEV);

        push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);

        sprintf(name[0], "%s", mds->mds_profile);
        sprintf(name[1], "%s-clean", mds->mds_profile);
        sprintf(name[2], "%s", client);
        sprintf(name[3], "%s-clean", client);

        for (i = 0; i < 4; i++) {
                int index, uncanceled = 0;
                rc = llog_create(ctxt, &handle, NULL, name[i]);
                if (rc)
                        GOTO(out_pop, rc);
                rc = llog_init_handle(handle, 0, NULL);
                if (rc) {
                        llog_close(handle);
                        GOTO(out_pop, rc = -ENOENT);
                }

                for (index = 1; index < (LLOG_BITMAP_BYTES * 8); index ++) {
                        if (ext2_test_bit(index, handle->lgh_hdr->llh_bitmap))
                                uncanceled++;
                }

                l = snprintf(out, remains, "[Log Name]: %s\nLog Size: %llu\n"
                             "Last Index: %d\nUncanceled Records: %d\n\n",
                             name[i],
                             i_size_read(handle->lgh_file->f_dentry->d_inode),
                             handle->lgh_last_idx, uncanceled);
                out += l;
                remains -= l;

                llog_close(handle);
                if (remains <= 0)
                        break;
        }
        GOTO(out_pop, rc);
out_pop:
        pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
release_ctxt:
        llog_ctxt_put(ctxt);
        return rc;
}
Exemple #15
0
static int mdd_changelog_user_register(const struct lu_env *env,
				       struct mdd_device *mdd, int *id)
{
        struct llog_ctxt *ctxt;
        struct llog_changelog_user_rec *rec;
        int rc;
        ENTRY;

        ctxt = llog_get_context(mdd2obd_dev(mdd),
				LLOG_CHANGELOG_USER_ORIG_CTXT);
        if (ctxt == NULL)
                RETURN(-ENXIO);

        OBD_ALLOC_PTR(rec);
        if (rec == NULL) {
                llog_ctxt_put(ctxt);
                RETURN(-ENOMEM);
        }

        /* Assume we want it on since somebody registered */
        rc = mdd_changelog_on(env, mdd, 1);
        if (rc)
                GOTO(out, rc);

        rec->cur_hdr.lrh_len = sizeof(*rec);
        rec->cur_hdr.lrh_type = CHANGELOG_USER_REC;
	spin_lock(&mdd->mdd_cl.mc_user_lock);
	if (mdd->mdd_cl.mc_lastuser == (unsigned int)(-1)) {
		spin_unlock(&mdd->mdd_cl.mc_user_lock);
		CERROR("Maximum number of changelog users exceeded!\n");
		GOTO(out, rc = -EOVERFLOW);
	}
	*id = rec->cur_id = ++mdd->mdd_cl.mc_lastuser;
	rec->cur_endrec = mdd->mdd_cl.mc_index;
	spin_unlock(&mdd->mdd_cl.mc_user_lock);

	rc = llog_cat_add(env, ctxt->loc_handle, &rec->cur_hdr, NULL);

        CDEBUG(D_IOCTL, "Registered changelog user %d\n", *id);
out:
        OBD_FREE_PTR(rec);
        llog_ctxt_put(ctxt);
        RETURN(rc);
}
Exemple #16
0
/* -------------------------------------------------------------------------
 * Tests above, boring obd functions below
 * ------------------------------------------------------------------------- */
static int llog_run_tests(const struct lu_env *env, struct obd_device *obd)
{
	struct llog_handle	*llh = NULL;
	struct llog_ctxt	*ctxt;
	int			 rc, err;
	char			 name[10];

	ENTRY;
	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
	LASSERT(ctxt);

	sprintf(name, "%x", llog_test_rand);

	rc = llog_test_1(env, obd, name);
	if (rc)
		GOTO(cleanup_ctxt, rc);

	rc = llog_test_2(env, obd, name, &llh);
	if (rc)
		GOTO(cleanup_ctxt, rc);

	rc = llog_test_3(env, obd, llh);
	if (rc)
		GOTO(cleanup, rc);

	rc = llog_test_4(env, obd);
	if (rc)
		GOTO(cleanup, rc);

	rc = llog_test_5(env, obd);
	if (rc)
		GOTO(cleanup, rc);

	rc = llog_test_6(env, obd, name);
	if (rc)
		GOTO(cleanup, rc);

	rc = llog_test_7(env, obd);
	if (rc)
		GOTO(cleanup, rc);

	rc = llog_test_8(env, obd);
	if (rc)
		GOTO(cleanup, rc);

cleanup:
	err = llog_destroy(env, llh);
	if (err)
		CERROR("cleanup: llog_destroy failed: %d\n", err);
	llog_close(env, llh);
	if (rc == 0)
		rc = err;
cleanup_ctxt:
	llog_ctxt_put(ctxt);
	return rc;
}
Exemple #17
0
/* -------------------------------------------------------------------------
 * Tests above, boring obd functions below
 * ------------------------------------------------------------------------- */
static int llog_run_tests(struct obd_device *obd)
{
        struct llog_handle *llh;
        struct lvfs_run_ctxt saved;
        struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
        int rc, err, cleanup_phase = 0;
        char name[10];
        ENTRY;

        sprintf(name, "%x", llog_test_rand);
        push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);

        rc = llog_test_1(obd, name);
        if (rc)
                GOTO(cleanup, rc);

        rc = llog_test_2(obd, name, &llh);
        if (rc)
                GOTO(cleanup, rc);
        cleanup_phase = 1; /* close llh */

        rc = llog_test_3(obd, llh);
        if (rc)
                GOTO(cleanup, rc);

        rc = llog_test_4(obd);
        if (rc)
                GOTO(cleanup, rc);

        rc = llog_test_5(obd);
        if (rc)
                GOTO(cleanup, rc);

        rc = llog_test_6(obd, name);
        if (rc)
                GOTO(cleanup, rc);

        rc = llog_test_7(obd);
        if (rc)
                GOTO(cleanup, rc);

 cleanup:
        switch (cleanup_phase) {
        case 1:
                err = llog_close(llh);
                if (err)
                        CERROR("cleanup: llog_close failed: %d\n", err);
                if (!rc)
                        rc = err;
        case 0:
                pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
        }
        llog_ctxt_put(ctxt);
        return rc;
}
int llog_origin_handle_read_header(struct ptlrpc_request *req)
{
	struct llog_handle	*loghandle;
	struct llogd_body	*body;
	struct llog_log_hdr	*hdr;
	struct llog_ctxt	*ctxt;
	__u32			 flags;
	int			 rc;

	ENTRY;

	body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
	if (body == NULL)
		RETURN(err_serious(-EFAULT));

	rc = req_capsule_server_pack(&req->rq_pill);
	if (rc)
		RETURN(err_serious(-ENOMEM));

	if (body->lgd_ctxt_idx >= LLOG_MAX_CTXTS) {
		CDEBUG(D_WARNING, "%s: bad ctxt ID: idx=%d\n",
		       req->rq_export->exp_obd->obd_name, body->lgd_ctxt_idx);
		RETURN(-EPROTO);
	}

	ctxt = llog_get_context(req->rq_export->exp_obd, body->lgd_ctxt_idx);
	if (ctxt == NULL)
		RETURN(-ENODEV);

	rc = llog_open(req->rq_svc_thread->t_env, ctxt, &loghandle,
		       &body->lgd_logid, NULL, LLOG_OPEN_EXISTS);
	if (rc)
		GOTO(out_ctxt, rc);

	/*
	 * llog_init_handle() reads the llog header
	 */
	flags = body->lgd_llh_flags;
	rc = llog_init_handle(req->rq_svc_thread->t_env, loghandle, flags,
			      NULL);
	if (rc)
		GOTO(out_close, rc);
	flags = loghandle->lgh_hdr->llh_flags;

	hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR);
	*hdr = *loghandle->lgh_hdr;
	EXIT;
out_close:
	llog_origin_close(req->rq_svc_thread->t_env, loghandle);
out_ctxt:
	llog_ctxt_put(ctxt);
	return rc;
}
Exemple #19
0
int llog_origin_handle_read_header(struct ptlrpc_request *req)
{
        struct obd_export    *exp = req->rq_export;
        struct obd_device    *obd = exp->exp_obd;
        struct obd_device    *disk_obd;
        struct llog_handle   *loghandle;
        struct llogd_body    *body;
        struct llog_log_hdr  *hdr;
        struct lvfs_run_ctxt  saved;
        struct llog_ctxt     *ctxt;
        __u32                 flags;
        int                   rc, rc2;
        ENTRY;

        body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
        if (body == NULL)
                RETURN(-EFAULT);

        ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
        if (ctxt == NULL)
                RETURN(-ENODEV);

        disk_obd = ctxt->loc_exp->exp_obd;
        push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);

        rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL);
        if (rc)
                GOTO(out_pop, rc);

        /*
         * llog_init_handle() reads the llog header
         */
        flags = body->lgd_llh_flags;
        rc = llog_init_handle(loghandle, flags, NULL);
        if (rc)
                GOTO(out_close, rc);

        rc = req_capsule_server_pack(&req->rq_pill);
        if (rc)
                GOTO(out_close, rc = -ENOMEM);

        hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR);
        *hdr = *loghandle->lgh_hdr;
        GOTO(out_close, rc);
out_close:
        rc2 = llog_close(loghandle);
        if (!rc)
                rc = rc2;
out_pop:
        pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
        llog_ctxt_put(ctxt);
        return rc;
}
Exemple #20
0
int llog_origin_handle_destroy(struct ptlrpc_request *req)
{
        struct obd_export    *exp = req->rq_export;
        struct obd_device    *obd = exp->exp_obd;
        struct obd_device    *disk_obd;
        struct llog_handle   *loghandle;
        struct llogd_body    *body;
        struct lvfs_run_ctxt  saved;
        struct llog_logid    *logid = NULL;
        struct llog_ctxt     *ctxt;
        int                   rc;
        ENTRY;

        body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY);
        if (body == NULL)
                RETURN(-EFAULT);

        if (body->lgd_logid.lgl_oid > 0)
                logid = &body->lgd_logid;

        ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
        if (ctxt == NULL)
                RETURN(-ENODEV);

        disk_obd = ctxt->loc_exp->exp_obd;
        push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);

        rc = llog_create(ctxt, &loghandle, logid, NULL);
        if (rc)
                GOTO(out_pop, rc);

        rc = req_capsule_server_pack(&req->rq_pill);
        if (rc)
                GOTO(out_close, rc = -ENOMEM);

        body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY);
        body->lgd_logid = loghandle->lgh_id;
        rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
        if (rc)
                GOTO(out_close, rc);
        rc = llog_destroy(loghandle);
        if (rc)
                GOTO(out_close, rc);
        llog_free_handle(loghandle);
        GOTO(out_close, rc);
out_close:
        if (rc)
                llog_close(loghandle);
out_pop:
        pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
        llog_ctxt_put(ctxt);
        return rc;
}
Exemple #21
0
/** Add a CL_MARK record to the changelog
 * \param mdd
 * \param markerflags - CLM_*
 * \retval 0 ok
 */
int mdd_changelog_write_header(const struct lu_env *env,
			       struct mdd_device *mdd, int markerflags)
{
	struct obd_device		*obd = mdd2obd_dev(mdd);
	struct llog_changelog_rec	*rec;
	struct lu_buf			*buf;
	struct llog_ctxt		*ctxt;
	int				 reclen;
	int				 len = strlen(obd->obd_name);
	int				 rc;

	ENTRY;

	if (mdd->mdd_cl.mc_mask & (1 << CL_MARK)) {
		mdd->mdd_cl.mc_starttime = cfs_time_current_64();
		RETURN(0);
	}

	reclen = llog_data_len(sizeof(*rec) + len);
	buf = lu_buf_check_and_alloc(&mdd_env_info(env)->mti_big_buf, reclen);
	if (buf->lb_buf == NULL)
		RETURN(-ENOMEM);
	rec = buf->lb_buf;

        rec->cr.cr_flags = CLF_VERSION;
        rec->cr.cr_type = CL_MARK;
        rec->cr.cr_namelen = len;
	memcpy(changelog_rec_name(&rec->cr), obd->obd_name, rec->cr.cr_namelen);
        /* Status and action flags */
	rec->cr.cr_markerflags = mdd->mdd_cl.mc_flags | markerflags;
	rec->cr_hdr.lrh_len = llog_data_len(changelog_rec_size(&rec->cr) +
					    rec->cr.cr_namelen);
	rec->cr_hdr.lrh_type = CHANGELOG_REC;
	rec->cr.cr_time = cl_time();
	spin_lock(&mdd->mdd_cl.mc_lock);
	rec->cr.cr_index = ++mdd->mdd_cl.mc_index;
	spin_unlock(&mdd->mdd_cl.mc_lock);

	ctxt = llog_get_context(obd, LLOG_CHANGELOG_ORIG_CTXT);
	LASSERT(ctxt);

	rc = llog_cat_add(env, ctxt->loc_handle, &rec->cr_hdr, NULL);
	if (rc > 0)
		rc = 0;
	llog_ctxt_put(ctxt);

	/* assume on or off event; reset repeat-access time */
	mdd->mdd_cl.mc_starttime = cfs_time_current_64();
	RETURN(rc);
}
Exemple #22
0
static int mds_llog_repl_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *lsm,
                          int count, struct llog_cookie *cookies, int flags)
{
        struct obd_device *obd = ctxt->loc_obd;
        struct obd_device *lov_obd = obd->u.mds.mds_lov_obd;
        struct llog_ctxt *lctxt;
        int rc;
        ENTRY;

        lctxt = llog_get_context(lov_obd, ctxt->loc_idx);
        rc = llog_cancel(lctxt, lsm, count, cookies, flags);
        llog_ctxt_put(lctxt);
        RETURN(rc);
}
Exemple #23
0
/* Test named-log reopen; returns opened log on success */
static int llog_test_2(struct obd_device *obd, char *name,
                       struct llog_handle **llh)
{
        struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
        int rc;
        ENTRY;

        CWARN("2a: re-open a log with name: %s\n", name);
        rc = llog_create(ctxt, llh, NULL, name);
        if (rc) {
                CERROR("2a: re-open log with name %s failed: %d\n", name, rc);
                GOTO(out, rc);
        }
        llog_init_handle(*llh, LLOG_F_IS_PLAIN, &uuid);

        if ((rc = verify_handle("2", *llh, 1)))
                GOTO(out, rc);
#if 0
        CWARN("2b: create a log without specified NAME & LOGID\n");
        rc = llog_create(ctxt, &loghandle, NULL, NULL);
        if (rc) {
                CERROR("2b: create log failed\n");
                GOTO(out, rc);
        }
        llog_init_handle(loghandle, LLOG_F_IS_PLAIN, &uuid);
        logid = loghandle->lgh_id;
        llog_close(loghandle);

        CWARN("2b: re-open the log by LOGID\n");
        rc = llog_create(ctxt, &loghandle, &logid, NULL);
        if (rc) {
                CERROR("2b: re-open log by LOGID failed\n");
                GOTO(out, rc);
        }
        llog_init_handle(loghandle, LLOG_F_IS_PLAIN, &uuid);

        CWARN("2b: destroy this log\n");
        rc = llog_destroy(loghandle);
        if (rc) {
                CERROR("2b: destroy log failed\n");
                GOTO(out, rc);
        }
        llog_free_handle(loghandle);
#endif
out:
        llog_ctxt_put(ctxt);

        RETURN(rc);
}
Exemple #24
0
static int mdd_changelog_size_ctxt(const struct lu_env *env,
                                   struct mdd_device *mdd,
                                   int index, __u64 *val)
{
    struct llog_ctxt	*ctxt;

    ctxt = llog_get_context(mdd2obd_dev(mdd),
                            index);
    if (ctxt == NULL)
        return -ENXIO;

    if (!(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) {
        CERROR("%s: ChangeLog has wrong flags: rc = %d\n",
               ctxt->loc_obd->obd_name, -EINVAL);
        llog_ctxt_put(ctxt);
        return -EINVAL;
    }

    *val += llog_cat_size(env, ctxt->loc_handle);

    llog_ctxt_put(ctxt);

    return 0;
}
Exemple #25
0
static int mds_llog_origin_connect(struct llog_ctxt *ctxt,
                                   struct llog_logid *logid,
                                   struct llog_gen *gen,
                                   struct obd_uuid *uuid)
{
        struct obd_device *obd = ctxt->loc_obd;
        struct obd_device *lov_obd = obd->u.mds.mds_lov_obd;
        struct llog_ctxt *lctxt;
        int rc;
        ENTRY;

        lctxt = llog_get_context(lov_obd, ctxt->loc_idx);
        rc = llog_connect(lctxt, logid, gen, uuid);
        llog_ctxt_put(lctxt);
        RETURN(rc);
}
Exemple #26
0
static int mds_llog_origin_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
                               struct lov_stripe_md *lsm,
                               struct llog_cookie *logcookies, int numcookies)
{
        struct obd_device *obd = ctxt->loc_obd;
        struct obd_device *lov_obd = obd->u.mds.mds_lov_obd;
        struct llog_ctxt *lctxt;
        int rc;
        ENTRY;

        lctxt = llog_get_context(lov_obd, ctxt->loc_idx);
        rc = llog_add(lctxt, rec, lsm, logcookies, numcookies);
        llog_ctxt_put(lctxt);

        RETURN(rc);
}
Exemple #27
0
/**
 * set llog methods and create LLOG_AGENT_ORIG_CTXT llog
 * object in obd_device
 */
static int mdd_hsm_actions_llog_init(const struct lu_env *env,
				     struct mdd_device *m)
{
	struct obd_device	*obd = mdd2obd_dev(m);
	struct llog_ctxt	*ctxt = NULL;
	int			 rc;
	ENTRY;

	OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
	obd->obd_lvfs_ctxt.dt = m->mdd_bottom;

	rc = llog_setup(env, obd, &obd->obd_olg, LLOG_AGENT_ORIG_CTXT,
			obd, &hsm_actions_logops);
	if (rc) {
		CERROR("%s: hsm actions llog setup failed: rc = %d\n",
			obd->obd_name, rc);
		RETURN(rc);
	}

	ctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
	LASSERT(ctxt);

	rc = llog_open_create(env, ctxt, &ctxt->loc_handle, NULL,
			      HSM_ACTIONS);
	if (rc) {
		CERROR("%s: hsm actions llog open_create failed: rc = %d\n",
			obd->obd_name, rc);
		GOTO(out_cleanup, rc);
	}

	rc = llog_cat_init_and_process(env, ctxt->loc_handle);
	if (rc)
		GOTO(out_close, rc);

	llog_ctxt_put(ctxt);
	RETURN(0);

out_close:
	llog_cat_close(env, ctxt->loc_handle);
	ctxt->loc_handle = NULL;
out_cleanup:
	llog_cleanup(env, ctxt);

	return rc;
}
Exemple #28
0
static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
			 struct obd_device *tgt, int *index)
{
	struct llog_ctxt *ctxt;
	int rc;

	LASSERT(olg == &obd->obd_olg);
	rc = llog_setup(NULL, obd, olg, LLOG_CONFIG_REPL_CTXT, tgt,
			&llog_client_ops);
	if (rc < 0)
		return rc;

	ctxt = llog_group_get_ctxt(olg, LLOG_CONFIG_REPL_CTXT);
	llog_initiator_connect(ctxt);
	llog_ctxt_put(ctxt);

	return rc;
}
Exemple #29
0
/** Remove entries with indicies up to and including \a endrec from the
 *  changelog
 * \param mdd
 * \param endrec
 * \retval 0 ok
 */
static int
mdd_changelog_llog_cancel(const struct lu_env *env, struct mdd_device *mdd,
			  long long endrec)
{
        struct obd_device *obd = mdd2obd_dev(mdd);
        struct llog_ctxt *ctxt;
        long long unsigned cur;
        int rc;

        ctxt = llog_get_context(obd, LLOG_CHANGELOG_ORIG_CTXT);
        if (ctxt == NULL)
                return -ENXIO;

	spin_lock(&mdd->mdd_cl.mc_lock);
	cur = (long long)mdd->mdd_cl.mc_index;
	spin_unlock(&mdd->mdd_cl.mc_lock);
        if (endrec > cur)
                endrec = cur;

        /* purge to "0" is shorthand for everything */
        if (endrec == 0)
                endrec = cur;

        /* If purging all records, write a header entry so we don't have an
           empty catalog and we're sure to have a valid starting index next
           time.  In case of crash, we just restart with old log so we're
           allright. */
        if (endrec == cur) {
                /* XXX: transaction is started by llog itself */
                rc = mdd_changelog_write_header(env, mdd, CLM_PURGE);
                if (rc)
                      goto out;
        }

        /* Some records were purged, so reset repeat-access time (so we
           record new mtime update records, so users can see a file has been
           changed since the last purge) */
        mdd->mdd_cl.mc_starttime = cfs_time_current_64();

	rc = llog_cancel(env, ctxt, (struct llog_cookie *)&endrec, 0);
out:
        llog_ctxt_put(ctxt);
        return rc;
}
Exemple #30
0
/* the replicators commit callback */
static int lov_llog_repl_cancel(const struct lu_env *env,
				struct llog_ctxt *ctxt,
				struct lov_stripe_md *lsm,
				int count, struct llog_cookie *cookies,
				int flags)
{
        struct lov_obd *lov;
        struct obd_device *obd = ctxt->loc_obd;
        int rc = 0, i;
        ENTRY;

        LASSERT(lsm != NULL);
        LASSERT(count == lsm->lsm_stripe_count);

        lov = &obd->u.lov;
        obd_getref(obd);
        for (i = 0; i < count; i++, cookies++) {
                struct lov_oinfo *loi = lsm->lsm_oinfo[i];
                struct obd_device *child =
                        lov->lov_tgts[loi->loi_ost_idx]->ltd_exp->exp_obd;
                struct llog_ctxt *cctxt =
                        llog_get_context(child, ctxt->loc_idx);
                int err;

		err = llog_cancel(env, cctxt, NULL, 1, cookies, flags);
		llog_ctxt_put(cctxt);
		if (err && lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
			CERROR("%s: objid "DOSTID" subobj "DOSTID
			       " on OST idx %d: rc = %d\n",
			       obd->obd_name, POSTID(&lsm->lsm_oi),
			       POSTID(&loi->loi_oi), loi->loi_ost_idx, err);
			if (!rc)
				rc = err;
		}
	}
	obd_putref(obd);
	RETURN(rc);
}