rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg);
break;
}
+ case LL_IOC_FID2MDTIDX: {
+ struct lu_fid *fid = karg;
+ int mdt_index;
+
+ rc = lmv_fld_lookup(lmv, fid, &mdt_index);
+ if (rc != 0)
+ RETURN(rc);
+
+ /* Note: this is from llite(see ll_dir_ioctl()), @uarg does not
+ * point to user space memory for FID2MDTIDX. */
+ *(__u32 *)uarg = mdt_index;
+ break;
+ }
case OBD_IOC_FID2PATH: {
rc = lmv_fid2path(exp, len, karg, uarg);
break;
* retval pointer to the lmv_tgt_desc if succeed.
* ERR_PTR(errno) if failed.
*/
-struct lmv_tgt_desc
-*lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data,
- struct lu_fid *fid)
+struct lmv_tgt_desc*
+lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data,
+ struct lu_fid *fid)
{
struct lmv_stripe_md *lsm = op_data->op_mea1;
struct lmv_tgt_desc *tgt;
+ /* During creating VOLATILE file, it should honor the mdt
+ * index if the file under striped dir is being restored, see
+ * ct_restore(). */
+ if (op_data->op_bias & MDS_CREATE_VOLATILE &&
+ (int)op_data->op_mds != -1 && lsm != NULL) {
+ int i;
+ tgt = lmv_get_target(lmv, op_data->op_mds, NULL);
+ if (IS_ERR(tgt))
+ return tgt;
+
+ /* refill the right parent fid */
+ for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
+ struct lmv_oinfo *oinfo;
+
+ oinfo = &lsm->lsm_md_oinfo[i];
+ if (oinfo->lmo_mds == op_data->op_mds) {
+ *fid = oinfo->lmo_fid;
+ break;
+ }
+ }
+
+ /* Hmm, can not find the stripe by mdt_index(op_mds) */
+ if (i == lsm->lsm_md_stripe_count)
+ tgt = ERR_PTR(-EINVAL);
+
+ return tgt;
+ }
+
if (lsm == NULL || op_data->op_namelen == 0) {
tgt = lmv_find_target(lmv, fid);
if (IS_ERR(tgt))
RETURN(rc);
}
-/*
- * Adjust a set of pages, each page containing an array of lu_dirpages,
- * so that each page can be used as a single logical lu_dirpage.
- *
- * A lu_dirpage is laid out as follows, where s = ldp_hash_start,
- * e = ldp_hash_end, f = ldp_flags, p = padding, and each "ent" is a
- * struct lu_dirent. It has size up to LU_PAGE_SIZE. The ldp_hash_end
- * value is used as a cookie to request the next lu_dirpage in a
- * directory listing that spans multiple pages (two in this example):
- * ________
- * | |
- * .|--------v------- -----.
- * |s|e|f|p|ent|ent| ... |ent|
- * '--|-------------- -----' Each CFS_PAGE contains a single
- * '------. lu_dirpage.
- * .---------v------- -----.
- * |s|e|f|p|ent| 0 | ... | 0 |
- * '----------------- -----'
- *
- * However, on hosts where the native VM page size (PAGE_CACHE_SIZE) is
- * larger than LU_PAGE_SIZE, a single host page may contain multiple
- * lu_dirpages. After reading the lu_dirpages from the MDS, the
- * ldp_hash_end of the first lu_dirpage refers to the one immediately
- * after it in the same CFS_PAGE (arrows simplified for brevity, but
- * in general e0==s1, e1==s2, etc.):
- *
- * .-------------------- -----.
- * |s0|e0|f0|p|ent|ent| ... |ent|
- * |---v---------------- -----|
- * |s1|e1|f1|p|ent|ent| ... |ent|
- * |---v---------------- -----| Here, each CFS_PAGE contains
- * ... multiple lu_dirpages.
- * |---v---------------- -----|
- * |s'|e'|f'|p|ent|ent| ... |ent|
- * '---|---------------- -----'
- * v
- * .----------------------------.
- * | next CFS_PAGE |
- *
- * This structure is transformed into a single logical lu_dirpage as follows:
- *
- * - Replace e0 with e' so the request for the next lu_dirpage gets the page
- * labeled 'next CFS_PAGE'.
- *
- * - Copy the LDF_COLLIDE flag from f' to f0 to correctly reflect whether
- * a hash collision with the next page exists.
- *
- * - Adjust the lde_reclen of the ending entry of each lu_dirpage to span
- * to the first entry of the next lu_dirpage.
- */
-#if PAGE_CACHE_SIZE > LU_PAGE_SIZE
-static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs)
-{
- int i;
-
- for (i = 0; i < ncfspgs; i++) {
- struct lu_dirpage *dp = kmap(pages[i]);
- struct lu_dirpage *first = dp;
- struct lu_dirent *end_dirent = NULL;
- struct lu_dirent *ent;
- __u64 hash_end = dp->ldp_hash_end;
- __u32 flags = dp->ldp_flags;
-
- while (--nlupgs > 0) {
- ent = lu_dirent_start(dp);
- for (end_dirent = ent; ent != NULL;
- end_dirent = ent, ent = lu_dirent_next(ent));
-
- /* Advance dp to next lu_dirpage. */
- dp = (struct lu_dirpage *)((char *)dp + LU_PAGE_SIZE);
-
- /* Check if we've reached the end of the CFS_PAGE. */
- if (!((unsigned long)dp & ~CFS_PAGE_MASK))
- break;
-
- /* Save the hash and flags of this lu_dirpage. */
- hash_end = dp->ldp_hash_end;
- flags = dp->ldp_flags;
-
- /* Check if lu_dirpage contains no entries. */
- if (!end_dirent)
- break;
-
- /* Enlarge the end entry lde_reclen from 0 to
- * first entry of next lu_dirpage. */
- LASSERT(le16_to_cpu(end_dirent->lde_reclen) == 0);
- end_dirent->lde_reclen =
- cpu_to_le16((char *)(dp->ldp_entries) -
- (char *)end_dirent);
- }
-
- first->ldp_hash_end = hash_end;
- first->ldp_flags &= ~cpu_to_le32(LDF_COLLIDE);
- first->ldp_flags |= flags & cpu_to_le32(LDF_COLLIDE);
-
- kunmap(pages[i]);
- }
- LASSERTF(nlupgs == 0, "left = %d", nlupgs);
-}
-#else
-#define lmv_adjust_dirpages(pages, ncfspgs, nlupgs) do {} while (0)
-#endif /* PAGE_CACHE_SIZE > LU_PAGE_SIZE */
-
/**
* Get current minimum entry from striped directory
*
/* Not cross-ref case, just get out of here. */
if (likely(!(body->mbo_valid & OBD_MD_MDS)))
- RETURN(0);
+ RETURN(rc);
CDEBUG(D_INODE, "%s: try unlink to another MDT for "DFID"\n",
exp->exp_obd->obd_name, PFID(&body->mbo_fid1));
lsm->lsm_md_layout_version);
stripe_count = le32_to_cpu(lmm1->lmv_stripe_count);
- for (i = 0; i < le32_to_cpu(stripe_count); i++) {
+ for (i = 0; i < stripe_count; i++) {
fid_le_to_cpu(&lsm->lsm_md_oinfo[i].lmo_fid,
&lmm1->lmv_stripe_fids[i]);
rc = lmv_fld_lookup(lmv, &lsm->lsm_md_oinfo[i].lmo_fid,