Whamcloud - gitweb
LU-2482 layout: introduce new layout for released files
authorJinshan Xiong <jinshan.xiong@intel.com>
Wed, 29 May 2013 17:55:55 +0000 (10:55 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 7 Jun 2013 04:29:40 +0000 (00:29 -0400)
Released files now have a standard layout (with generation, pool, ...)
and a stripe count 0 and lmm_pattern flag LOV_PATTERN_F_RELEASED.

Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com>
Signed-off-by: Johann Lombardi <johann.lombardi@intel.com>
Change-Id: Id2c3b95fdd304f803d391281a86927f5c93cb3b4
Reviewed-on: http://review.whamcloud.com/4816
Reviewed-by: Keith Mannthey <keith.mannthey@intel.com>
Tested-by: Hudson
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
20 files changed:
lustre/include/lustre/lustre_idl.h
lustre/include/obd.h
lustre/lclient/lcommon_cl.c
lustre/llite/file.c
lustre/llite/llite_lib.c
lustre/llite/vvp_io.c
lustre/lod/lod_internal.h
lustre/lod/lod_lov.c
lustre/lod/lod_object.c
lustre/lod/lod_qos.c
lustre/lov/lov_cl_internal.h
lustre/lov/lov_ea.c
lustre/lov/lov_io.c
lustre/lov/lov_obd.c
lustre/lov/lov_object.c
lustre/lov/lov_pack.c
lustre/mdt/mdt_lib.c
lustre/tests/multiop.c
lustre/tests/sanity.sh
lustre/utils/liblustreapi.c

index 5ad9f21..b9fd5a7 100644 (file)
@@ -1550,10 +1550,16 @@ enum obdo_flags {
 #define LOV_MAGIC_V1_DEF  0x0CD10BD0
 #define LOV_MAGIC_V3_DEF  0x0CD30BD0
 
-#define LOV_PATTERN_RAID0 0x001   /* stripes are used round-robin */
-#define LOV_PATTERN_RAID1 0x002   /* stripes are mirrors of each other */
-#define LOV_PATTERN_FIRST 0x100   /* first stripe is not in round-robin */
-#define LOV_PATTERN_CMOBD 0x200
+#define LOV_PATTERN_RAID0      0x001   /* stripes are used round-robin */
+#define LOV_PATTERN_RAID1      0x002   /* stripes are mirrors of each other */
+#define LOV_PATTERN_FIRST      0x100   /* first stripe is not in round-robin */
+#define LOV_PATTERN_CMOBD      0x200
+
+#define LOV_PATTERN_F_MASK     0xffff0000
+#define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */
+
+#define lov_pattern(pattern)           (pattern & ~LOV_PATTERN_F_MASK)
+#define lov_pattern_flags(pattern)     (pattern & LOV_PATTERN_F_MASK)
 
 #define lov_ost_data lov_ost_data_v1
 struct lov_ost_data_v1 {          /* per-stripe data structure (little-endian)*/
index 289b1bc..b208efd 100644 (file)
@@ -130,6 +130,20 @@ struct lov_stripe_md {
 #define lsm_stripe_count lsm_wire.lw_stripe_count
 #define lsm_pool_name    lsm_wire.lw_pool_name
 
+static inline bool lsm_is_released(struct lov_stripe_md *lsm)
+{
+       return !!(lsm->lsm_pattern & LOV_PATTERN_F_RELEASED);
+}
+
+static inline bool lsm_has_objects(struct lov_stripe_md *lsm)
+{
+       if (lsm == NULL)
+               return false;
+       if (lsm_is_released(lsm))
+               return false;
+       return true;
+}
+
 struct obd_info;
 
 typedef int (*obd_enqueue_update_f)(void *cookie, int rc);
index 27b5bb8..bc97877 100644 (file)
@@ -1186,7 +1186,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md)
                          * locked by I_NEW bit.
                          */
                         lli->lli_clob = clob;
-                       lli->lli_has_smd = md->lsm != NULL;
+                       lli->lli_has_smd = lsm_has_objects(md->lsm);
                         lu_object_ref_add(&clob->co_lu, "inode", inode);
                 } else
                         result = PTR_ERR(clob);
index 2947f4b..a5d5f05 100644 (file)
@@ -1278,7 +1278,7 @@ static int ll_lov_recreate(struct inode *inode, struct ost_id *oi,
                RETURN(-ENOMEM);
 
        lsm = ccc_inode_lsm_get(inode);
-        if (lsm == NULL)
+       if (!lsm_has_objects(lsm))
                 GOTO(out, rc = -ENOENT);
 
         lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) *
@@ -1434,6 +1434,12 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
          * passing it to userspace.
          */
         if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) {
+               int stripe_count;
+
+               stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
+               if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
+                       stripe_count = 0;
+
                 /* if function called for directory - we should
                  * avoid swab not existent lsm objects */
                 if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) {
@@ -1441,13 +1447,13 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
                         if (S_ISREG(body->mode))
                                 lustre_swab_lov_user_md_objects(
                                  ((struct lov_user_md_v1 *)lmm)->lmm_objects,
-                                 ((struct lov_user_md_v1 *)lmm)->lmm_stripe_count);
+                                 stripe_count);
                 } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) {
                         lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm);
                         if (S_ISREG(body->mode))
                                 lustre_swab_lov_user_md_objects(
                                  ((struct lov_user_md_v3 *)lmm)->lmm_objects,
-                                 ((struct lov_user_md_v3 *)lmm)->lmm_stripe_count);
+                                 stripe_count);
                 }
         }
 
@@ -1833,20 +1839,18 @@ int ll_data_version(struct inode *inode, __u64 *data_version,
 
        /* If no stripe, we consider version is 0. */
        lsm = ccc_inode_lsm_get(inode);
-       if (lsm == NULL) {
+       if (!lsm_has_objects(lsm)) {
                *data_version = 0;
                CDEBUG(D_INODE, "No object for inode\n");
-               RETURN(0);
+               GOTO(out, rc = 0);
        }
 
        OBD_ALLOC_PTR(obdo);
-       if (obdo == NULL) {
-               ccc_inode_lsm_put(inode, lsm);
-               RETURN(-ENOMEM);
-       }
+       if (obdo == NULL)
+               GOTO(out, rc = -ENOMEM);
 
        rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, NULL, obdo, 0, extent_lock);
-       if (!rc) {
+       if (rc == 0) {
                if (!(obdo->o_valid & OBD_MD_FLDATAVERSION))
                        rc = -EOPNOTSUPP;
                else
@@ -1854,8 +1858,9 @@ int ll_data_version(struct inode *inode, __u64 *data_version,
        }
 
        OBD_FREE_PTR(obdo);
+       EXIT;
+out:
        ccc_inode_lsm_put(inode, lsm);
-
        RETURN(rc);
 }
 
index 01ddfd2..e6adb42 100644 (file)
@@ -1305,13 +1305,6 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
                 RETURN(rc);
         }
 
-       ia_valid = op_data->op_attr.ia_valid;
-       /* inode size will be in ll_setattr_ost, can't do it now since dirty
-        * cache is not cleared yet. */
-       op_data->op_attr.ia_valid &= ~(TIMES_SET_FLAGS | ATTR_SIZE);
-       rc = simple_setattr(dentry, &op_data->op_attr);
-       op_data->op_attr.ia_valid = ia_valid;
-
         /* Extract epoch data if obtained. */
         op_data->op_handle = md.body->handle;
         op_data->op_ioepoch = md.body->ioepoch;
@@ -1437,6 +1430,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
         struct ll_inode_info *lli = ll_i2info(inode);
         struct md_op_data *op_data = NULL;
         struct md_open_data *mod = NULL;
+       unsigned int valid = attr->ia_valid;
         int rc = 0, rc1 = 0;
         ENTRY;
 
@@ -1548,6 +1542,13 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
                 rc = ll_setattr_ost(inode, attr);
         EXIT;
 out:
+       if (rc == 0) {
+               /* Update inode attribute after dirty cache is cleaned
+                * by truncating OST objects. */
+               attr->ia_valid |= ATTR_FORCE;
+               rc = simple_setattr(dentry, attr);
+               LASSERT(rc == 0);
+       }
         if (op_data) {
                 if (op_data->op_ioepoch) {
                         rc1 = ll_setattr_done_writing(inode, op_data, mod);
@@ -1566,7 +1567,8 @@ out:
        ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ?
                        LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1);
 
-       return rc;
+       attr->ia_valid = valid;
+       RETURN(rc);
 }
 
 int ll_setattr(struct dentry *de, struct iattr *attr)
@@ -1991,8 +1993,10 @@ int ll_iocontrol(struct inode *inode, struct file *file,
                inode->i_flags = ll_ext_to_inode_flags(flags);
 
                lsm = ccc_inode_lsm_get(inode);
-               if (lsm == NULL)
+               if (!lsm_has_objects(lsm)) {
+                       ccc_inode_lsm_put(inode, lsm);
                        RETURN(0);
+               }
 
                OBDO_ALLOC(oinfo.oi_oa);
                if (!oinfo.oi_oa) {
index e7ca14e..562c875 100644 (file)
@@ -406,13 +406,15 @@ static int vvp_io_setattr_start(const struct lu_env *env,
 {
        struct cl_io    *io    = ios->cis_io;
        struct inode    *inode = ccc_object_inode(io->ci_obj);
+       int result = 0;
 
        mutex_lock(&inode->i_mutex);
        if (cl_io_is_trunc(io))
-               return vvp_io_setattr_trunc(env, ios, inode,
-                                           io->u.ci_setattr.sa_attr.lvb_size);
-       else
-               return vvp_io_setattr_time(env, ios);
+               result = vvp_io_setattr_trunc(env, ios, inode,
+                                       io->u.ci_setattr.sa_attr.lvb_size);
+       if (result == 0)
+               result = vvp_io_setattr_time(env, ios);
+       return result;
 }
 
 static void vvp_io_setattr_end(const struct lu_env *env,
index 2661c40..0dd077b 100644 (file)
@@ -151,6 +151,8 @@ struct lod_object {
        __u16              ldo_stripenr;
        __u16              ldo_layout_gen;
        __u32              ldo_stripe_size;
+       __u32              ldo_pattern;
+       __u16              ldo_released_stripenr;
        char              *ldo_pool;
        struct dt_object **ldo_stripe;
        /* to know how much memory to free, ldo_stripenr can be less */
index 5426554..cc70895 100644 (file)
@@ -504,9 +504,8 @@ int lod_generate_and_set_lovea(const struct lu_env *env,
        ENTRY;
 
        LASSERT(lo);
-       LASSERT(lo->ldo_stripenr > 0);
 
-       magic = lo->ldo_pool ? LOV_MAGIC_V3 : LOV_MAGIC_V1;
+       magic = lo->ldo_pool != NULL ? LOV_MAGIC_V3 : LOV_MAGIC_V1;
        lmm_size = lov_mds_md_size(lo->ldo_stripenr, magic);
        if (info->lti_ea_store_size < lmm_size) {
                rc = lod_ea_store_resize(info, lmm_size);
@@ -514,14 +513,19 @@ int lod_generate_and_set_lovea(const struct lu_env *env,
                        RETURN(rc);
        }
 
+       if (lo->ldo_pattern == 0) /* default striping */
+               lo->ldo_pattern = LOV_PATTERN_RAID0;
+
        lmm = info->lti_ea_store;
 
        lmm->lmm_magic = cpu_to_le32(magic);
-       lmm->lmm_pattern = cpu_to_le32(LOV_PATTERN_RAID0);
+       lmm->lmm_pattern = cpu_to_le32(lo->ldo_pattern);
        fid_to_lmm_oi(fid, &lmm->lmm_oi);
        lmm_oi_cpu_to_le(&lmm->lmm_oi, &lmm->lmm_oi);
        lmm->lmm_stripe_size = cpu_to_le32(lo->ldo_stripe_size);
        lmm->lmm_stripe_count = cpu_to_le16(lo->ldo_stripenr);
+       if (lo->ldo_pattern & LOV_PATTERN_F_RELEASED)
+               lmm->lmm_stripe_count = cpu_to_le16(lo->ldo_released_stripenr);
        lmm->lmm_layout_gen = 0;
        if (magic == LOV_MAGIC_V1) {
                objs = &lmm->lmm_objects[0];
@@ -678,7 +682,7 @@ int lod_initialize_objects(const struct lu_env *env, struct lod_object *lo,
        int                      i, idx, rc = 0;
        ENTRY;
 
-       LASSERT(lo);
+       LASSERT(lo != NULL);
        LASSERT(lo->ldo_stripe == NULL);
        LASSERT(lo->ldo_stripenr > 0);
        LASSERT(lo->ldo_stripe_size > 0);
@@ -746,6 +750,7 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo,
        struct lov_mds_md_v1    *lmm;
        struct lov_ost_data_v1  *objs;
        __u32                    magic;
+       __u32                    pattern;
        int                      rc = 0;
        ENTRY;
 
@@ -755,15 +760,20 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo,
 
        lmm = (struct lov_mds_md_v1 *) buf->lb_buf;
        magic = le32_to_cpu(lmm->lmm_magic);
+       pattern = le32_to_cpu(lmm->lmm_pattern);
 
        if (magic != LOV_MAGIC_V1 && magic != LOV_MAGIC_V3)
                GOTO(out, rc = -EINVAL);
-       if (le32_to_cpu(lmm->lmm_pattern) != LOV_PATTERN_RAID0)
+       if (lov_pattern(pattern) != LOV_PATTERN_RAID0)
                GOTO(out, rc = -EINVAL);
 
+       lo->ldo_pattern = pattern;
        lo->ldo_stripe_size = le32_to_cpu(lmm->lmm_stripe_size);
-       lo->ldo_stripenr = le16_to_cpu(lmm->lmm_stripe_count);
        lo->ldo_layout_gen = le16_to_cpu(lmm->lmm_layout_gen);
+       lo->ldo_stripenr = le16_to_cpu(lmm->lmm_stripe_count);
+       /* released file stripenr fixup. */
+       if (pattern & LOV_PATTERN_F_RELEASED)
+               lo->ldo_stripenr = 0;
 
        LASSERT(buf->lb_len >= lov_mds_md_size(lo->ldo_stripenr, magic));
 
@@ -775,7 +785,8 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo,
                objs = &lmm->lmm_objects[0];
        }
 
-       rc = lod_initialize_objects(env, lo, objs);
+       if (lo->ldo_stripenr > 0)
+               rc = lod_initialize_objects(env, lo, objs);
 
 out:
        RETURN(rc);
index 787e461..9eeda28 100644 (file)
@@ -962,8 +962,6 @@ int lod_striping_create(const struct lu_env *env, struct dt_object *dt,
        int                rc = 0, i;
        ENTRY;
 
-       LASSERT(lo->ldo_stripe);
-       LASSERT(lo->ldo_stripenr > 0);
        LASSERT(lo->ldo_striping_cached == 0);
 
        /* create all underlying objects */
@@ -1235,6 +1233,7 @@ void lod_object_free_striping(const struct lu_env *env, struct lod_object *lo)
                lo->ldo_stripes_allocated = 0;
        }
        lo->ldo_stripenr = 0;
+       lo->ldo_pattern = 0;
 }
 
 /*
index fa7eed8..8a4d1bb 100644 (file)
@@ -1233,6 +1233,7 @@ static int lod_use_defined_striping(const struct lu_env *env,
                GOTO(out, rc = -EINVAL);
        }
 
+       mo->ldo_pattern = le32_to_cpu(v1->lmm_pattern);
        mo->ldo_stripe_size = le32_to_cpu(v1->lmm_stripe_size);
        mo->ldo_stripenr = le16_to_cpu(v1->lmm_stripe_count);
        mo->ldo_layout_gen = le16_to_cpu(v1->lmm_layout_gen);
@@ -1282,10 +1283,14 @@ static int lod_qos_parse_config(const struct lu_env *env,
                RETURN(-EINVAL);
        }
 
-       if (v1->lmm_pattern != 0 && v1->lmm_pattern != LOV_PATTERN_RAID0) {
+       v1->lmm_magic = magic;
+       if (v1->lmm_pattern == 0)
+               v1->lmm_pattern = LOV_PATTERN_RAID0;
+       if (lov_pattern(v1->lmm_pattern) != LOV_PATTERN_RAID0) {
                CERROR("invalid pattern: %x\n", v1->lmm_pattern);
                RETURN(-EINVAL);
        }
+       lo->ldo_pattern = v1->lmm_pattern;
 
        if (v1->lmm_stripe_size)
                lo->ldo_stripe_size = v1->lmm_stripe_size;
@@ -1339,6 +1344,12 @@ static int lod_qos_parse_config(const struct lu_env *env,
        } else
                lod_object_set_pool(lo, NULL);
 
+       /* fixup for released file */
+       if (lo->ldo_pattern & LOV_PATTERN_F_RELEASED) {
+               lo->ldo_released_stripenr = lo->ldo_stripenr;
+               lo->ldo_stripenr = 0;
+       }
+
        RETURN(0);
 }
 
@@ -1376,6 +1387,10 @@ int lod_qos_prep_create(const struct lu_env *env, struct lod_object *lo,
        if (rc)
                GOTO(out, rc);
 
+       /* A released file is being created */
+       if (lo->ldo_stripenr == 0)
+               GOTO(out, rc = 0);
+
        if (likely(lo->ldo_stripe == NULL)) {
                /*
                 * no striping has been created so far
index 13c2f5a..61ee850 100644 (file)
@@ -166,11 +166,10 @@ struct lov_device {
  * Layout type.
  */
 enum lov_layout_type {
-        /** empty file without body */
-        LLT_EMPTY,
-        /** striped file */
-        LLT_RAID0,
-        LLT_NR
+       LLT_EMPTY,      /** empty file without body (mknod + truncate) */
+       LLT_RAID0,      /** striped file */
+       LLT_RELEASED,   /** file with no objects (data in HSM) */
+       LLT_NR
 };
 
 /**
@@ -259,6 +258,8 @@ struct lov_object {
                 } raid0;
                 struct lov_layout_state_empty {
                 } empty;
+               struct lov_layout_state_released {
+               } released;
         } u;
         /**
          * Thread that acquired lov_object::lo_type_guard in an exclusive
@@ -586,6 +587,8 @@ int   lov_io_init_raid0   (const struct lu_env *env, struct cl_object *obj,
                            struct cl_io *io);
 int   lov_io_init_empty   (const struct lu_env *env, struct cl_object *obj,
                            struct cl_io *io);
+int   lov_io_init_released(const struct lu_env *env, struct cl_object *obj,
+                           struct cl_io *io);
 void  lov_lock_unlink     (const struct lu_env *env, struct lov_lock_link *link,
                            struct lovsub_lock *sub);
 
index af18014..bf6d9eb 100644 (file)
@@ -61,7 +61,7 @@ struct lovea_unpack_args {
 static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes,
                                  __u16 stripe_count)
 {
-       if (stripe_count == 0 || stripe_count > LOV_V1_INSANE_STRIPE_COUNT) {
+       if (stripe_count > LOV_V1_INSANE_STRIPE_COUNT) {
                CERROR("bad stripe count %d\n", stripe_count);
                lov_dump_lmm_common(D_WARNING, lmm);
                return -EINVAL;
@@ -73,7 +73,7 @@ static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes,
                return -EINVAL;
        }
 
-       if (lmm->lmm_pattern != cpu_to_le32(LOV_PATTERN_RAID0)) {
+       if (lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_RAID0) {
                CERROR("bad striping pattern\n");
                lov_dump_lmm_common(D_WARNING, lmm);
                return -EINVAL;
@@ -201,6 +201,8 @@ static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes,
        }
 
        *stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
+       if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
+               *stripe_count = 0;
 
        if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)) {
                CERROR("LOV EA V1 too small: %d, need %d\n",
@@ -217,11 +219,14 @@ int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
 {
         struct lov_oinfo *loi;
         int i;
+       int stripe_count;
         __u64 stripe_maxbytes = OBD_OBJECT_EOF;
 
         lsm_unpackmd_common(lsm, lmm);
 
-       for (i = 0; i < lsm->lsm_stripe_count; i++) {
+       stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count;
+
+       for (i = 0; i < stripe_count; i++) {
                /* XXX LOV STACKING call down to osc_unpackmd() */
                loi = lsm->lsm_oinfo[i];
                ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
@@ -243,9 +248,11 @@ int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
                                  &stripe_maxbytes);
         }
 
-        lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count;
+       lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count;
+       if (lsm->lsm_stripe_count == 0)
+               lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count;
 
-        return 0;
+       return 0;
 }
 
 const struct lsm_operations lsm_v1_ops = {
@@ -271,6 +278,8 @@ static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes,
        }
 
        *stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
+       if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
+               *stripe_count = 0;
 
        if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)) {
                CERROR("LOV EA V3 too small: %d, need %d\n",
@@ -289,18 +298,22 @@ int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
         struct lov_mds_md_v3 *lmm;
         struct lov_oinfo *loi;
         int i;
+       int stripe_count;
         __u64 stripe_maxbytes = OBD_OBJECT_EOF;
        int cplen = 0;
 
         lmm = (struct lov_mds_md_v3 *)lmmv1;
 
         lsm_unpackmd_common(lsm, (struct lov_mds_md_v1 *)lmm);
+
+       stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count;
+
        cplen = strlcpy(lsm->lsm_pool_name, lmm->lmm_pool_name,
                        sizeof(lsm->lsm_pool_name));
        if (cplen >= sizeof(lsm->lsm_pool_name))
                return -E2BIG;
 
-        for (i = 0; i < lsm->lsm_stripe_count; i++) {
+        for (i = 0; i < stripe_count; i++) {
                 /* XXX LOV STACKING call down to osc_unpackmd() */
                 loi = lsm->lsm_oinfo[i];
                ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
@@ -322,9 +335,11 @@ int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
                                  &stripe_maxbytes);
         }
 
-        lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count;
+       lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count;
+       if (lsm->lsm_stripe_count == 0)
+               lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count;
 
-        return 0;
+       return 0;
 }
 
 const struct lsm_operations lsm_v3_ops = {
index 76b0901..6f6ea84 100644 (file)
@@ -968,4 +968,38 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
        RETURN(result != 0);
 }
 
+int lov_io_init_released(const struct lu_env *env, struct cl_object *obj,
+                       struct cl_io *io)
+{
+       struct lov_object *lov = cl2lov(obj);
+       struct lov_io *lio = lov_env_io(env);
+       int result;
+       ENTRY;
+
+       LASSERT(lov->lo_lsm != NULL);
+       lio->lis_object = lov;
+
+       switch (io->ci_type) {
+       default:
+               LASSERTF(0, "invalid type %d\n", io->ci_type);
+       case CIT_MISC:
+       case CIT_FSYNC:
+       case CIT_SETATTR:
+               result = +1;
+               break;
+       case CIT_READ:
+       case CIT_WRITE:
+       case CIT_FAULT:
+               /* TODO: need to restore the file. */
+               result = -EBADF;
+               break;
+       }
+       if (result == 0) {
+               cl_io_slice_add(io, &lio->lis_cl, obj, &lov_empty_io_ops);
+               cfs_atomic_inc(&lov->lo_active_ios);
+       }
+
+       io->ci_result = result < 0 ? result : 0;
+       RETURN(result != 0);
+}
 /** @} lov */
index 9c75cb3..5843bca 100644 (file)
@@ -2276,7 +2276,7 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key,
         int cur_stripe = 0, cur_stripe_wrap = 0, stripe_count;
         unsigned int buffer_size = FIEMAP_BUFFER_SIZE;
 
-        if (lsm == NULL)
+       if (!lsm_has_objects(lsm))
                 GOTO(out, rc = 0);
 
         if (fiemap_count_to_size(fm_key->fiemap.fm_extent_count) < buffer_size)
index 07ed284..e1f5b5d 100644 (file)
@@ -258,10 +258,25 @@ out:
         RETURN(result);
 }
 
+static int lov_init_released(const struct lu_env *env,
+                       struct lov_device *dev, struct lov_object *lov,
+                       const struct cl_object_conf *conf,
+                       union  lov_layout_state *state)
+{
+       struct lov_stripe_md *lsm = conf->u.coc_md->lsm;
+
+       LASSERT(lsm != NULL);
+       LASSERT(lsm_is_released(lsm));
+       LASSERT(lov->lo_lsm == NULL);
+
+       lov->lo_lsm = lsm_addref(lsm);
+       return 0;
+}
+
 static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov,
                            union lov_layout_state *state)
 {
-       LASSERT(lov->lo_type == LLT_EMPTY);
+       LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED);
 
        lov_layout_wait(env, lov);
 
@@ -349,7 +364,7 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov,
 static void lov_fini_empty(const struct lu_env *env, struct lov_object *lov,
                            union lov_layout_state *state)
 {
-        LASSERT(lov->lo_type == LLT_EMPTY);
+       LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED);
 }
 
 static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov,
@@ -369,6 +384,15 @@ static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov,
        EXIT;
 }
 
+static void lov_fini_released(const struct lu_env *env, struct lov_object *lov,
+                               union lov_layout_state *state)
+{
+       ENTRY;
+       dump_lsm(D_INODE, lov->lo_lsm);
+       lov_free_memmd(&lov->lo_lsm);
+       EXIT;
+}
+
 static int lov_print_empty(const struct lu_env *env, void *cookie,
                            lu_printer_t p, const struct lu_object *o)
 {
@@ -400,6 +424,13 @@ static int lov_print_raid0(const struct lu_env *env, void *cookie,
         return 0;
 }
 
+static int lov_print_released(const struct lu_env *env, void *cookie,
+                               lu_printer_t p, const struct lu_object *o)
+{
+       (*p)(env, cookie, "released\n");
+       return 0;
+}
+
 /**
  * Implements cl_object_operations::coo_attr_get() method for an object
  * without stripes (LLT_EMPTY layout type).
@@ -503,10 +534,20 @@ const static struct lov_layout_operations lov_dispatch[] = {
                 .llo_lock_init = lov_lock_init_raid0,
                 .llo_io_init   = lov_io_init_raid0,
                 .llo_getattr   = lov_attr_get_raid0
+       },
+        [LLT_RELEASED] = {
+                .llo_init      = lov_init_released,
+                .llo_delete    = lov_delete_empty,
+                .llo_fini      = lov_fini_released,
+                .llo_install   = lov_install_empty,
+                .llo_print     = lov_print_released,
+                .llo_page_init = lov_page_init_empty,
+                .llo_lock_init = lov_lock_init_empty,
+                .llo_io_init   = lov_io_init_released,
+                .llo_getattr   = lov_attr_get_empty
         }
 };
 
-
 /**
  * Performs a double-dispatch based on the layout type of an object.
  */
@@ -520,6 +561,18 @@ const static struct lov_layout_operations lov_dispatch[] = {
         lov_dispatch[__llt].op(__VA_ARGS__);                            \
 })
 
+/**
+ * Return lov_layout_type associated with a given lsm
+ */
+enum lov_layout_type lov_type(struct lov_stripe_md *lsm)
+{
+       if (lsm == NULL)
+               return LLT_EMPTY;
+       if (lsm_is_released(lsm))
+               return LLT_RELEASED;
+       return LLT_RAID0;
+}
+
 static inline void lov_conf_freeze(struct lov_object *lov)
 {
        if (lov->lo_owner != cfs_current())
@@ -612,8 +665,8 @@ static int lov_layout_change(const struct lu_env *unused,
 
        LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch));
 
-       if (conf->u.coc_md != NULL && conf->u.coc_md->lsm != NULL)
-               llt = LLT_RAID0; /* only raid0 is supported. */
+       if (conf->u.coc_md != NULL)
+               llt = lov_type(conf->u.coc_md->lsm);
        LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch));
 
        cookie = cl_env_reenter();
@@ -658,7 +711,6 @@ static int lov_layout_change(const struct lu_env *unused,
  * Lov object operations.
  *
  */
-
 int lov_object_init(const struct lu_env *env, struct lu_object *obj,
                     const struct lu_object_conf *conf)
 {
@@ -677,7 +729,7 @@ int lov_object_init(const struct lu_env *env, struct lu_object *obj,
        cl_object_page_init(lu2cl(obj), sizeof(struct lov_page));
 
         /* no locking is necessary, as object is being created */
-        lov->lo_type = cconf->u.coc_md->lsm != NULL ? LLT_RAID0 : LLT_EMPTY;
+       lov->lo_type = lov_type(cconf->u.coc_md->lsm);
         ops = &lov_dispatch[lov->lo_type];
         result = ops->llo_init(env, dev, lov, cconf, set);
         if (result == 0)
@@ -688,9 +740,9 @@ int lov_object_init(const struct lu_env *env, struct lu_object *obj,
 static int lov_conf_set(const struct lu_env *env, struct cl_object *obj,
                         const struct cl_object_conf *conf)
 {
-       struct lov_stripe_md *lsm = NULL;
-       struct lov_object *lov = cl2lov(obj);
-       int result = 0;
+       struct lov_stripe_md    *lsm = NULL;
+       struct lov_object       *lov = cl2lov(obj);
+       int                      result = 0;
        ENTRY;
 
        lov_conf_lock(lov);
@@ -928,6 +980,7 @@ int lov_read_and_clear_async_rc(struct cl_object *clob)
                                loi->loi_ar.ar_rc = 0;
                        }
                }
+               case LLT_RELEASED:
                case LLT_EMPTY:
                        break;
                default:
index 47e0127..282b184 100644 (file)
@@ -169,13 +169,15 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
         if (lsm) {
                 /* If we are just sizing the EA, limit the stripe count
                  * to the actual number of OSTs in this filesystem. */
-                if (!lmmp) {
-                        stripe_count = lov_get_stripecnt(lov, lmm_magic,
-                                                         lsm->lsm_stripe_count);
-                        lsm->lsm_stripe_count = stripe_count;
-                } else {
-                        stripe_count = lsm->lsm_stripe_count;
-                }
+               if (!lmmp) {
+                       stripe_count = lov_get_stripecnt(lov, lmm_magic,
+                                                       lsm->lsm_stripe_count);
+                       lsm->lsm_stripe_count = stripe_count;
+               } else if (!lsm_is_released(lsm)) {
+                       stripe_count = lsm->lsm_stripe_count;
+               } else {
+                       stripe_count = 0;
+               }
         } else {
                 /* No need to allocate more than maximum supported stripes.
                  * Anyway, this is pretty inaccurate since ld_tgt_count now
@@ -328,7 +330,8 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count,
         (*lsmp)->lsm_pattern = pattern;
         (*lsmp)->lsm_pool_name[0] = '\0';
         (*lsmp)->lsm_layout_gen = 0;
-        (*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0;
+       if (stripe_count > 0)
+               (*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0;
 
         for (i = 0; i < stripe_count; i++)
                 loi_init((*lsmp)->lsm_oinfo[i]);
@@ -362,6 +365,7 @@ int lov_unpackmd(struct obd_export *exp,  struct lov_stripe_md **lsmp,
         int rc = 0, lsm_size;
         __u16 stripe_count;
         __u32 magic;
+       __u32 pattern;
         ENTRY;
 
         /* If passed an MDS struct use values from there, otherwise defaults */
@@ -387,8 +391,8 @@ int lov_unpackmd(struct obd_export *exp,  struct lov_stripe_md **lsmp,
                 RETURN(0);
         }
 
-        lsm_size = lov_alloc_memmd(lsmp, stripe_count, LOV_PATTERN_RAID0,
-                                   magic);
+       pattern = le32_to_cpu(lmm->lmm_pattern);
+        lsm_size = lov_alloc_memmd(lsmp, stripe_count, pattern, magic);
         if (lsm_size < 0)
                 RETURN(lsm_size);
 
@@ -433,7 +437,7 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
                         lov->desc.ld_pattern : LOV_PATTERN_RAID0;
         }
 
-        if (lumv1->lmm_pattern != LOV_PATTERN_RAID0) {
+        if (lov_pattern(lumv1->lmm_pattern) != LOV_PATTERN_RAID0) {
                 CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n",
                        lumv1->lmm_pattern);
                 RETURN(-EINVAL);
@@ -493,6 +497,9 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
                 }
         }
 
+       if (lumv1->lmm_pattern & LOV_PATTERN_F_RELEASED)
+               stripe_count = 0;
+
         rc = lov_alloc_memmd(lsmp, stripe_count, lumv1->lmm_pattern, lmm_magic);
 
         if (rc >= 0) {
index 6283f66..4eec5f2 100644 (file)
@@ -542,7 +542,8 @@ void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
               le32_to_cpu(lmm->lmm_pattern));
         CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
                le32_to_cpu(lmm->lmm_stripe_size), count);
-        if (count == LOV_ALL_STRIPES)
+        if (count == LOV_ALL_STRIPES ||
+           le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
                 return;
 
        LASSERT(count <= LOV_MAX_STRIPE_COUNT);
index b1a157d..541e1b0 100644 (file)
@@ -320,6 +320,17 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
+               case 'H':
+                       len = atoi(commands+1);
+                       fd = llapi_file_open(fname, O_CREAT | O_WRONLY,
+                               0644, 0, 0, len,
+                               LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED);
+                       if (fd == -1) {
+                               save_errno = errno;
+                               perror("create stripe file");
+                               exit(save_errno);
+                       }
+                       break;
                case 'K':
                        oldpath = POP_ARG();
                        if (oldpath == NULL)
index f3de47f..39b1138 100644 (file)
@@ -11129,6 +11129,34 @@ test_228c() {
 }
 run_test 228c "NOT shrink the last entry in OI index node to recycle idle leaf"
 
+test_229() { # LU-2482
+       [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
+
+       # Create a file with a release layout (stripe count = 0)
+       $MULTIOP $DIR/$tfile H2c ||
+               error "failed to create file w. released layout"
+
+       $GETSTRIPE -v $DIR/$tfile
+
+       local pattern=$($GETSTRIPE -v $DIR/$tfile |
+                       grep lmm_stripe_pattern | awk '{print $2}')
+       [ X"$pattern" = X"80000001" ] || error "pattern error ($pattern)"
+
+       local stripe_count=$($GETSTRIPE -c $DIR/$tfile) || error "getstripe"
+       [ $stripe_count -eq 2 ] || error "stripe count not 2 ($stripe_count)"
+       stat $DIR/$tfile || error "failed to stat released file"
+
+       $TRUNCATE $DIR/$tfile 200000
+       $CHECKSTAT -s 200000 $DIR/$tfile || error
+
+       # Stripe count should be no change after truncate
+       stripe_count=$($GETSTRIPE -c $DIR/$tfile) || error "getstripe failed"
+       [ $stripe_count -eq 2 ] || error "after trunc: ($stripe_count)"
+
+       rm $DIR/$tfile || error "failed to remove released file"
+}
+run_test 229 "getstripe/stat/rm work on released files (stripe count = 0)"
+
 test_230a() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
index 5e76bca..155f5c3 100644 (file)
@@ -2244,7 +2244,8 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name,
                 lov_dump_user_lmm_header(lum, path, objects, is_dir, header,
                                          depth, raw, pool_name);
 
-        if (!is_dir && (header & VERBOSE_OBJID)) {
+        if (!is_dir && (header & VERBOSE_OBJID) &&
+           !(lum->lmm_pattern & LOV_PATTERN_F_RELEASED)) {
                 if (obdstripe == 1)
                         llapi_printf(LLAPI_MSG_NORMAL,
                                   "\tobdidx\t\t objid\t\t objid\t\t group\n");