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); }
/* * 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); }
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); }
/** * 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); }
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); }
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); }
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); }