Ejemplo n.º 1
0
void mdd_read_lock(const struct lu_env *env, struct mdd_object *obj,
                   enum mdd_object_role role)
{
        struct dt_object  *next = mdd_object_child(obj);

        next->do_ops->do_read_lock(env, next, role);
}
Ejemplo n.º 2
0
/*
 * To enable DNE functionality we need FID of /ROOT directory
 * (which is / as seen by the clients) to belong to MDT0 and
 * not to FID_SEQ_LOCAL_FILE or some other local sequence,
 * which can be used by any node, so can't be part of FLDB.
 *
 * Pre-production code was using FID_SEQ_LOCAL_FILE for /ROOT
 * making few existing setups incompatibile with DNE. This
 * applies to ZFS-based setups only as ldiskfs-based setups
 * are still using IGIF to identify /ROOT.
 *
 * The intention of this code is to fix on-disk state to use
 * FID_SEQ_ROOT for /ROOT:
 *  - "." and ".." references in /ROOT itself and it`s subdirectories
 *  - LinkEA in all the objects listed in /ROOT
 *
 * Given only ZFS is affected where "." and ".." are not stored, we need to:
 *  - delete "." and ".." from /ROOT and its subdirectories
 *  - rename references in LinkEA in all the objects listed in /ROOT
 *
 * This code is subject for removal in 2.5
 */
static int mdd_convert_remove_dots(const struct lu_env *env,
				   struct mdd_device *mdd,
				   struct mdd_object *o)
{
	struct thandle		*th;
	const struct dt_key	*dot = (const struct dt_key *)".";
	const struct dt_key	*dotdot = (const struct dt_key *)"..";
	int			 rc;

	if (dt_try_as_dir(env, mdd_object_child(o)) == 0)
		RETURN(-ENOTDIR);

	/* remove "."/".." and do not insert them back - not stored in ZFS */
	th = dt_trans_create(env, mdd->mdd_child);
	if (IS_ERR(th))
		RETURN(PTR_ERR(th));

	rc = dt_declare_delete(env, mdd_object_child(o), dot, th);
	if (rc)
		GOTO(out, rc);
	rc = dt_declare_delete(env, mdd_object_child(o), dotdot, th);
	if (rc)
		GOTO(out, rc);
	rc = dt_trans_start_local(env, mdd->mdd_child, th);
	if (rc)
		GOTO(out, rc);
	/* ignore non-existing "."/".." - we stored them on disk for
	 * pre-production systems, but this is not how regular ZFS works */
	rc = dt_delete(env, mdd_object_child(o), dot, th, BYPASS_CAPA);
	if (rc == -ENOENT)
		rc = 0;
	if (rc)
		GOTO(out, rc);
	rc = dt_delete(env, mdd_object_child(o), dotdot, th, BYPASS_CAPA);
	if (rc == -ENOENT)
		rc = 0;
	if (rc)
		GOTO(out, rc);

out:
	dt_trans_stop(env, mdd->mdd_child, th);
	RETURN(rc);
}
Ejemplo n.º 3
0
static int orph_index_insert(const struct lu_env *env,
                             struct mdd_object *obj,
                             __u32 op,
                             struct thandle *th)
{
        struct mdd_device       *mdd    = mdo2mdd(&obj->mod_obj);
        struct dt_object        *dor    = mdd->mdd_orphans;
        const struct lu_fid     *lf_dor = lu_object_fid(&dor->do_lu);
        struct dt_object        *next   = mdd_object_child(obj);
        int rc;
        ENTRY;

        LASSERT(mdd_write_locked(env, obj) != 0);
        LASSERT(!(obj->mod_flags & ORPHAN_OBJ));

        mdd_orphan_write_lock(env, mdd);

        rc = mdd_orphan_insert_obj(env, mdd, obj, op, th);
        if (rc)
                GOTO(out, rc);

        mdo_ref_add(env, obj, th);
        if (!S_ISDIR(mdd_object_type(obj)))
                goto out;

        mdo_ref_add(env, obj, th);
        mdd_orphan_ref_add(env, mdd, th);

        /* try best to fixup directory, dont return errors
         * from here */
        if (!dt_try_as_dir(env, next))
                goto out;
        next->do_index_ops->dio_delete(env, next,
                                       (const struct dt_key *)dotdot,
                                       th, BYPASS_CAPA);

        next->do_index_ops->dio_insert(env, next,
                                       (struct dt_rec *)lf_dor,
                                       (const struct dt_key *)dotdot,
                                       th, BYPASS_CAPA, 1);

out:
        if (rc == 0)
                obj->mod_flags |= ORPHAN_OBJ;

        mdd_orphan_write_unlock(env, mdd);

        RETURN(rc);
}
Ejemplo n.º 4
0
/**
 *  add an orphan \a obj to the orphan index.
 *  \param obj file or directory.
 *  \param th  transaction for index insert.
 *
 *  \pre obj nlink == 0 && obj->mod_count != 0
 *
 *  \retval 0  success
 *  \retval  -ve index operation error.
 */
int mdd_orphan_insert(const struct lu_env *env, struct mdd_object *obj,
		      struct thandle *th)
{
	struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
	struct dt_object *dor = mdd->mdd_orphans;
	const struct lu_fid *lf_dor = lu_object_fid(&dor->do_lu);
	struct dt_object *next = mdd_object_child(obj);
	struct dt_insert_rec *rec = &mdd_env_info(env)->mti_dt_rec;
	int rc;
	ENTRY;

	LASSERT(mdd_write_locked(env, obj) != 0);
	LASSERT(!(obj->mod_flags & ORPHAN_OBJ));

	dt_write_lock(env, mdd->mdd_orphans, MOR_TGT_ORPHAN);

	rc = mdd_orphan_insert_obj(env, mdd, obj, th);
	if (rc)
		GOTO(out, rc);

	mdo_ref_add(env, obj, th);
	if (!S_ISDIR(mdd_object_type(obj)))
		GOTO(out, rc = 0);

	mdo_ref_add(env, obj, th);
	dt_ref_add(env, mdd->mdd_orphans, th);

	/* try best to fixup directory, do not return errors from here */
	if (!dt_try_as_dir(env, next))
		GOTO(out, rc = 0);

	dt_delete(env, next, (const struct dt_key *)dotdot, th);

	rec->rec_fid = lf_dor;
	rec->rec_type = S_IFDIR;
	dt_insert(env, next, (const struct dt_rec *)rec,
		  (const struct dt_key *)dotdot, th);

out:
	if (rc == 0)
		obj->mod_flags |= ORPHAN_OBJ;

	dt_write_unlock(env, mdd->mdd_orphans);

	RETURN(rc);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
int mdd_write_locked(const struct lu_env *env, struct mdd_object *obj)
{
        struct dt_object  *next = mdd_object_child(obj);

        return next->do_ops->do_write_locked(env, next);
}
Ejemplo n.º 7
0
void mdd_read_unlock(const struct lu_env *env, struct mdd_object *obj)
{
        struct dt_object  *next = mdd_object_child(obj);

        next->do_ops->do_read_unlock(env, next);
}