From: Jinshan Xiong Date: Wed, 29 May 2013 17:55:55 +0000 (-0700) Subject: LU-2482 layout: introduce new layout for released files X-Git-Tag: 2.4.51~36 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=a61ff5914bf6b784b22eea0625bb8b61d7bea950 LU-2482 layout: introduce new layout for released files 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 Signed-off-by: Johann Lombardi Change-Id: Id2c3b95fdd304f803d391281a86927f5c93cb3b4 Reviewed-on: http://review.whamcloud.com/4816 Reviewed-by: Keith Mannthey Tested-by: Hudson Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Tested-by: Maloo --- diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index 5ad9f21..b9fd5a7 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -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)*/ diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 289b1bc..b208efd 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -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); diff --git a/lustre/lclient/lcommon_cl.c b/lustre/lclient/lcommon_cl.c index 27b5bb8..bc97877 100644 --- a/lustre/lclient/lcommon_cl.c +++ b/lustre/lclient/lcommon_cl.c @@ -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); diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 2947f4b..a5d5f05 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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); } diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 01ddfd2..e6adb42 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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) { diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index e7ca14e..562c875 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -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, diff --git a/lustre/lod/lod_internal.h b/lustre/lod/lod_internal.h index 2661c40..0dd077b 100644 --- a/lustre/lod/lod_internal.h +++ b/lustre/lod/lod_internal.h @@ -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 */ diff --git a/lustre/lod/lod_lov.c b/lustre/lod/lod_lov.c index 5426554..cc70895 100644 --- a/lustre/lod/lod_lov.c +++ b/lustre/lod/lod_lov.c @@ -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); diff --git a/lustre/lod/lod_object.c b/lustre/lod/lod_object.c index 787e461..9eeda28 100644 --- a/lustre/lod/lod_object.c +++ b/lustre/lod/lod_object.c @@ -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; } /* diff --git a/lustre/lod/lod_qos.c b/lustre/lod/lod_qos.c index fa7eed8..8a4d1bb 100644 --- a/lustre/lod/lod_qos.c +++ b/lustre/lod/lod_qos.c @@ -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 diff --git a/lustre/lov/lov_cl_internal.h b/lustre/lov/lov_cl_internal.h index 13c2f5a..61ee850 100644 --- a/lustre/lov/lov_cl_internal.h +++ b/lustre/lov/lov_cl_internal.h @@ -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); diff --git a/lustre/lov/lov_ea.c b/lustre/lov/lov_ea.c index af18014..bf6d9eb 100644 --- a/lustre/lov/lov_ea.c +++ b/lustre/lov/lov_ea.c @@ -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 = { diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index 76b0901..6f6ea84 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -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 */ diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 9c75cb3..5843bca 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -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) diff --git a/lustre/lov/lov_object.c b/lustre/lov/lov_object.c index 07ed284..e1f5b5d 100644 --- a/lustre/lov/lov_object.c +++ b/lustre/lov/lov_object.c @@ -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: diff --git a/lustre/lov/lov_pack.c b/lustre/lov/lov_pack.c index 47e0127..282b184 100644 --- a/lustre/lov/lov_pack.c +++ b/lustre/lov/lov_pack.c @@ -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) { diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 6283f66..4eec5f2 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -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); diff --git a/lustre/tests/multiop.c b/lustre/tests/multiop.c index b1a157d..541e1b0 100644 --- a/lustre/tests/multiop.c +++ b/lustre/tests/multiop.c @@ -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) diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index f3de47f..39b1138 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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 diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 5e76bca..155f5c3 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -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");