예제 #1
0
int lmv_fld_lookup(struct lmv_obd *lmv,
		   const struct lu_fid *fid,
		   mdsno_t *mds)
{
	int rc;

	/* FIXME: Currently ZFS still use local seq for ROOT unfortunately, and
	 * this fid_is_local check should be removed once LU-2240 is fixed */
	LASSERTF((fid_seq_in_fldb(fid_seq(fid)) ||
		  fid_seq_is_local_file(fid_seq(fid))) &&
		 fid_is_sane(fid), DFID" is insane!\n", PFID(fid));

	rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds,
			       LU_SEQ_RANGE_MDT, NULL);
	if (rc) {
		CERROR("Error while looking for mds number. Seq %#llx, err = %d\n",
		       fid_seq(fid), rc);
		return rc;
	}

	CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
	       *mds, PFID(fid));

	if (*mds >= lmv->desc.ld_tgt_count) {
		CERROR("FLD lookup got invalid mds #%x (max: %x) "
		       "for fid="DFID"\n", *mds, lmv->desc.ld_tgt_count,
		       PFID(fid));
		rc = -EINVAL;
	}
	return rc;
}
예제 #2
0
int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds)
{
	struct obd_device *obd = lmv2obd_dev(lmv);
	int rc;

	/*
	 * FIXME: Currently ZFS still use local seq for ROOT unfortunately, and
	 * this fid_is_local check should be removed once LU-2240 is fixed
	 */
	if (!fid_is_sane(fid) || !(fid_seq_in_fldb(fid_seq(fid)) ||
				   fid_seq_is_local_file(fid_seq(fid)))) {
		CERROR("%s: invalid FID " DFID "\n", obd->obd_name, PFID(fid));
		return -EINVAL;
	}

	rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds,
			       LU_SEQ_RANGE_MDT, NULL);
	if (rc) {
		CERROR("Error while looking for mds number. Seq %#llx, err = %d\n",
		       fid_seq(fid), rc);
		return rc;
	}

	CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
	       *mds, PFID(fid));

	if (*mds >= lmv->desc.ld_tgt_count) {
		CERROR("FLD lookup got invalid mds #%x (max: %x) for fid=" DFID "\n", *mds, lmv->desc.ld_tgt_count,
		       PFID(fid));
		rc = -EINVAL;
	}
	return rc;
}
예제 #3
0
static int osd_remote_fid(const struct lu_env *env, struct osd_device *osd,
			  struct lu_fid *fid)
{
	ENTRY;

	/* FID seqs not in FLDB, must be local seq */
	if (unlikely(!fid_seq_in_fldb(fid_seq(fid))))
		RETURN(0);

	if (osd_seq_exists(env, osd, fid_seq(fid)))
		RETURN(0);

	RETURN(1);
}
예제 #4
0
int fid_is_on_ost(struct osd_thread_info *info, struct osd_device *osd,
		  const struct lu_fid *fid, enum oi_check_flags flags)
{
	struct lu_seq_range	*range = &info->oti_seq_range;
	int			rc;
	ENTRY;

	if (flags & OI_KNOWN_ON_OST)
		RETURN(1);

	if (unlikely(fid_is_local_file(fid) || fid_is_igif(fid) ||
		     fid_is_llog(fid)) || fid_is_name_llog(fid) ||
		     fid_is_quota(fid))
		RETURN(0);

	if (fid_is_idif(fid) || fid_is_last_id(fid))
		RETURN(1);

	if (!(flags & OI_CHECK_FLD))
		RETURN(0);

	rc = osd_fld_lookup(info->oti_env, osd, fid_seq(fid), range);
	if (rc != 0) {
		if (rc != -ENOENT)
			CERROR("%s: lookup FLD "DFID": rc = %d\n",
			       osd_name(osd), PFID(fid), rc);
		RETURN(0);
	}

	if (fld_range_is_ost(range))
		RETURN(1);

	RETURN(0);
}
예제 #5
0
int osd_oi_update(struct osd_thread_info *info, struct osd_device *osd,
		  const struct lu_fid *fid, const struct osd_inode_id *id,
		  handle_t *th, enum oi_check_flags flags)
{
	struct lu_fid	    *oi_fid = &info->oti_fid2;
	struct osd_inode_id *oi_id  = &info->oti_id2;
	int		     rc     = 0;

	if (unlikely(fid_is_last_id(fid)))
		return osd_obj_spec_update(info, osd, fid, id, th);

	if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid))
		return osd_obj_map_update(info, osd, fid, id, th);

	fid_cpu_to_be(oi_fid, fid);
	osd_id_pack(oi_id, id);
	rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid),
			       (const struct dt_rec *)oi_id,
			       (const struct dt_key *)oi_fid, th, false);
	if (rc != 0)
		return rc;

	if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
		rc = osd_obj_spec_update(info, osd, fid, id, th);
	return rc;
}
예제 #6
0
/*
 * The transaction passed to this routine must have
 * dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT) called and then assigned
 * to a transaction group.
 */
int __osd_object_create(const struct lu_env *env, struct osd_object *obj,
			dmu_buf_t **dbp, dmu_tx_t *tx, struct lu_attr *la)
{
	uint64_t	     oid;
	int		     rc;
	struct osd_device   *osd = osd_obj2dev(obj);
	const struct lu_fid *fid = lu_object_fid(&obj->oo_dt.do_lu);
	dmu_object_type_t    type = DMU_OT_PLAIN_FILE_CONTENTS;

	/* Use DMU_OTN_UINT8_METADATA for local objects so their data blocks
	 * would get an additional ditto copy */
	if (unlikely(S_ISREG(la->la_mode) &&
		     fid_seq_is_local_file(fid_seq(fid))))
		type = DMU_OTN_UINT8_METADATA;

	/* Create a new DMU object using the default dnode size. */
	oid = osd_dmu_object_alloc(osd->od_os, type, 0, 0, tx);
	rc = -sa_buf_hold(osd->od_os, oid, osd_obj_tag, dbp);
	LASSERTF(rc == 0, "sa_buf_hold %llu failed: %d\n", oid, rc);

	LASSERT(la->la_valid & LA_MODE);
	la->la_size = 0;
	la->la_nlink = 1;

	return 0;
}
예제 #7
0
int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
		  const struct lu_fid *fid, struct osd_inode_id *id,
		  enum oi_check_flags flags)
{
	if (unlikely(fid_is_last_id(fid)))
		return osd_obj_spec_lookup(info, osd, fid, id);

	if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid))
		return osd_obj_map_lookup(info, osd, fid, id);


	if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE)) {
		int rc;
		if (fid_is_fs_root(fid)) {
			osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino,
				   osd_sb(osd)->s_root->d_inode->i_generation);
			return 0;
		}
		if (unlikely(fid_is_acct(fid)))
			return osd_acct_obj_lookup(info, osd, fid, id);

		/* For other special FIDs, try OI first, then do spec lookup */
		rc = __osd_oi_lookup(info, osd, fid, id);
		if (rc == -ENOENT)
			return osd_obj_spec_lookup(info, osd, fid, id);
		return rc;
	}

	if (!osd->od_igif_inoi && fid_is_igif(fid)) {
		osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid));
		return 0;
	}

	return __osd_oi_lookup(info, osd, fid, id);
}
예제 #8
0
파일: obdo.c 프로젝트: Announcement/linux
void obdo_set_parent_fid(struct obdo *dst, const struct lu_fid *parent)
{
	dst->o_parent_oid = fid_oid(parent);
	dst->o_parent_seq = fid_seq(parent);
	dst->o_parent_ver = fid_ver(parent);
	dst->o_valid |= OBD_MD_FLGENER | OBD_MD_FLFID;
}
예제 #9
0
파일: lproc_osp.c 프로젝트: Lezval/lustre
static int osp_rd_prealloc_last_seq(char *page, char **start, off_t off,
				    int count, int *eof, void *data)
{
	struct obd_device *obd = data;
	struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev);

	if (osp == NULL)
		return 0;

	return snprintf(page, count, LPX64"\n",
			fid_seq(&osp->opd_pre_last_created_fid));
}
예제 #10
0
/* compatibility with orphan files created in versions before 2.11 */
static struct dt_key *mdd_orphan_key_fill_20(const struct lu_env *env,
					     const struct lu_fid *lf)
{
	char *key = mdd_env_info(env)->mti_key;

	LASSERT(key);
	snprintf(key, sizeof(mdd_env_info(env)->mti_key),
		 ORPHAN_FILE_NAME_FORMAT_20,
		 fid_seq(lf), fid_oid(lf), fid_ver(lf), ORPH_OP_UNLINK);

	return (struct dt_key *)key;
}
예제 #11
0
int osp_precreate_rollover_new_seq(struct lu_env *env, struct osp_device *osp)
{
	struct lu_fid	*fid = &osp_env_info(env)->osi_fid;
	struct lu_fid	*last_fid = &osp->opd_last_used_fid;
	int		rc;
	ENTRY;

	rc = seq_client_get_seq(env, osp->opd_obd->u.cli.cl_seq, &fid->f_seq);
	if (rc != 0) {
		CERROR("%s: alloc fid error: rc = %d\n",
		       osp->opd_obd->obd_name, rc);
		RETURN(rc);
	}

	fid->f_oid = 1;
	fid->f_ver = 0;
	LASSERTF(fid_seq(fid) != fid_seq(last_fid),
		 "fid "DFID", last_fid "DFID"\n", PFID(fid),
		 PFID(last_fid));

	rc = osp_write_last_oid_seq_files(env, osp, fid, 1);
	if (rc != 0) {
		CERROR("%s: Can not update oid/seq file: rc = %d\n",
		       osp->opd_obd->obd_name, rc);
		RETURN(rc);
	}

	LCONSOLE_INFO("%s: update sequence from "LPX64" to "LPX64"\n",
		      osp->opd_obd->obd_name, fid_seq(last_fid),
		      fid_seq(fid));
	/* Update last_xxx to the new seq */
	spin_lock(&osp->opd_pre_lock);
	osp->opd_last_used_fid = *fid;
	osp->opd_gap_start_fid = *fid;
	osp->opd_pre_used_fid = *fid;
	osp->opd_pre_last_created_fid = *fid;
	spin_unlock(&osp->opd_pre_lock);

	RETURN(rc);
}
예제 #12
0
static struct dt_key* orph_key_fill_18(const struct lu_env *env,
                                       const struct lu_fid *lf)
{
	char *key = mdd_env_info(env)->mti_key;
        int rc;

        LASSERT(key);
        rc = snprintf(key, NAME_MAX + 1, ORPHAN_FILE_NAME_FORMAT_18,
                      (unsigned long long)fid_seq(lf), fid_oid(lf));
        if (rc > 0)
                return (struct dt_key*) key;
        else
                return ERR_PTR(rc);
}
예제 #13
0
static inline int osp_objs_precreated(const struct lu_env *env,
				      struct osp_device *osp)
{
	struct lu_fid *fid1 = &osp->opd_pre_last_created_fid;
	struct lu_fid *fid2 = &osp->opd_pre_used_fid;

	LASSERTF(fid_seq(fid1) == fid_seq(fid2),
		 "Created fid"DFID" Next fid "DFID"\n", PFID(fid1), PFID(fid2));

	if (fid_is_idif(fid1)) {
		struct ost_id *oi1 = &osp_env_info(env)->osi_oi;
		struct ost_id *oi2 = &osp_env_info(env)->osi_oi2;

		LASSERT(fid_is_idif(fid1) && fid_is_idif(fid2));
		fid_to_ostid(fid1, oi1);
		fid_to_ostid(fid2, oi2);
		LASSERT(ostid_id(oi1) >= ostid_id(oi2));

		return ostid_id(oi1) - ostid_id(oi2);
	}

	return fid_oid(fid1) - fid_oid(fid2);
}
예제 #14
0
int lmv_fld_lookup(struct lmv_obd *lmv,
                   const struct lu_fid *fid,
                   mdsno_t *mds)
{
	int rc;
	ENTRY;

	LASSERTF(fid_is_sane(fid), DFID" is insane!\n", PFID(fid));

	/* FIXME: Because ZFS still use LOCAL fid sequence for root,
	 * and root will always be in MDT0, for local fid, it will
	 * return 0 directly. And it should be removed once the root
	 * FID has been assigned with special sequence */
	if (fid_seq(fid) == FID_SEQ_LOCAL_FILE) {
		*mds = 0;
		RETURN(0);
	}

	rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds,
                               LU_SEQ_RANGE_MDT, NULL);
        if (rc) {
                CERROR("Error while looking for mds number. Seq "LPX64
                       ", err = %d\n", fid_seq(fid), rc);
                RETURN(rc);
        }

        CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
               *mds, PFID(fid));

        if (*mds >= lmv->desc.ld_tgt_count) {
                CERROR("FLD lookup got invalid mds #%x (max: %x) "
                       "for fid="DFID"\n", *mds, lmv->desc.ld_tgt_count,
                       PFID(fid));
                rc = -EINVAL;
        }
        RETURN(rc);
}
예제 #15
0
/*
 * The transaction passed to this routine must have
 * dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT) called and then assigned
 * to a transaction group.
 */
int __osd_object_create(const struct lu_env *env, struct osd_object *obj,
			dmu_buf_t **dbp, dmu_tx_t *tx, struct lu_attr *la,
			uint64_t parent)
{
	uint64_t	     oid;
	int		     rc;
	struct osd_device   *osd = osd_obj2dev(obj);
	const struct lu_fid *fid = lu_object_fid(&obj->oo_dt.do_lu);
	dmu_object_type_t    type = DMU_OT_PLAIN_FILE_CONTENTS;

	/* Assert that the transaction has been assigned to a
	   transaction group. */
	LASSERT(tx->tx_txg != 0);

	/* Use DMU_OTN_UINT8_METADATA for local objects so their data blocks
	 * would get an additional ditto copy */
	if (unlikely(S_ISREG(la->la_mode) &&
		     fid_seq_is_local_file(fid_seq(fid))))
		type = DMU_OTN_UINT8_METADATA;

	/* Create a new DMU object. */
	oid = dmu_object_alloc(osd->od_os, type, 0,
			       DMU_OT_SA, DN_MAX_BONUSLEN, tx);
	rc = -sa_buf_hold(osd->od_os, oid, osd_obj_tag, dbp);
	LASSERTF(rc == 0, "sa_buf_hold "LPU64" failed: %d\n", oid, rc);

	LASSERT(la->la_valid & LA_MODE);
	la->la_size = 0;
	la->la_nlink = 1;

	rc = __osd_attr_init(env, osd, oid, tx, la, parent);
	if (rc != 0) {
		sa_buf_rele(*dbp, osd_obj_tag);
		*dbp = NULL;
		dmu_object_free(osd->od_os, oid, tx);
		return rc;
	}

	return 0;
}
예제 #16
0
/*
 * Returns true, if fid is local to this server node.
 *
 * WARNING: this function is *not* guaranteed to return false if fid is
 * remote: it makes an educated conservative guess only.
 *
 * fid_is_local() is supposed to be used in assertion checks only.
 */
int fid_is_local(const struct lu_env *env,
                 struct lu_site *site, const struct lu_fid *fid)
{
	int result;
	struct seq_server_site *ss_site;
	struct lu_seq_range *range;
	struct fld_thread_info *info;
	ENTRY;

	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
	range = &info->fti_lrange;

	result = 1; /* conservatively assume fid is local */
	ss_site = lu_site2seq(site);
	if (ss_site->ss_client_fld != NULL) {
		int rc;

		rc = fld_cache_lookup(ss_site->ss_client_fld->lcf_cache,
				      fid_seq(fid), range);
		if (rc == 0)
			result = (range->lsr_index == ss_site->ss_node_id);
	}
	return result;
}
예제 #17
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);
}
예제 #18
0
파일: mdd_compat.c 프로젝트: Lezval/lustre
int mdd_compat_fixes(const struct lu_env *env, struct mdd_device *mdd)
{
	struct mdd_thread_info	*info = mdd_env_info(env);
	struct mdd_object	*root;
	struct dt_object	*o;
	struct lustre_mdt_attrs	*lma;
	struct lu_buf		 buf;
	int			 rc;
	ENTRY;

	/* IGIF FIDS are valid for old 1.8 and 2.[123] ROOT and are kept.
	 * Normal FIDs used by Xyratex 1.8->2.1 upgrade tool are also kept. */
	if (fid_is_igif(&mdd->mdd_root_fid) || fid_is_norm(&mdd->mdd_root_fid))
		RETURN(0);

	/*
	 * FID is supposed to be FID_SEQ_ROOT for:
	 *  - new ldiskfs fs
	 *  - new ZFS fs
	 *  - old ZFS fs, by now processed with osd_convert_root_to_new_seq()
	 */
	if (fid_seq(&mdd->mdd_root_fid) != FID_SEQ_ROOT) {
		CERROR("%s: wrong FID "DFID" is used for /ROOT\n",
		       mdd2obd_dev(mdd)->obd_name,
		       PFID(&mdd->mdd_root_fid));
		RETURN(-EINVAL);
	}

	root = mdd_object_find(env, mdd, &mdd->mdd_root_fid);
	if (IS_ERR(root))
		RETURN(PTR_ERR(root));
	o = mdd_object_child(root);

	CDEBUG(D_OTHER, "/ROOT = "DFID"\n", PFID(&mdd->mdd_root_fid));

	if (dt_try_as_dir(env, o) == 0) {
		CERROR("%s: not a directory\n", mdd2obd_dev(mdd)->obd_name);
		GOTO(out, rc = -ENOTDIR);
	}

	lma = (struct lustre_mdt_attrs *)&info->mti_xattr_buf;
	CLASSERT(sizeof(info->mti_xattr_buf) >= LMA_OLD_SIZE);
	buf.lb_len = LMA_OLD_SIZE;
	buf.lb_buf = lma;
	rc = mdo_xattr_get(env, root, &buf, XATTR_NAME_LMA, BYPASS_CAPA);
	if (rc < 0 && rc != -ENODATA) {
		CERROR("%s: can't fetch LMA: rc = %d\n",
		       mdd2obd_dev(mdd)->obd_name, rc);
		GOTO(out, rc);
	}

	lustre_lma_swab(lma);
	if (lu_fid_eq(&lma->lma_self_fid, &mdd->mdd_root_fid)) {
		/* /ROOT has been converted already
		 * or was correct from the beginning */
		CDEBUG(D_OTHER, "%s: converted already\n",
		       mdd2obd_dev(mdd)->obd_name);
		GOTO(out, rc = 0);
	}

	/* this is supposed to happen only on pre-production ZFS backend */
	if (strcmp(mdd->mdd_bottom->dd_lu_dev.ld_type->ldt_name,
		   LUSTRE_OSD_ZFS_NAME) != 0) {
		CERROR("%s: "DFID" is used on ldiskfs?!\n",
		       mdd2obd_dev(mdd)->obd_name, PFID(&mdd->mdd_root_fid));
		GOTO(out, rc = -ENOTSUPP);
	}

	LCONSOLE_INFO("%s: FID of /ROOT has been changed. "
		      "Please remount the clients.\n",
		      mdd2obd_dev(mdd)->obd_name);

	/* Fill FLDB first */
	rc = mdd_fill_fldb(env, mdd);
	if (rc)
		GOTO(out, rc);

	/* remove ./.. from /ROOT */
	rc = mdd_convert_remove_dots(env, mdd, root);
	if (rc)
		GOTO(out, rc);

	/* go over the directory, fix all the objects */
	rc = mdd_fix_children(env, mdd, o);
	if (rc)
		GOTO(out, rc);

	/* Update LMA on /ROOT.  Done for simplicity in MDD, not in osd-zfs.
	 * Correct LMA will imply the whole directory has been coverted
	 * successfully, otherwise it will be retried on next mount. */
	rc = mdd_convert_lma(env, mdd, root);

out:
	mdd_object_put(env, root);
	RETURN(rc);
}
예제 #19
0
static int lfsck_master_oit_engine(const struct lu_env *env,
				   struct lfsck_instance *lfsck)
{
	struct lfsck_thread_info	*info	= lfsck_env_info(env);
	const struct dt_it_ops		*iops	=
				&lfsck->li_obj_oit->do_index_ops->dio_it;
	struct dt_it			*di	= lfsck->li_di_oit;
	struct lu_fid			*fid	= &info->lti_fid;
	struct lfsck_bookmark		*bk	= &lfsck->li_bookmark_ram;
	struct ptlrpc_thread		*thread = &lfsck->li_thread;
	__u32				 idx	=
				lfsck_dev_idx(lfsck->li_bottom);
	int				 rc;
	ENTRY;

	do {
		struct dt_object *target;
		bool		  update_lma = false;

		if (lfsck->li_di_dir != NULL) {
			rc = lfsck_master_dir_engine(env, lfsck);
			if (rc <= 0)
				RETURN(rc);
		}

		if (unlikely(lfsck->li_oit_over))
			RETURN(1);

		if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY1) &&
		    cfs_fail_val > 0) {
			struct l_wait_info lwi;

			lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val),
					  NULL, NULL);
			l_wait_event(thread->t_ctl_waitq,
				     !thread_is_running(thread),
				     &lwi);
		}

		if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH))
			RETURN(0);

		lfsck->li_current_oit_processed = 1;
		lfsck->li_new_scanned++;
		rc = iops->rec(env, di, (struct dt_rec *)fid, 0);
		if (rc != 0) {
			lfsck_fail(env, lfsck, true);
			if (rc < 0 && bk->lb_param & LPF_FAILOUT)
				RETURN(rc);
			else
				goto checkpoint;
		}

		if (fid_is_idif(fid)) {
			__u32 idx1 = fid_idif_ost_idx(fid);

			LASSERT(!lfsck->li_master);

			/* It is an old format device, update the LMA. */
			if (idx != idx1) {
				struct ost_id *oi = &info->lti_oi;

				fid_to_ostid(fid, oi);
				ostid_to_fid(fid, oi, idx);
				update_lma = true;
			}
		} else if (!fid_is_norm(fid) && !fid_is_igif(fid) &&
			   !fid_is_last_id(fid) && !fid_is_root(fid) &&
			   !fid_seq_is_dot(fid_seq(fid))) {
			/* If the FID/object is only used locally and invisible
			 * to external nodes, then LFSCK will not handle it. */
			goto checkpoint;
		}

		target = lfsck_object_find(env, lfsck, fid);
		if (target == NULL) {
			goto checkpoint;
		} else if (IS_ERR(target)) {
			lfsck_fail(env, lfsck, true);
			if (bk->lb_param & LPF_FAILOUT)
				RETURN(PTR_ERR(target));
			else
				goto checkpoint;
		}

		/* XXX: Currently, skip remote object, the consistency for
		 *	remote object will be processed in LFSCK phase III. */
		if (dt_object_exists(target) && !dt_object_remote(target)) {
			if (update_lma)
				rc = lfsck_update_lma(env, lfsck, target);
			if (rc == 0)
				rc = lfsck_exec_oit(env, lfsck, target);
		}
		lfsck_object_put(env, target);
		if (rc != 0 && bk->lb_param & LPF_FAILOUT)
			RETURN(rc);

checkpoint:
		rc = lfsck_checkpoint(env, lfsck);
		if (rc != 0 && bk->lb_param & LPF_FAILOUT)
			RETURN(rc);

		/* Rate control. */
		lfsck_control_speed(lfsck);

		if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_FATAL1)) {
			spin_lock(&lfsck->li_lock);
			thread_set_flags(thread, SVC_STOPPING);
			spin_unlock(&lfsck->li_lock);
			RETURN(-EINVAL);
		}

		rc = iops->next(env, di);
		if (unlikely(rc > 0))
			lfsck->li_oit_over = 1;
		else if (likely(rc == 0))
			lfsck->li_current_oit_processed = 0;

		if (unlikely(!thread_is_running(thread)))
			RETURN(0);
	} while (rc == 0 || lfsck->li_di_dir != NULL);

	RETURN(rc);
}
예제 #20
0
/**
 * Prepare buffers for write request processing.
 *
 * This function converts remote buffers from client to local buffers
 * and prepares the latter. If there is recovery in progress and required
 * object is missing then it can be re-created before write.
 *
 * \param[in] env	execution environment
 * \param[in] exp	OBD export of client
 * \param[in] ofd	OFD device
 * \param[in] fid	FID of object
 * \param[in] la	object attributes
 * \param[in] oa	OBDO structure from client
 * \param[in] objcount	always 1
 * \param[in] obj	object data
 * \param[in] rnb	remote buffers
 * \param[in] nr_local	number of local buffers
 * \param[in] lnb	local buffers
 * \param[in] jobid	job ID name
 *
 * \retval		0 on successful prepare
 * \retval		negative value on error
 */
static int ofd_preprw_write(const struct lu_env *env, struct obd_export *exp,
			    struct ofd_device *ofd, const struct lu_fid *fid,
			    struct lu_attr *la, struct obdo *oa,
			    int objcount, struct obd_ioobj *obj,
			    struct niobuf_remote *rnb, int *nr_local,
			    struct niobuf_local *lnb, char *jobid)
{
	struct ofd_object	*fo;
	int			 i, j, k, rc = 0, tot_bytes = 0;

	ENTRY;
	LASSERT(env != NULL);
	LASSERT(objcount == 1);

	if (unlikely(exp->exp_obd->obd_recovering)) {
		u64 seq = fid_seq(fid);
		u64 oid = fid_oid(fid);
		struct ofd_seq *oseq;

		oseq = ofd_seq_load(env, ofd, seq);
		if (IS_ERR(oseq)) {
			CERROR("%s: Can't find FID Sequence "LPX64": rc = %d\n",
			       ofd_name(ofd), seq, (int)PTR_ERR(oseq));
			GOTO(out, rc = -EINVAL);
		}

		if (oid > ofd_seq_last_oid(oseq)) {
			int sync = 0;
			int diff;

			mutex_lock(&oseq->os_create_lock);
			diff = oid - ofd_seq_last_oid(oseq);

			/* Do sync create if the seq is about to used up */
			if (fid_seq_is_idif(seq) || fid_seq_is_mdt0(seq)) {
				if (unlikely(oid >= IDIF_MAX_OID - 1))
					sync = 1;
			} else if (fid_seq_is_norm(seq)) {
				if (unlikely(oid >=
					     LUSTRE_DATA_SEQ_MAX_WIDTH - 1))
					sync = 1;
			} else {
				CERROR("%s : invalid o_seq "DOSTID"\n",
				       ofd_name(ofd), POSTID(&oa->o_oi));
				mutex_unlock(&oseq->os_create_lock);
				ofd_seq_put(env, oseq);
				GOTO(out, rc = -EINVAL);
			}

			while (diff > 0) {
				u64 next_id = ofd_seq_last_oid(oseq) + 1;
				int count = ofd_precreate_batch(ofd, diff);

				rc = ofd_precreate_objects(env, ofd, next_id,
							   oseq, count, sync);
				if (rc < 0) {
					mutex_unlock(&oseq->os_create_lock);
					ofd_seq_put(env, oseq);
					GOTO(out, rc);
				}

				diff -= rc;
			}

			mutex_unlock(&oseq->os_create_lock);
		}

		ofd_seq_put(env, oseq);
	}

	fo = ofd_object_find(env, ofd, fid);
	if (IS_ERR(fo))
		GOTO(out, rc = PTR_ERR(fo));
	LASSERT(fo != NULL);

	ofd_read_lock(env, fo);
	if (!ofd_object_exists(fo)) {
		CERROR("%s: BRW to missing obj "DOSTID"\n",
		       exp->exp_obd->obd_name, POSTID(&obj->ioo_oid));
		ofd_read_unlock(env, fo);
		ofd_object_put(env, fo);
		GOTO(out, rc = -ENOENT);
	}

	if (ofd->ofd_lfsck_verify_pfid && oa->o_valid & OBD_MD_FLFID) {
		rc = ofd_verify_ff(env, fo, oa);
		if (rc != 0) {
			ofd_read_unlock(env, fo);
			ofd_object_put(env, fo);
			GOTO(out, rc);
		}
	}

	/* Process incoming grant info, set OBD_BRW_GRANTED flag and grant some
	 * space back if possible */
	ofd_grant_prepare_write(env, exp, oa, rnb, obj->ioo_bufcnt);

	/* parse remote buffers to local buffers and prepare the latter */
	*nr_local = 0;
	for (i = 0, j = 0; i < obj->ioo_bufcnt; i++) {
		rc = dt_bufs_get(env, ofd_object_child(fo),
				 rnb + i, lnb + j, 1);
		if (unlikely(rc < 0))
			GOTO(err, rc);
		LASSERT(rc <= PTLRPC_MAX_BRW_PAGES);
		/* correct index for local buffers to continue with */
		for (k = 0; k < rc; k++) {
			lnb[j+k].lnb_flags = rnb[i].rnb_flags;
			if (!(rnb[i].rnb_flags & OBD_BRW_GRANTED))
				lnb[j+k].lnb_rc = -ENOSPC;
		}
		j += rc;
		*nr_local += rc;
		LASSERT(j <= PTLRPC_MAX_BRW_PAGES);
		tot_bytes += rnb[i].rnb_len;
	}
	LASSERT(*nr_local > 0 && *nr_local <= PTLRPC_MAX_BRW_PAGES);

	rc = dt_write_prep(env, ofd_object_child(fo), lnb, *nr_local);
	if (unlikely(rc != 0))
		GOTO(err, rc);

	ofd_counter_incr(exp, LPROC_OFD_STATS_WRITE, jobid, tot_bytes);
	RETURN(0);
err:
	dt_bufs_put(env, ofd_object_child(fo), lnb, *nr_local);
	ofd_read_unlock(env, fo);
	ofd_object_put(env, fo);
	/* ofd_grant_prepare_write() was called, so we must commit */
	ofd_grant_commit(exp, oa->o_grant_used, rc);
out:
	/* let's still process incoming grant information packed in the oa,
	 * but without enforcing grant since we won't proceed with the write.
	 * Just like a read request actually. */
	ofd_grant_prepare_read(env, exp, oa);
	return rc;
}
예제 #21
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;
}
예제 #22
0
int osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd,
		  const struct lu_fid *fid, const struct osd_inode_id *id,
		  handle_t *th, enum oi_check_flags flags)
{
	struct lu_fid	    *oi_fid = &info->oti_fid2;
	struct osd_inode_id *oi_id  = &info->oti_id2;
	int		     rc     = 0;

	if (unlikely(fid_is_last_id(fid)))
		return osd_obj_spec_insert(info, osd, fid, id, th);

	if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid))
		return osd_obj_map_insert(info, osd, fid, id, th);

	fid_cpu_to_be(oi_fid, fid);
	osd_id_pack(oi_id, id);
	rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid),
			       (const struct dt_rec *)oi_id,
			       (const struct dt_key *)oi_fid, th, true);
	if (rc != 0) {
		struct inode *inode;
		struct lustre_mdt_attrs *lma = &info->oti_mdt_attrs;

		if (rc != -EEXIST)
			return rc;

		rc = osd_oi_lookup(info, osd, fid, oi_id, 0);
		if (rc != 0)
			return rc;

		if (unlikely(osd_id_eq(id, oi_id)))
			return 1;

		/* Check whether the mapping for oi_id is valid or not. */
		inode = osd_iget(info, osd, oi_id);
		if (IS_ERR(inode)) {
			rc = PTR_ERR(inode);
			if (rc == -ENOENT || rc == -ESTALE)
				goto update;
			return rc;
		}

		/* The EA inode should NOT be in OI, old OI scrub may added
		 * such OI mapping by wrong, replace it. */
		if (unlikely(osd_is_ea_inode(inode))) {
			iput(inode);
			goto update;
		}

		rc = osd_get_lma(info, inode, &info->oti_obj_dentry, lma);
		iput(inode);
		if (rc == -ENODATA)
			goto update;

		if (rc != 0)
			return rc;

		if (!(lma->lma_compat & LMAC_NOT_IN_OI) &&
		    lu_fid_eq(fid, &lma->lma_self_fid)) {
			CERROR("%.16s: the FID "DFID" is used by two objects: "
			       "%u/%u %u/%u\n",
			       LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name,
			       PFID(fid), oi_id->oii_ino, oi_id->oii_gen,
			       id->oii_ino, id->oii_gen);
			return -EEXIST;
		}

update:
		osd_id_pack(oi_id, id);
		rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid),
					(const struct dt_rec *)oi_id,
					(const struct dt_key *)oi_fid, th, false);
		if (rc != 0)
			return rc;
	}

	if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
		rc = osd_obj_spec_insert(info, osd, fid, id, th);
	return rc;
}
예제 #23
0
static inline int fid_is_fs_root(const struct lu_fid *fid)
{
        /* Map root inode to special local object FID */
        return (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE &&
                         fid_oid(fid) == OSD_FS_ROOT_OID));
}