Exemple #1
0
static int __mdd_orphan_cleanup(void *args)
{
	struct mdd_generic_thread *thread = (struct mdd_generic_thread *)args;
	struct lu_env		  *env = NULL;
	int			   rc;
	ENTRY;

	complete(&thread->mgt_started);

	OBD_ALLOC_PTR(env);
	if (env == NULL)
		GOTO(out, rc = -ENOMEM);

	rc = lu_env_init(env, LCT_MD_THREAD);
	if (rc)
		GOTO(out, rc);

	rc = orph_index_iterate(env, thread);

	lu_env_fini(env);
	GOTO(out, rc);
out:
	if (env)
		OBD_FREE_PTR(env);
	complete(&thread->mgt_finished);
	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
static int lprocfs_wr_lfsck_speed_limit(struct file *file, const char *buffer,
					unsigned long count, void *data)
{
	struct mdd_device *mdd = data;
	struct md_lfsck *lfsck;
	__u32 val;
	int rc;

	LASSERT(mdd != NULL);
	rc = lprocfs_write_helper(buffer, count, &val);
	if (rc != 0)
		return rc;

	lfsck = &mdd->mdd_lfsck;
	if (val != lfsck->ml_bookmark_ram.lb_speed_limit) {
		struct lu_env env;

		rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
		if (rc != 0)
			return rc;

		rc = mdd_lfsck_set_speed(&env, lfsck, val);
		lu_env_fini(&env);
	}
	return rc != 0 ? rc : count;
}
Exemple #4
0
/**
 * Disconnect a connected client.
 *
 * This function terminates the client connection. The client export is
 * disconnected (cleaned up) and client data on persistent storage is removed.
 *
 * \param[in] exp	OBD export
 *
 * \retval		0 if successful
 * \retval		negative value on error
 */
int ofd_obd_disconnect(struct obd_export *exp)
{
	struct ofd_device	*ofd = ofd_exp(exp);
	struct lu_env		 env;
	int			 rc;

	ENTRY;

	LASSERT(exp);
	class_export_get(exp);

	if (!(exp->exp_flags & OBD_OPT_FORCE))
		ofd_grant_sanity_check(ofd_obd(ofd), __FUNCTION__);

	nodemap_del_member(exp);
	rc = server_disconnect_export(exp);

	ofd_grant_discard(exp);

	/* Do not erase record for recoverable client. */
	if (exp->exp_obd->obd_replayable &&
	    (!exp->exp_obd->obd_fail || exp->exp_failed)) {
		rc = lu_env_init(&env, LCT_DT_THREAD);
		if (rc)
			GOTO(out, rc);

		tgt_client_del(&env, exp);
		lu_env_fini(&env);
	}
out:
	class_export_put(exp);
	RETURN(rc);
}
Exemple #5
0
int osp_init_pre_fid(struct osp_device *osp)
{
	struct lu_env		env;
	struct osp_thread_info	*osi;
	struct lu_client_seq	*cli_seq;
	struct lu_fid		*last_fid;
	int			rc;
	ENTRY;

	LASSERT(osp->opd_pre != NULL);

	/* Return if last_used fid has been initialized */
	if (!fid_is_zero(&osp->opd_last_used_fid))
		RETURN(0);

	rc = lu_env_init(&env, osp->opd_dt_dev.dd_lu_dev.ld_type->ldt_ctx_tags);
	if (rc) {
		CERROR("%s: init env error: rc = %d\n",
		       osp->opd_obd->obd_name, rc);
		RETURN(rc);
	}

	osi = osp_env_info(&env);
	last_fid = &osi->osi_fid;
	fid_zero(last_fid);
	/* For a freshed fs, it will allocate a new sequence first */
	if (osp_is_fid_client(osp) && osp->opd_group != 0) {
		cli_seq = osp->opd_obd->u.cli.cl_seq;
		rc = seq_client_get_seq(&env, cli_seq, &last_fid->f_seq);
		if (rc != 0) {
			CERROR("%s: alloc fid error: rc = %d\n",
			       osp->opd_obd->obd_name, rc);
			GOTO(out, rc);
		}
	} else {
		last_fid->f_seq = fid_idif_seq(0, osp->opd_index);
	}
	last_fid->f_oid = 1;
	last_fid->f_ver = 0;

	spin_lock(&osp->opd_pre_lock);
	osp->opd_last_used_fid = *last_fid;
	osp->opd_pre_used_fid = *last_fid;
	osp->opd_pre_last_created_fid = *last_fid;
	spin_unlock(&osp->opd_pre_lock);
	rc = osp_write_last_oid_seq_files(&env, osp, last_fid, 1);
	if (rc != 0) {
		CERROR("%s: write fid error: rc = %d\n",
		       osp->opd_obd->obd_name, rc);
		GOTO(out, rc);
	}
out:
	lu_env_fini(&env);
	RETURN(rc);
}
Exemple #6
0
static ssize_t
ldiskfs_osd_index_in_idif_seq_write(struct file *file,
				    const char __user *buffer,
				    size_t count, loff_t *off)
{
	struct lu_env env;
	struct seq_file *m = file->private_data;
	struct dt_device *dt = m->private;
	struct osd_device *dev = osd_dt_dev(dt);
	struct lu_target *tgt;
	__s64 val;
	int rc;

	LASSERT(dev != NULL);
	if (unlikely(dev->od_mnt == NULL))
		return -EINPROGRESS;

	rc = lprocfs_str_to_s64(buffer, count, &val);
	if (rc != 0)
		return rc;

	if (dev->od_index_in_idif) {
		if (val != 0)
			return count;

		LCONSOLE_WARN("%s: OST-index in IDIF has been enabled, "
			      "it cannot be reverted back.\n", osd_name(dev));
		return -EPERM;
	}

	if (val == 0)
		return count;

	rc = lu_env_init(&env, LCT_DT_THREAD);
	if (rc != 0)
		return rc;

	tgt = dev->od_dt_dev.dd_lu_dev.ld_site->ls_tgt;
	tgt->lut_lsd.lsd_feature_rocompat |= OBD_ROCOMPAT_IDX_IN_IDIF;
	rc = tgt_server_data_update(&env, tgt, 1);
	lu_env_fini(&env);
	if (rc < 0)
		return rc;

	LCONSOLE_INFO("%s: enable OST-index in IDIF successfully, "
		      "it cannot be reverted back.\n", osd_name(dev));

	dev->od_index_in_idif = 1;
	return count;
}
Exemple #7
0
static int lprocfs_osd_wr_force_sync(struct file *file, const char *buffer,
					unsigned long count, void *data)
{
	struct dt_device  *dt = data;
	struct lu_env      env;
	int rc;

	rc = lu_env_init(&env, LCT_LOCAL);
	if (rc)
		return rc;
	rc = dt_sync(&env, dt);
	lu_env_fini(&env);

	return rc == 0 ? count : rc;
}
Exemple #8
0
static int llog_test_cleanup(struct obd_device *obd)
{
	struct obd_device	*tgt;
	struct lu_env		 env;
	int			 rc;

	rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
	if (rc)
		return rc;

	tgt = obd->obd_lvfs_ctxt.dt->dd_lu_dev.ld_obd;
	rc = llog_cleanup(&env, llog_get_context(tgt, LLOG_TEST_ORIG_CTXT));
	if (rc)
		CERROR("failed to llog_test_llog_finish: %d\n", rc);
	lu_env_fini(&env);
	return rc;
}
Exemple #9
0
static ssize_t
lprocfs_osd_force_sync_seq_write(struct file *file, const char __user *buffer,
				size_t count, loff_t *off)
{
	struct seq_file	  *m = file->private_data;
	struct dt_device  *dt = m->private;
	struct lu_env      env;
	int rc;

	rc = lu_env_init(&env, LCT_LOCAL);
	if (rc)
		return rc;
	rc = dt_sync(&env, dt);
	lu_env_fini(&env);

	return rc == 0 ? count : rc;
}
Exemple #10
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 #11
0
/**
 * Implementation of obd_ops::o_postrecov.
 *
 * This function is called from target_finish_recovery() upon recovery
 * completion.
 *
 * \param[in] obd	OBD device of OFD
 *
 * \retval		0 if successful
 * \retval		negative value on error
 */
static int ofd_obd_postrecov(struct obd_device *obd)
{
	struct lu_env		 env;
	struct lu_device	*ldev = obd->obd_lu_dev;
	int			 rc;

	ENTRY;

	rc = lu_env_init(&env, LCT_DT_THREAD);
	if (rc)
		RETURN(rc);
	ofd_info_init(&env, obd->obd_self_export);

	rc = ofd_postrecov(&env, ofd_dev(ldev));

	lu_env_fini(&env);
	RETURN(rc);
}
Exemple #12
0
static int lprocfs_rd_lfsck_namespace(char *page, char **start, off_t off,
				      int count, int *eof, void *data)
{
	struct lu_env env;
	struct mdd_device *mdd = data;
	int rc;

	LASSERT(mdd != NULL);
	*eof = 1;

	rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
	if (rc != 0)
		return rc;

	rc = mdd_lfsck_dump(&env, &mdd->mdd_lfsck, LT_NAMESPACE, page, count);
	lu_env_fini(&env);
	return rc;
}
Exemple #13
0
static int lprocfs_osd_wr_force_sync(struct file *file, const char *buffer,
				     unsigned long count, void *data)
{
	struct osd_device	*osd = osd_dt_dev(data);
	struct dt_device	*dt = data;
	struct lu_env		 env;
	int			 rc;

	LASSERT(osd != NULL);
	if (unlikely(osd->od_mnt == NULL))
		return -EINPROGRESS;

	rc = lu_env_init(&env, LCT_LOCAL);
	if (rc)
		return rc;
	rc = dt_sync(&env, dt);
	lu_env_fini(&env);

	return rc == 0 ? count : rc;
}
Exemple #14
0
static int llog_process_thread_daemonize(void *arg)
{
	struct llog_process_info	*lpi = arg;
	struct lu_env			 env;
	int				 rc;

	unshare_fs_struct();

	/* client env has no keys, tags is just 0 */
	rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
	if (rc)
		goto out;
	lpi->lpi_env = &env;

	rc = llog_process_thread(arg);

	lu_env_fini(&env);
out:
	complete(&lpi->lpi_completion);
	return rc;
}
Exemple #15
0
static ssize_t
lprocfs_osd_force_sync_seq_write(struct file *file, const char *buffer,
					size_t count, loff_t *off)
{
	struct seq_file	  *m = file->private_data;
	struct dt_device  *dt = m->private;
	struct osd_device *osd = osd_dt_dev(dt);
	struct lu_env	   env;
	int		   rc;

	LASSERT(osd != NULL);
	if (unlikely(osd->od_mnt == NULL))
		return -EINPROGRESS;

	rc = lu_env_init(&env, LCT_LOCAL);
	if (rc)
		return rc;
	rc = dt_sync(&env, dt);
	lu_env_fini(&env);

	return rc == 0 ? count : rc;
}
Exemple #16
0
static int mdd_changelog_size_seq_show(struct seq_file *m, void *data)
{
    struct lu_env		 env;
    struct mdd_device	*mdd = m->private;
    __u64			 tmp = 0;
    int			 rc;

    rc = lu_env_init(&env, LCT_LOCAL);
    if (rc)
        return rc;

    rc = mdd_changelog_size_ctxt(&env, mdd, LLOG_CHANGELOG_ORIG_CTXT, &tmp);
    if (rc) {
        lu_env_fini(&env);
        return rc;
    }

    rc = mdd_changelog_size_ctxt(&env, mdd, LLOG_CHANGELOG_USER_ORIG_CTXT,
                                 &tmp);

    seq_printf(m, "%llu\n", tmp);
    lu_env_fini(&env);
    return rc;
}
Exemple #17
0
/**
 * Implementation of ldlm_valblock_ops::lvbo_init for OFD.
 *
 * This function allocates and initializes new LVB data for the given
 * LDLM resource if it is not allocated yet. New LVB is filled with attributes
 * of the object associated with that resource. Function does nothing if LVB
 * for the given LDLM resource is allocated already.
 *
 * Called with res->lr_lvb_sem held.
 *
 * \param[in] res	LDLM resource
 *
 * \retval		0 on successful setup
 * \retval		negative value on error
 */
static int ofd_lvbo_init(struct ldlm_resource *res)
{
	struct ost_lvb		*lvb;
	struct ofd_device	*ofd;
	struct ofd_object	*fo;
	struct ofd_thread_info	*info;
	struct lu_env		 env;
	int			 rc = 0;

	ENTRY;

	LASSERT(res);
	LASSERT(mutex_is_locked(&res->lr_lvb_mutex));

	if (res->lr_lvb_data != NULL)
		RETURN(0);

	ofd = ldlm_res_to_ns(res)->ns_lvbp;
	LASSERT(ofd != NULL);

	if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_OST_LVB))
		RETURN(-ENOMEM);

	rc = lu_env_init(&env, LCT_DT_THREAD);
	if (rc)
		RETURN(rc);

	OBD_ALLOC_PTR(lvb);
	if (lvb == NULL)
		GOTO(out_env, rc = -ENOMEM);

	res->lr_lvb_data = lvb;
	res->lr_lvb_len = sizeof(*lvb);

	info = ofd_info_init(&env, NULL);
	ost_fid_from_resid(&info->fti_fid, &res->lr_name,
			   ofd->ofd_lut.lut_lsd.lsd_osd_index);
	fo = ofd_object_find(&env, ofd, &info->fti_fid);
	if (IS_ERR(fo))
		GOTO(out_lvb, rc = PTR_ERR(fo));

	rc = ofd_attr_get(&env, fo, &info->fti_attr);
	if (rc)
		GOTO(out_obj, rc);

	lvb->lvb_size = info->fti_attr.la_size;
	lvb->lvb_blocks = info->fti_attr.la_blocks;
	lvb->lvb_mtime = info->fti_attr.la_mtime;
	lvb->lvb_atime = info->fti_attr.la_atime;
	lvb->lvb_ctime = info->fti_attr.la_ctime;

	CDEBUG(D_DLMTRACE, "res: "DFID" initial lvb size: "LPU64", "
	       "mtime: "LPX64", blocks: "LPX64"\n",
	       PFID(&info->fti_fid), lvb->lvb_size,
	       lvb->lvb_mtime, lvb->lvb_blocks);

	EXIT;
out_obj:
	ofd_object_put(&env, fo);
out_lvb:
	if (rc != 0)
		OST_LVB_SET_ERR(lvb->lvb_blocks, rc);
out_env:
	lu_env_fini(&env);
	/* Don't free lvb data on lookup error */
	return rc;
}
Exemple #18
0
static int mdt_ck_thread_main(void *args)
{
	struct mdt_device      *mdt = args;
	struct ptlrpc_thread   *thread = &mdt->mdt_ck_thread;
	struct lustre_capa_key *bkey = &mdt->mdt_capa_keys[0],
			       *rkey = &mdt->mdt_capa_keys[1];
	struct lustre_capa_key *tmp;
	struct lu_env           env;
	struct mdt_thread_info *info;
	struct md_device       *next;
	struct l_wait_info      lwi = { 0 };
	mdsno_t                 mdsnum;
	int                     rc;
	ENTRY;

	unshare_fs_struct();
	cfs_block_allsigs();

	thread_set_flags(thread, SVC_RUNNING);
	wake_up(&thread->t_ctl_waitq);

	rc = lu_env_init(&env, LCT_MD_THREAD|LCT_REMEMBER|LCT_NOREF);
	if (rc)
		RETURN(rc);

	thread->t_env = &env;
	env.le_ctx.lc_thread = thread;
	env.le_ctx.lc_cookie = 0x1;

	info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
	LASSERT(info != NULL);

	tmp = &info->mti_capa_key;
	mdsnum = mdt_seq_site(mdt)->ss_node_id;
	while (1) {
		l_wait_event(thread->t_ctl_waitq,
			     thread_is_stopping(thread) ||
			     thread_is_event(thread),
			     &lwi);

		if (thread_is_stopping(thread))
			break;
		thread_clear_flags(thread, SVC_EVENT);

		if (cfs_time_before(cfs_time_current(), mdt->mdt_ck_expiry))
			break;

		*tmp = *rkey;
		make_capa_key(tmp, mdsnum, rkey->lk_keyid);

		next = mdt->mdt_child;
		rc = next->md_ops->mdo_update_capa_key(&env, next, tmp);
		if (!rc) {
			spin_lock(&capa_lock);
			*bkey = *rkey;
			*rkey = *tmp;
			spin_unlock(&capa_lock);

			rc = write_capa_keys(&env, mdt, mdt->mdt_capa_keys);
			if (rc) {
				spin_lock(&capa_lock);
				*rkey = *bkey;
				memset(bkey, 0, sizeof(*bkey));
				spin_unlock(&capa_lock);
			} else {
				set_capa_key_expiry(mdt);
				DEBUG_CAPA_KEY(D_SEC, rkey, "new");
			}
		}
		if (rc) {
			DEBUG_CAPA_KEY(D_ERROR, rkey, "update failed for");
			/* next retry is in 300 sec */
			mdt->mdt_ck_expiry = jiffies + 300 * HZ;
		}

		cfs_timer_arm(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
		CDEBUG(D_SEC, "mdt_ck_timer %lu\n", mdt->mdt_ck_expiry);
	}
	lu_env_fini(&env);

	thread_set_flags(thread, SVC_STOPPED);
	wake_up(&thread->t_ctl_waitq);
	RETURN(0);
}
Exemple #19
0
/**
 * Implementation of ldlm_valblock_ops::lvbo_update for OFD.
 *
 * When a client generates a glimpse enqueue, it wants to get the current
 * file size and updated attributes for a stat() type operation, but these
 * attributes may be writeback cached on another client. The client with
 * the DLM extent lock at the highest offset is asked for its current
 * attributes via a glimpse callback on its extent lock, on the assumption
 * that it has the highest file size and the newest timestamps. The timestamps
 * are guaranteed to be correct if there is only a single writer on the file,
 * but may be slightly inaccurate if there are multiple concurrent writers on
 * the same object. In order to avoid race conditions between the glimpse AST
 * and the client cancelling the lock, ofd_lvbo_update() also updates
 * the attributes from the local object. If the last client hasn't done any
 * writes yet, or has already written its data and cancelled its lock before
 * it processed the glimpse, then the local inode will have more uptodate
 * information.
 *
 * This is called in two ways:
 *  \a req != NULL : called by the DLM itself after a glimpse callback
 *  \a req == NULL : called by the OFD after a disk write
 *
 * \param[in] res		LDLM resource
 * \param[in] req		PTLRPC request
 * \param[in] increase_only	don't allow LVB values to decrease
 *
 * \retval		0 on successful setup
 * \retval		negative value on error
 */
static int ofd_lvbo_update(struct ldlm_resource *res,
			   struct ptlrpc_request *req, int increase_only)
{
	struct ofd_device	*ofd;
	struct ofd_object	*fo;
	struct ofd_thread_info	*info;
	struct ost_lvb		*lvb;
	struct lu_env		 env;
	int			 rc = 0;

	ENTRY;

	LASSERT(res != NULL);

	ofd = ldlm_res_to_ns(res)->ns_lvbp;
	LASSERT(ofd != NULL);

	rc = lu_env_init(&env, LCT_DT_THREAD);
	if (rc)
		RETURN(rc);

	info = ofd_info_init(&env, NULL);
	fid_extract_from_res_name(&info->fti_fid, &res->lr_name);

	lvb = res->lr_lvb_data;
	if (lvb == NULL) {
		CERROR("%s: no LVB data for "DFID"\n",
		       ofd_name(ofd), PFID(&info->fti_fid));
		GOTO(out_env, rc = 0);
	}

	/* Update the LVB from the network message */
	if (req != NULL) {
		struct ost_lvb *rpc_lvb;
		bool lvb_type;

		if (req->rq_import != NULL)
			lvb_type = imp_connect_lvb_type(req->rq_import);
		else
			lvb_type = exp_connect_lvb_type(req->rq_export);

		if (!lvb_type) {
			struct ost_lvb_v1 *lvb_v1;

			lvb_v1 = req_capsule_server_swab_get(&req->rq_pill,
					&RMF_DLM_LVB, lustre_swab_ost_lvb_v1);
			if (lvb_v1 == NULL)
				goto disk_update;

			rpc_lvb = &info->fti_lvb;
			memcpy(rpc_lvb, lvb_v1, sizeof *lvb_v1);
			rpc_lvb->lvb_mtime_ns = 0;
			rpc_lvb->lvb_atime_ns = 0;
			rpc_lvb->lvb_ctime_ns = 0;
		} else {
			rpc_lvb = req_capsule_server_swab_get(&req->rq_pill,
							      &RMF_DLM_LVB,
							lustre_swab_ost_lvb);
			if (rpc_lvb == NULL)
				goto disk_update;
		}

		lock_res(res);
		if (rpc_lvb->lvb_size > lvb->lvb_size || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb size: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_size, rpc_lvb->lvb_size);
			lvb->lvb_size = rpc_lvb->lvb_size;
		}
		if (rpc_lvb->lvb_mtime > lvb->lvb_mtime || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb mtime: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_mtime, rpc_lvb->lvb_mtime);
			lvb->lvb_mtime = rpc_lvb->lvb_mtime;
		}
		if (rpc_lvb->lvb_atime > lvb->lvb_atime || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb atime: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_atime, rpc_lvb->lvb_atime);
			lvb->lvb_atime = rpc_lvb->lvb_atime;
		}
		if (rpc_lvb->lvb_ctime > lvb->lvb_ctime || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb ctime: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_ctime, rpc_lvb->lvb_ctime);
			lvb->lvb_ctime = rpc_lvb->lvb_ctime;
		}
		if (rpc_lvb->lvb_blocks > lvb->lvb_blocks || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb blocks: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_blocks, rpc_lvb->lvb_blocks);
			lvb->lvb_blocks = rpc_lvb->lvb_blocks;
		}
		unlock_res(res);
	}

disk_update:
	/* Update the LVB from the disk inode */
	ost_fid_from_resid(&info->fti_fid, &res->lr_name,
			   ofd->ofd_lut.lut_lsd.lsd_osd_index);
	fo = ofd_object_find(&env, ofd, &info->fti_fid);
	if (IS_ERR(fo))
		GOTO(out_env, rc = PTR_ERR(fo));

	rc = ofd_attr_get(&env, fo, &info->fti_attr);
	if (rc)
		GOTO(out_obj, rc);

	lock_res(res);
	if (info->fti_attr.la_size > lvb->lvb_size || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb size from disk: "
		       LPU64" -> %llu\n", PFID(&info->fti_fid),
		       lvb->lvb_size, info->fti_attr.la_size);
		lvb->lvb_size = info->fti_attr.la_size;
	}

	if (info->fti_attr.la_mtime >lvb->lvb_mtime || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb mtime from disk: "
		       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
		       lvb->lvb_mtime, info->fti_attr.la_mtime);
		lvb->lvb_mtime = info->fti_attr.la_mtime;
	}
	if (info->fti_attr.la_atime >lvb->lvb_atime || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb atime from disk: "
		       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
		       lvb->lvb_atime, info->fti_attr.la_atime);
		lvb->lvb_atime = info->fti_attr.la_atime;
	}
	if (info->fti_attr.la_ctime >lvb->lvb_ctime || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb ctime from disk: "
		       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
		       lvb->lvb_ctime, info->fti_attr.la_ctime);
		lvb->lvb_ctime = info->fti_attr.la_ctime;
	}
	if (info->fti_attr.la_blocks > lvb->lvb_blocks || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb blocks from disk: "
		       LPU64" -> %llu\n", PFID(&info->fti_fid), lvb->lvb_blocks,
		       (unsigned long long)info->fti_attr.la_blocks);
		lvb->lvb_blocks = info->fti_attr.la_blocks;
	}
	unlock_res(res);

out_obj:
	ofd_object_put(&env, fo);
out_env:
	lu_env_fini(&env);
	return rc;
}
Exemple #20
0
/**
 * Blocking callback handler for per-ID lock
 *
 * \param lock - is the lock for which ast occurred.
 * \param desc - is the description of a conflicting lock in case of blocking
 *               ast.
 * \param data - is the value of lock->l_ast_data
 * \param flag - LDLM_CB_BLOCKING or LDLM_CB_CANCELING. Used to distinguish
 *               cancellation and blocking ast's.
 */
static int qsd_id_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
			       void *data, int flag)
{
	struct lustre_handle	lockh;
	int			rc = 0;
	ENTRY;

	switch(flag) {
	case LDLM_CB_BLOCKING: {

		LDLM_DEBUG(lock, "blocking AST on ID quota lock");
		ldlm_lock2handle(lock, &lockh);
		rc = ldlm_cli_cancel(&lockh, LCF_ASYNC);
		break;
	}
	case LDLM_CB_CANCELING: {
		struct lu_env           *env;
		struct lquota_entry	*lqe;
		bool			 rel = false;

		LDLM_DEBUG(lock, "canceling global quota lock");
		lqe = qsd_id_ast_data_get(lock, true);
		if (lqe == NULL)
			break;

		LQUOTA_DEBUG(lqe, "losing ID lock");

		/* just local cancel (for stack clean up or eviction), don't
		 * release quota space in this case */
		if (ldlm_is_local_only(lock)) {
			lqe_putref(lqe);
			break;
		}

		/* allocate environment */
		OBD_ALLOC_PTR(env);
		if (env == NULL) {
			lqe_putref(lqe);
			rc = -ENOMEM;
			break;
		}

		/* initialize environment */
		rc = lu_env_init(env, LCT_DT_THREAD);
		if (rc) {
			OBD_FREE_PTR(env);
			lqe_putref(lqe);
			break;
		}

		ldlm_lock2handle(lock, &lockh);
		lqe_write_lock(lqe);
		if (lustre_handle_equal(&lockh, &lqe->lqe_lockh)) {
			/* Clear lqe_lockh & reset qunit to 0 */
			qsd_set_qunit(lqe, 0);
			memset(&lqe->lqe_lockh, 0, sizeof(lqe->lqe_lockh));
			lqe->lqe_edquot = false;
			rel = true;
		}
		lqe_write_unlock(lqe);

		/* If there is qqacq inflight, the release will be skipped
		 * at this time, and triggered on dqacq completion later,
		 * which means there could be a short window that slave is
		 * holding spare grant wihtout per-ID lock. */
		if (rel)
			rc = qsd_adjust(env, lqe);

		/* release lqe reference grabbed by qsd_id_ast_data_get() */
		lqe_putref(lqe);
		lu_env_fini(env);
		OBD_FREE_PTR(env);
		break;
	}
	default:
		LASSERTF(0, "invalid flags for blocking ast %d", flag);
	}

	RETURN(rc);
}
Exemple #21
0
static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
{
	struct obd_device	*tgt;
	struct llog_ctxt	*ctxt;
	struct dt_object	*o;
	struct lu_env		 env;
	struct lu_context	 test_session;
	int			 rc;

	if (lcfg->lcfg_bufcount < 2) {
		CERROR("requires a TARGET OBD name\n");
		return -EINVAL;
	}

	if (lcfg->lcfg_buflens[1] < 1) {
		CERROR("requires a TARGET OBD name\n");
		return -EINVAL;
	}

	/* disk obd */
	tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
	if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
		CERROR("target device not attached or not set up (%s)\n",
		       lustre_cfg_string(lcfg, 1));
		return -EINVAL;
	}

	rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
	if (rc)
		return rc;

	rc = lu_context_init(&test_session, LCT_SESSION);
	if (rc)
		GOTO(cleanup_env, rc);
	test_session.lc_thread = (struct ptlrpc_thread *)current;
	lu_context_enter(&test_session);
	env.le_ses = &test_session;

	CWARN("Setup llog-test device over %s device\n",
	      lustre_cfg_string(lcfg, 1));

	OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
	obd->obd_lvfs_ctxt.dt = lu2dt_dev(tgt->obd_lu_dev);

	rc = llog_setup(&env, tgt, &tgt->obd_olg, LLOG_TEST_ORIG_CTXT, tgt,
			&llog_osd_ops);
	if (rc)
		GOTO(cleanup_session, rc);

	/* use MGS llog dir for tests */
	ctxt = llog_get_context(tgt, LLOG_CONFIG_ORIG_CTXT);
	LASSERT(ctxt);
	o = ctxt->loc_dir;
	llog_ctxt_put(ctxt);

	ctxt = llog_get_context(tgt, LLOG_TEST_ORIG_CTXT);
	LASSERT(ctxt);
	ctxt->loc_dir = o;
	llog_ctxt_put(ctxt);

	llog_test_rand = cfs_rand();

	rc = llog_run_tests(&env, tgt);
	if (rc)
		llog_test_cleanup(obd);
cleanup_session:
	lu_context_exit(&test_session);
	lu_context_fini(&test_session);
cleanup_env:
	lu_env_fini(&env);
	return rc;
}
Exemple #22
0
static int osp_precreate_thread(void *_arg)
{
	struct osp_device	*d = _arg;
	struct ptlrpc_thread	*thread = &d->opd_pre_thread;
	struct l_wait_info	 lwi = { 0 };
	struct lu_env		 env;
	int			 rc;

	ENTRY;

	rc = lu_env_init(&env, d->opd_dt_dev.dd_lu_dev.ld_type->ldt_ctx_tags);
	if (rc) {
		CERROR("%s: init env error: rc = %d\n", d->opd_obd->obd_name,
		       rc);
		RETURN(rc);
	}

	spin_lock(&d->opd_pre_lock);
	thread->t_flags = SVC_RUNNING;
	spin_unlock(&d->opd_pre_lock);
	wake_up(&thread->t_ctl_waitq);

	while (osp_precreate_running(d)) {
		/*
		 * need to be connected to OST
		 */
		while (osp_precreate_running(d)) {
			l_wait_event(d->opd_pre_waitq,
				     !osp_precreate_running(d) ||
				     d->opd_new_connection,
				     &lwi);

			if (!d->opd_new_connection)
				continue;

			d->opd_new_connection = 0;
			d->opd_got_disconnected = 0;
			break;
		}

		if (!osp_precreate_running(d))
			break;

		LASSERT(d->opd_obd->u.cli.cl_seq != NULL);
		if (d->opd_obd->u.cli.cl_seq->lcs_exp == NULL) {
			/* Get new sequence for client first */
			LASSERT(d->opd_exp != NULL);
			d->opd_obd->u.cli.cl_seq->lcs_exp =
			class_export_get(d->opd_exp);
			rc = osp_init_pre_fid(d);
			if (rc != 0) {
				class_export_put(d->opd_exp);
				d->opd_obd->u.cli.cl_seq->lcs_exp = NULL;
				CERROR("%s: init pre fid error: rc = %d\n",
				       d->opd_obd->obd_name, rc);
				continue;
			}
		}

		osp_statfs_update(d);

		/*
		 * Clean up orphans or recreate missing objects.
		 */
		rc = osp_precreate_cleanup_orphans(&env, d);
		if (rc != 0)
			continue;
		/*
		 * connected, can handle precreates now
		 */
		while (osp_precreate_running(d)) {
			l_wait_event(d->opd_pre_waitq,
				     !osp_precreate_running(d) ||
				     osp_precreate_near_empty(&env, d) ||
				     osp_statfs_need_update(d) ||
				     d->opd_got_disconnected, &lwi);

			if (!osp_precreate_running(d))
				break;

			/* something happened to the connection
			 * have to start from the beginning */
			if (d->opd_got_disconnected)
				break;

			if (osp_statfs_need_update(d))
				osp_statfs_update(d);

			/* To avoid handling different seq in precreate/orphan
			 * cleanup, it will hold precreate until current seq is
			 * used up. */
			if (unlikely(osp_precreate_end_seq(&env, d) &&
			    !osp_create_end_seq(&env, d)))
				continue;

			if (unlikely(osp_precreate_end_seq(&env, d) &&
				     osp_create_end_seq(&env, d))) {
				LCONSOLE_INFO("%s:"LPX64" is used up."
					      " Update to new seq\n",
					      d->opd_obd->obd_name,
					 fid_seq(&d->opd_pre_last_created_fid));
				rc = osp_precreate_rollover_new_seq(&env, d);
				if (rc)
					continue;
			}

			if (osp_precreate_near_empty(&env, d)) {
				rc = osp_precreate_send(&env, d);
				/* osp_precreate_send() sets opd_pre_status
				 * in case of error, that prevent the using of
				 * failed device. */
				if (rc < 0 && rc != -ENOSPC &&
				    rc != -ETIMEDOUT && rc != -ENOTCONN)
					CERROR("%s: cannot precreate objects:"
					       " rc = %d\n",
					       d->opd_obd->obd_name, rc);
			}
		}
	}

	thread->t_flags = SVC_STOPPED;
	lu_env_fini(&env);
	wake_up(&thread->t_ctl_waitq);

	RETURN(0);
}
Exemple #23
0
/**
 * Implementation of ldlm_valblock_ops::lvbo_init for OFD.
 *
 * This function allocates and initializes new LVB data for the given
 * LDLM resource if it is not allocated yet. New LVB is filled with attributes
 * of the object associated with that resource. Function does nothing if LVB
 * for the given LDLM resource is allocated already.
 *
 * Called with res->lr_lvb_sem held.
 *
 * \param[in] lock	LDLM lock on resource
 *
 * \retval		0 on successful setup
 * \retval		negative value on error
 */
static int ofd_lvbo_init(const struct lu_env *env, struct ldlm_resource *res)
{
	struct ost_lvb		*lvb;
	struct ofd_device	*ofd;
	struct ofd_object	*fo;
	struct ofd_thread_info	*info;
	struct lu_env _env;
	int rc = 0;
	ENTRY;

	LASSERT(res);
	LASSERT(mutex_is_locked(&res->lr_lvb_mutex));

	if (res->lr_lvb_data != NULL)
		RETURN(0);

	ofd = ldlm_res_to_ns(res)->ns_lvbp;
	LASSERT(ofd != NULL);

	if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_OST_LVB))
		RETURN(-ENOMEM);

	if (!env) {
		rc = lu_env_init(&_env, LCT_DT_THREAD);
		if (rc)
			RETURN(rc);
		env = &_env;
	}

	OBD_ALLOC_PTR(lvb);
	if (lvb == NULL)
		GOTO(out, rc = -ENOMEM);

	info = ofd_info(env);
	res->lr_lvb_data = lvb;
	res->lr_lvb_len = sizeof(*lvb);

	ost_fid_from_resid(&info->fti_fid, &res->lr_name,
			   ofd->ofd_lut.lut_lsd.lsd_osd_index);
	fo = ofd_object_find(env, ofd, &info->fti_fid);
	if (IS_ERR(fo))
		GOTO(out_lvb, rc = PTR_ERR(fo));

	rc = ofd_attr_get(env, fo, &info->fti_attr);
	if (rc) {
		struct ofd_seq		*oseq;
		__u64			 seq;

		/* Object could be recreated during the first
		 * CLEANUP_ORPHAN request. */
		if (rc == -ENOENT) {
			seq = fid_seq(&info->fti_fid);
			oseq = ofd_seq_load(env, ofd, fid_seq_is_idif(seq) ?
					    FID_SEQ_OST_MDT0 : seq);
			if (!IS_ERR_OR_NULL(oseq)) {
				if (!oseq->os_last_id_synced)
					rc = -EAGAIN;
				ofd_seq_put(env, oseq);
			}
		}
		GOTO(out_obj, rc);
	}

	lvb->lvb_size = info->fti_attr.la_size;
	lvb->lvb_blocks = info->fti_attr.la_blocks;
	lvb->lvb_mtime = info->fti_attr.la_mtime;
	lvb->lvb_atime = info->fti_attr.la_atime;
	lvb->lvb_ctime = info->fti_attr.la_ctime;

	CDEBUG(D_DLMTRACE, "res: "DFID" initial lvb size: %llu, "
	       "mtime: %#llx, blocks: %#llx\n",
	       PFID(&info->fti_fid), lvb->lvb_size,
	       lvb->lvb_mtime, lvb->lvb_blocks);

	info->fti_attr.la_valid = 0;

	EXIT;
out_obj:
	ofd_object_put(env, fo);
out_lvb:
	if (rc != 0)
		OST_LVB_SET_ERR(lvb->lvb_blocks, rc);
out:
	/* Don't free lvb data on lookup error */
	if (env && env == &_env)
		lu_env_fini(&_env);
	return rc;
}
Exemple #24
0
		.ckd_name  = "osd_zapit_cache",
		.ckd_size  = sizeof(struct osd_zap_it)
	},
	{
		.ckd_cache = NULL
	}
};

static void arc_prune_func(int64_t bytes, void *private)
{
	struct osd_device *od = private;
	struct lu_site    *site = &od->od_site;
	struct lu_env      env;
	int rc;

	rc = lu_env_init(&env, LCT_SHRINKER);
	if (rc) {
		CERROR("%s: can't initialize shrinker env: rc = %d\n",
		       od->od_svname, rc);
		return;
	}

	lu_site_purge(&env, site, (bytes >> 10));

	lu_env_fini(&env);
}

/*
 * Concurrency: doesn't access mutable data
 */
static int osd_root_get(const struct lu_env *env,
Exemple #25
0
/**
 * Verification thread to check parent FID consistency.
 *
 * Kernel thread to check consistency of parent FID for any
 * new item added for checking by ofd_add_inconsistency_item().
 *
 * \param[in] args	OFD device
 *
 * \retval		0 on successful thread termination
 * \retval		negative value if thread can't start
 */
static int ofd_inconsistency_verification_main(void *args)
{
	struct lu_env		       env;
	struct ofd_device	      *ofd    = args;
	struct ptlrpc_thread	      *thread = &ofd->ofd_inconsistency_thread;
	struct ofd_inconsistency_item *oii;
	struct lfsck_request	      *lr     = NULL;
	struct l_wait_info	       lwi    = { 0 };
	int			       rc;
	ENTRY;

	rc = lu_env_init(&env, LCT_DT_THREAD);
	spin_lock(&ofd->ofd_inconsistency_lock);
	thread_set_flags(thread, rc != 0 ? SVC_STOPPED : SVC_RUNNING);
	wake_up_all(&thread->t_ctl_waitq);
	spin_unlock(&ofd->ofd_inconsistency_lock);
	if (rc != 0)
		RETURN(rc);

	OBD_ALLOC_PTR(lr);
	if (unlikely(lr == NULL))
		GOTO(out_unlocked, rc = -ENOMEM);

	lr->lr_event = LE_PAIRS_VERIFY;
	lr->lr_active = LFSCK_TYPE_LAYOUT;

	spin_lock(&ofd->ofd_inconsistency_lock);
	while (1) {
		if (unlikely(!thread_is_running(thread)))
			break;

		while (!list_empty(&ofd->ofd_inconsistency_list)) {
			oii = list_entry(ofd->ofd_inconsistency_list.next,
					 struct ofd_inconsistency_item,
					 oii_list);
			list_del_init(&oii->oii_list);
			spin_unlock(&ofd->ofd_inconsistency_lock);
			ofd_inconsistency_verify_one(&env, ofd, oii, lr);
			spin_lock(&ofd->ofd_inconsistency_lock);
		}

		spin_unlock(&ofd->ofd_inconsistency_lock);
		l_wait_event(thread->t_ctl_waitq,
			     !list_empty(&ofd->ofd_inconsistency_list) ||
			     !thread_is_running(thread),
			     &lwi);
		spin_lock(&ofd->ofd_inconsistency_lock);
	}

	while (!list_empty(&ofd->ofd_inconsistency_list)) {
		struct ofd_object *fo;

		oii = list_entry(ofd->ofd_inconsistency_list.next,
				 struct ofd_inconsistency_item,
				 oii_list);
		list_del_init(&oii->oii_list);
		fo = oii->oii_obj;
		spin_unlock(&ofd->ofd_inconsistency_lock);

		ofd_write_lock(&env, fo);
		fo->ofo_pfid_checking = 0;
		ofd_write_unlock(&env, fo);

		lu_object_put(&env, &fo->ofo_obj.do_lu);
		OBD_FREE_PTR(oii);
		spin_lock(&ofd->ofd_inconsistency_lock);
	}

	OBD_FREE_PTR(lr);

	GOTO(out, rc = 0);

out_unlocked:
	spin_lock(&ofd->ofd_inconsistency_lock);
out:
	thread_set_flags(thread, SVC_STOPPED);
	wake_up_all(&thread->t_ctl_waitq);
	spin_unlock(&ofd->ofd_inconsistency_lock);
	lu_env_fini(&env);

	return rc;
}
Exemple #26
0
static int mdt_lvbo_fill(struct ldlm_lock *lock, void *lvb, int lvblen)
{
	struct lu_env env;
	struct mdt_thread_info *info;
	struct mdt_device *mdt;
	struct lu_fid *fid;
	struct mdt_object *obj = NULL;
	struct md_object *child = NULL;
	int rc;
	ENTRY;

	mdt = ldlm_lock_to_ns(lock)->ns_lvbp;
	if (IS_LQUOTA_RES(lock->l_resource)) {
		if (mdt->mdt_qmt_dev == NULL)
			RETURN(0);

		/* call lvbo fill function of quota master */
		rc = qmt_hdls.qmth_lvbo_fill(mdt->mdt_qmt_dev, lock, lvb,
					     lvblen);
		RETURN(rc);
	}

	if (!ldlm_has_layout(lock))
		RETURN(0);

	/* layout lock will be granted to client, fill in lvb with layout */

	/* XXX create an env to talk to mdt stack. We should get this env from
	 * ptlrpc_thread->t_env. */
	rc = lu_env_init(&env, LCT_MD_THREAD);
	/* Likely ENOMEM */
	if (rc)
		RETURN(rc);

	info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
	/* Likely ENOMEM */
	if (info == NULL)
		GOTO(out, rc = -ENOMEM);

	memset(info, 0, sizeof *info);
	info->mti_env = &env;
	info->mti_exp = lock->l_export;
	info->mti_mdt = mdt;

	/* XXX get fid by resource id. why don't include fid in ldlm_resource */
	fid = &info->mti_tmp_fid2;
	fid_extract_from_res_name(fid, &lock->l_resource->lr_name);

	obj = mdt_object_find(&env, info->mti_mdt, fid);
	if (IS_ERR(obj))
		GOTO(out, rc = PTR_ERR(obj));

	if (!mdt_object_exists(obj) || mdt_object_remote(obj))
		GOTO(out, rc = -ENOENT);

	child = mdt_object_child(obj);

	/* get the length of lsm */
	rc = mo_xattr_get(&env, child, &LU_BUF_NULL, XATTR_NAME_LOV);
	if (rc < 0)
		GOTO(out, rc);

	if (rc > 0) {
		struct lu_buf *lmm = NULL;

		if (lvblen < rc) {
			CERROR("%s: expected %d actual %d.\n",
				mdt_obd_name(mdt), rc, lvblen);
			GOTO(out, rc = -ERANGE);
		}

		lmm = &info->mti_buf;
		lmm->lb_buf = lvb;
		lmm->lb_len = rc;

		rc = mo_xattr_get(&env, child, lmm, XATTR_NAME_LOV);
		if (rc < 0)
			GOTO(out, rc);
	}

out:
	if (obj != NULL && !IS_ERR(obj))
		mdt_object_put(&env, obj);
	lu_env_fini(&env);
	RETURN(rc < 0 ? 0 : rc);
}