Whamcloud - gitweb
LU-3531 llite: fix "lfs getdirstripe" to show stripe info
[fs/lustre-release.git] / lustre / llite / dir.c
index b97edda..c579304 100644 (file)
@@ -443,6 +443,13 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
                         lum_size = sizeof(struct lov_user_md_v3);
                         break;
                 }
+               case LMV_USER_MAGIC: {
+                       if (lump->lmm_magic != cpu_to_le32(LMV_USER_MAGIC))
+                               lustre_swab_lmv_user_md(
+                                       (struct lmv_user_md *)lump);
+                       lum_size = sizeof(struct lmv_user_md);
+                       break;
+               }
                 default: {
                         CDEBUG(D_IOCTL, "bad userland LOV MAGIC:"
                                         " %#08x != %#08x nor %#08x\n",
@@ -514,73 +521,113 @@ end:
        RETURN(rc);
 }
 
-int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp,
-                     int *lmm_size, struct ptlrpc_request **request)
+/**
+ * This function will be used to get default LOV/LMV/Default LMV
+ * @valid will be used to indicate which stripe it will retrieve
+ *     OBD_MD_MEA              LMV stripe EA
+ *     OBD_MD_DEFAULT_MEA      Default LMV stripe EA
+ *     otherwise               Default LOV EA.
+ * Each time, it can only retrieve 1 stripe EA
+ **/
+int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size,
+                    struct ptlrpc_request **request, obd_valid valid)
 {
-        struct ll_sb_info *sbi = ll_i2sbi(inode);
-        struct mdt_body   *body;
-        struct lov_mds_md *lmm = NULL;
-        struct ptlrpc_request *req = NULL;
-        int rc, lmmsize;
-        struct md_op_data *op_data;
+       struct ll_sb_info *sbi = ll_i2sbi(inode);
+       struct mdt_body   *body;
+       struct lov_mds_md *lmm = NULL;
+       struct ptlrpc_request *req = NULL;
+       int rc, lmm_size;
+       struct md_op_data *op_data;
+       ENTRY;
 
-        rc = ll_get_max_mdsize(sbi, &lmmsize);
-        if (rc)
-                RETURN(rc);
+       rc = ll_get_max_mdsize(sbi, &lmm_size);
+       if (rc)
+               RETURN(rc);
 
-        op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL,
-                                     0, lmmsize, LUSTRE_OPC_ANY,
-                                     NULL);
-        if (IS_ERR(op_data))
-                RETURN(PTR_ERR(op_data));
+       op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL,
+                                    0, lmm_size, LUSTRE_OPC_ANY,
+                                    NULL);
+       if (IS_ERR(op_data))
+               RETURN(PTR_ERR(op_data));
 
-        op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
-        rc = md_getattr(sbi->ll_md_exp, op_data, &req);
-        ll_finish_md_op_data(op_data);
-        if (rc < 0) {
+       op_data->op_valid = valid | OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
+       rc = md_getattr(sbi->ll_md_exp, op_data, &req);
+       ll_finish_md_op_data(op_data);
+       if (rc < 0) {
                CDEBUG(D_INFO, "md_getattr failed on inode "
                       DFID": rc %d\n", PFID(ll_inode2fid(inode)), rc);
-                GOTO(out, rc);
-        }
+               GOTO(out, rc);
+       }
 
-        body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-        LASSERT(body != NULL);
+       body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
+       LASSERT(body != NULL);
 
-        lmmsize = body->eadatasize;
+       lmm_size = body->eadatasize;
 
-        if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) ||
-            lmmsize == 0) {
-                GOTO(out, rc = -ENODATA);
-        }
+       if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) ||
+           lmm_size == 0) {
+               GOTO(out, rc = -ENODATA);
+       }
 
-        lmm = req_capsule_server_sized_get(&req->rq_pill,
-                                           &RMF_MDT_MD, lmmsize);
-        LASSERT(lmm != NULL);
-
-        /*
-         * This is coming from the MDS, so is probably in
-         * little endian.  We convert it to host endian before
-         * passing it to userspace.
-         */
-        /* We don't swab objects for directories */
-        switch (le32_to_cpu(lmm->lmm_magic)) {
-        case LOV_MAGIC_V1:
-                if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
-                        lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm);
-                break;
-        case LOV_MAGIC_V3:
-                if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
-                        lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm);
-                break;
-        default:
-                CERROR("unknown magic: %lX\n", (unsigned long)lmm->lmm_magic);
-                rc = -EPROTO;
-        }
+       lmm = req_capsule_server_sized_get(&req->rq_pill,
+                                          &RMF_MDT_MD, lmm_size);
+       LASSERT(lmm != NULL);
+
+       /*
+        * This is coming from the MDS, so is probably in
+        * little endian.  We convert it to host endian before
+        * passing it to userspace.
+        */
+       /* We don't swab objects for directories */
+       switch (le32_to_cpu(lmm->lmm_magic)) {
+       case LOV_MAGIC_V1:
+               if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
+                       lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm);
+               break;
+       case LOV_MAGIC_V3:
+               if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
+                       lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm);
+               break;
+       case LMV_MAGIC:
+               if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
+                       lustre_swab_lmv_mds_md((union lmv_mds_md *)lmm);
+               break;
+       case LMV_USER_MAGIC:
+               if (LMV_USER_MAGIC != cpu_to_le32(LMV_USER_MAGIC))
+                       lustre_swab_lmv_user_md((struct lmv_user_md *)lmm);
+               break;
+       default:
+               CERROR("unknown magic: %lX\n", (unsigned long)lmm->lmm_magic);
+               rc = -EPROTO;
+       }
 out:
-        *lmmp = lmm;
-        *lmm_size = lmmsize;
-        *request = req;
-        return rc;
+       *plmm = lmm;
+       *plmm_size = lmm_size;
+       *request = req;
+       return rc;
+}
+
+static int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi,
+                                const struct lu_fid *fid)
+{
+       struct md_op_data       *op_data;
+       int                     rc;
+       int                     mdt_index;
+       ENTRY;
+
+       OBD_ALLOC_PTR(op_data);
+       if (op_data == NULL)
+               RETURN(-ENOMEM);
+
+       op_data->op_flags |= MF_GET_MDT_IDX;
+       op_data->op_fid1 = *fid;
+       rc = md_getattr(sbi->ll_md_exp, op_data, NULL);
+       mdt_index = op_data->op_mds;
+       OBD_FREE_PTR(op_data);
+       if (rc < 0)
+               RETURN(rc);
+
+       RETURN(mdt_index);
 }
 
 /*
@@ -588,25 +635,7 @@ out:
  */
 int ll_get_mdt_idx(struct inode *inode)
 {
-        struct ll_sb_info *sbi = ll_i2sbi(inode);
-        struct md_op_data *op_data;
-        int rc, mdtidx;
-        ENTRY;
-
-        op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0,
-                                     0, LUSTRE_OPC_ANY, NULL);
-        if (IS_ERR(op_data))
-                RETURN(PTR_ERR(op_data));
-
-       op_data->op_flags |= MF_GET_MDT_IDX;
-        rc = md_getattr(sbi->ll_md_exp, op_data, NULL);
-        mdtidx = op_data->op_mds;
-        ll_finish_md_op_data(op_data);
-        if (rc < 0) {
-                CDEBUG(D_INFO, "md_getattr_name: %d\n", rc);
-                RETURN(rc);
-        }
-        return mdtidx;
+       return ll_get_mdt_idx_by_fid(ll_i2sbi(inode), ll_inode2fid(inode));
 }
 
 /**
@@ -1087,6 +1116,22 @@ lmv_out_free:
                RETURN(rc);
 
        }
+       case LL_IOC_LMV_SET_DEFAULT_STRIPE: {
+               struct lmv_user_md        lum;
+               struct lmv_user_md __user *ulump =
+                                       (struct lmv_user_md __user *)arg;
+               int                       rc;
+
+               if (copy_from_user(&lum, ulump, sizeof(lum)))
+                       RETURN(-EFAULT);
+
+               if (lum.lum_magic != LMV_USER_MAGIC)
+                       RETURN(-EINVAL);
+
+               rc = ll_dir_setstripe(inode, (struct lov_user_md *)&lum, 0);
+
+               RETURN(rc);
+       }
         case LL_IOC_LOV_SETSTRIPE: {
                 struct lov_user_md_v3 lumv3;
                 struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3;
@@ -1116,41 +1161,96 @@ lmv_out_free:
                 RETURN(rc);
         }
        case LL_IOC_LMV_GETSTRIPE: {
-               struct lmv_user_md *lump = (struct lmv_user_md *)arg;
-               struct lmv_user_md lum;
-               struct lmv_user_md *tmp;
-               int lum_size;
-               int rc = 0;
-               int mdtindex;
-
-               if (copy_from_user(&lum, lump, sizeof(struct lmv_user_md)))
+               struct lmv_user_md __user *ulmv =
+                                       (struct lmv_user_md __user *)arg;
+               struct lmv_user_md      lum;
+               struct ptlrpc_request   *request = NULL;
+               union lmv_mds_md        *lmm = NULL;
+               int                     lmmsize;
+               obd_valid               valid = 0;
+               struct lmv_user_md      *tmp = NULL;
+               int                     mdt_index;
+               int                     lum_size;
+               int                     stripe_count;
+               int                     i;
+               int                     rc;
+
+               if (copy_from_user(&lum, ulmv, sizeof(*ulmv)))
                        RETURN(-EFAULT);
 
-               if (lum.lum_magic != LMV_MAGIC_V1)
+               /* lum_magic will indicate which stripe the ioctl will like
+                * to get, LMV_MAGIC_V1 is for normal LMV stripe, LMV_USER_MAGIC
+                * is for default LMV stripe */
+               if (lum.lum_magic == LMV_MAGIC_V1)
+                       valid |= OBD_MD_MEA;
+               else if (lum.lum_magic == LMV_USER_MAGIC)
+                       valid |= OBD_MD_DEFAULT_MEA;
+               else
                        RETURN(-EINVAL);
 
-               lum_size = lmv_user_md_size(1, LMV_MAGIC_V1);
+               rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, &request,
+                                     valid);
+               if (rc != 0 && rc != -ENODATA)
+                       GOTO(finish_req, rc);
+
+               /* Get default LMV EA */
+               if (lum.lum_magic == LMV_USER_MAGIC) {
+                       if (rc != 0)
+                               GOTO(finish_req, rc);
+
+                       if (lmmsize > sizeof(*ulmv))
+                               GOTO(finish_req, rc = -EINVAL);
+
+                       if (copy_to_user(ulmv, lmm, lmmsize))
+                               GOTO(finish_req, rc = -EFAULT);
+
+                       GOTO(finish_req, rc);
+               }
+
+               /* Get normal LMV EA */
+               if (rc == -ENODATA) {
+                       stripe_count = 1;
+               } else {
+                       LASSERT(lmm != NULL);
+                       stripe_count = lmv_mds_md_stripe_count_get(lmm);
+               }
+
+               lum_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1);
                OBD_ALLOC(tmp, lum_size);
                if (tmp == NULL)
-                       GOTO(free_lmv, rc = -ENOMEM);
+                       GOTO(finish_req, rc = -ENOMEM);
 
-               memcpy(tmp, &lum, sizeof(lum));
+               tmp->lum_magic = LMV_MAGIC_V1;
                tmp->lum_stripe_count = 1;
-               mdtindex = ll_get_mdt_idx(inode);
-               if (mdtindex < 0)
-                       GOTO(free_lmv, rc = -ENOMEM);
-
-               tmp->lum_stripe_offset = mdtindex;
-               tmp->lum_objects[0].lum_mds = mdtindex;
-               memcpy(&tmp->lum_objects[0].lum_fid, ll_inode2fid(inode),
-                      sizeof(struct lu_fid));
-               if (copy_to_user((void *)arg, tmp, lum_size))
-                       GOTO(free_lmv, rc = -EFAULT);
-free_lmv:
-               if (tmp)
-                       OBD_FREE(tmp, lum_size);
-               RETURN(rc);
+               mdt_index = ll_get_mdt_idx(inode);
+               if (mdt_index < 0)
+                       GOTO(out_tmp, rc = -ENOMEM);
+               tmp->lum_stripe_offset = mdt_index;
+               tmp->lum_objects[0].lum_mds = mdt_index;
+               tmp->lum_objects[0].lum_fid = *ll_inode2fid(inode);
+               for (i = 1; i < stripe_count; i++) {
+                       struct lmv_mds_md_v1 *lmm1;
+
+                       lmm1 = &lmm->lmv_md_v1;
+                       mdt_index = ll_get_mdt_idx_by_fid(sbi,
+                                                    &lmm1->lmv_stripe_fids[i]);
+                       if (mdt_index < 0)
+                               GOTO(out_tmp, rc = mdt_index);
+
+                       tmp->lum_objects[i].lum_mds = mdt_index;
+                       tmp->lum_objects[i].lum_fid = lmm1->lmv_stripe_fids[i];
+                       tmp->lum_stripe_count++;
+               }
+
+               if (copy_to_user(ulmv, tmp, lum_size))
+                       GOTO(out_tmp, rc = -EFAULT);
+out_tmp:
+               OBD_FREE(tmp, lum_size);
+finish_req:
+               ptlrpc_req_finished(request);
+               return rc;
        }
+
        case LL_IOC_REMOVE_ENTRY: {
                char            *filename = NULL;
                int              namelen = 0;
@@ -1201,9 +1301,10 @@ out_rmdir:
 
                         rc = ll_lov_getstripe_ea_info(inode, filename, &lmm,
                                                       &lmmsize, &request);
-                } else {
-                        rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
-                }
+               } else {
+                       rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize,
+                                             &request, 0);
+               }
 
                 if (request) {
                         body = req_capsule_server_get(&request->rq_pill,