LMAI_REMOTE_PARENT = 0x00000004, /* the parent of the object
is on the remote MDT */
LMAI_STRIPED = 0x00000008, /* striped directory inode */
+ LMAI_ORPHAN = 0x00000010, /* inode is orphan */
+ LMA_INCOMPAT_SUPP = (LMAI_AGENT | LMAI_REMOTE_PARENT | \
+ LMAI_STRIPED | LMAI_ORPHAN)
};
-#define LMA_INCOMPAT_SUPP (LMAI_AGENT | LMAI_REMOTE_PARENT | LMAI_STRIPED)
extern void lustre_lma_swab(struct lustre_mdt_attrs *lma);
extern void lustre_lma_init(struct lustre_mdt_attrs *lma,
#define MDS_STATUS_CONN 1
#define MDS_STATUS_LOV 2
-/* these should be identical to their EXT4_*_FL counterparts, they are
- * redefined here only to avoid dragging in fs/ext4/ext4.h */
-#define LUSTRE_SYNC_FL 0x00000008 /* Synchronous updates */
-#define LUSTRE_IMMUTABLE_FL 0x00000010 /* Immutable file */
-#define LUSTRE_APPEND_FL 0x00000020 /* writes to file may only append */
-#define LUSTRE_NODUMP_FL 0x00000040 /* do not dump file */
-#define LUSTRE_NOATIME_FL 0x00000080 /* do not update atime */
-#define LUSTRE_INDEX_FL 0x00001000 /* hash-indexed directory */
-#define LUSTRE_DIRSYNC_FL 0x00010000 /* dirsync behaviour (dir only) */
-#define LUSTRE_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
-#define LUSTRE_DIRECTIO_FL 0x00100000 /* Use direct i/o */
-#define LUSTRE_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */
+enum {
+ /* these should be identical to their EXT4_*_FL counterparts, they are
+ * redefined here only to avoid dragging in fs/ext4/ext4.h */
+ LUSTRE_SYNC_FL = 0x00000008, /* Synchronous updates */
+ LUSTRE_IMMUTABLE_FL = 0x00000010, /* Immutable file */
+ LUSTRE_APPEND_FL = 0x00000020, /* writes to file may only append */
+ LUSTRE_NODUMP_FL = 0x00000040, /* do not dump file */
+ LUSTRE_NOATIME_FL = 0x00000080, /* do not update atime */
+ LUSTRE_INDEX_FL = 0x00001000, /* hash-indexed directory */
+ LUSTRE_DIRSYNC_FL = 0x00010000, /* dirsync behaviour (dir only) */
+ LUSTRE_TOPDIR_FL = 0x00020000, /* Top of directory hierarchies*/
+ LUSTRE_DIRECTIO_FL = 0x00100000, /* Use direct i/o */
+ LUSTRE_INLINE_DATA_FL = 0x10000000, /* Inode has inline data. */
+
+ /* These flags will not be identical to any EXT4_*_FL counterparts,
+ * and only reserved for lustre purpose. Note: these flags might
+ * be conflict with some of EXT4 flags, so
+ * 1. these conflict flags needs to be removed when the flag is
+ * wired by la_flags see osd_attr_get().
+ * 2. If these flags needs to be stored into inode, they will be
+ * stored in LMA. see LMAI_XXXX */
+ LUSTRE_ORPHAN_FL = 0x00002000,
+
+ LUSTRE_LMA_FL_MASKS = LUSTRE_ORPHAN_FL,
+};
+
+/* LUSTRE_LMA_FL_MASKS defines which flags will be stored in LMA */
+
+static inline int lma_to_lustre_flags(__u32 lma_flags)
+{
+ return (lma_flags & LMAI_ORPHAN) ? LUSTRE_ORPHAN_FL : 0;
+}
+
+static inline int lustre_to_lma_flags(__u32 la_flags)
+{
+ return (la_flags & LUSTRE_ORPHAN_FL) ? LMAI_ORPHAN : 0;
+}
+
#ifdef __KERNEL__
/* Convert wire LUSTRE_*_FL to corresponding client local VFS S_* values
#define LMV_HASH_TYPE_MASK 0x0000ffff
#define LMV_HASH_FLAG_MIGRATION 0x80000000
+
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 10, 53, 0)
+/* Since lustre 2.8, this flag will not be needed, instead this DEAD
+ * and orphan flags will be stored in LMA (see LMAI_ORPHAN)
+ * Keep this flag just for LFSCK, because it still might meet such
+ * flag when it checks the old FS */
#define LMV_HASH_FLAG_DEAD 0x40000000
+#endif
#define LMV_HASH_FLAG_BAD_TYPE 0x20000000
/* The striped directory has ever lost its master LMV EA, then LFSCK
const struct md_dir_operations *mo_dir_ops;
};
-/* Mark the object to be dead, and can not be accessed anymore.
- * XXX, right now, it will only be used for striped directory to
- * mark the slave stripes dead, when deleting master object. It will be
- * stored in slave LMV EA (see lod_mark_dead_object), which is only
- * temporary, and will be removed later when we have proper way to mark
- * the dead object. */
-#define LUSTRE_SLAVE_DEAD_FL 0x80000000
-
static inline struct md_device *lu2md_dev(const struct lu_device *d)
{
LASSERT(IS_ERR(d) || lu_device_is_md(d));
#define OBD_FAIL_LLITE_XATTR_ENOMEM 0x1405
#define OBD_FAIL_MAKE_LOVEA_HOLE 0x1406
#define OBD_FAIL_LLITE_LOST_LAYOUT 0x1407
+#define OBD_FAIL_LLITE_NO_CHECK_DEAD 0x1408
#define OBD_FAIL_FID_INDIR 0x1501
#define OBD_FAIL_FID_INLMA 0x1502
!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_DIR_STRIPE))
RETURN(-EINVAL);
+ if (IS_DEADDIR(parent) &&
+ !OBD_FAIL_CHECK(OBD_FAIL_LLITE_NO_CHECK_DEAD))
+ RETURN(-ENOENT);
+
if (lump->lum_magic != cpu_to_le32(LMV_USER_MAGIC))
lustre_swab_lmv_user_md(lump);
}
/**
- * Mark all of the striped directory sub-stripes dead.
- *
- * When a striped object is a subject to removal, we have
- * to mark all the stripes to prevent further access to
- * them (e.g. create a new file in those). So we mark
- * all the stripes with LMV_HASH_FLAG_DEAD. The function
- * can be used to declare the changes and to apply them.
- * If the object isn't striped, then just return success.
- *
- * \param[in] env execution environment
- * \param[in] dt the striped object
- * \param[in] handle transaction handle
- * \param[in] declare whether to declare the change or apply
- *
- * \retval 0 on success
- * \retval negative if failed
- **/
-static int lod_mark_dead_object(const struct lu_env *env,
- struct dt_object *dt,
- struct thandle *th,
- bool declare)
-{
- struct lod_object *lo = lod_dt_obj(dt);
- struct lmv_mds_md_v1 *lmv;
- __u32 dead_hash_type;
- int rc;
- int i;
-
- ENTRY;
-
- if (!S_ISDIR(dt->do_lu.lo_header->loh_attr))
- RETURN(0);
-
- rc = lod_load_striping_locked(env, lo);
- if (rc != 0)
- RETURN(rc);
-
- if (lo->ldo_stripenr == 0)
- RETURN(0);
-
- rc = lod_get_lmv_ea(env, lo);
- if (rc <= 0)
- RETURN(rc);
-
- lmv = lod_env_info(env)->lti_ea_store;
- lmv->lmv_magic = cpu_to_le32(LMV_MAGIC_STRIPE);
- dead_hash_type = le32_to_cpu(lmv->lmv_hash_type) | LMV_HASH_FLAG_DEAD;
- lmv->lmv_hash_type = cpu_to_le32(dead_hash_type);
- for (i = 0; i < lo->ldo_stripenr; i++) {
- struct lu_buf buf;
-
- lmv->lmv_master_mdt_index = i;
- buf.lb_buf = lmv;
- buf.lb_len = sizeof(*lmv);
- if (declare) {
- rc = lod_sub_object_declare_xattr_set(env,
- lo->ldo_stripe[i], &buf,
- XATTR_NAME_LMV,
- LU_XATTR_REPLACE, th);
- } else {
- rc = lod_sub_object_xattr_set(env, lo->ldo_stripe[i],
- &buf, XATTR_NAME_LMV,
- LU_XATTR_REPLACE, th);
- }
- if (rc != 0)
- break;
- }
-
- RETURN(rc);
-}
-
-/**
* Implementation of dt_object_operations::do_declare_attr_set.
*
* If the object is striped, then apply the changes to all the stripes.
int rc, i;
ENTRY;
- /* Set dead object on all other stripes */
- if (attr->la_valid & LA_FLAGS && !(attr->la_valid & ~LA_FLAGS) &&
- attr->la_flags & LUSTRE_SLAVE_DEAD_FL) {
- rc = lod_mark_dead_object(env, dt, th, true);
- RETURN(rc);
- }
-
/*
* declare setattr on the local object
*/
int rc, i;
ENTRY;
- /* Set dead object on all other stripes */
- if (attr->la_valid & LA_FLAGS && !(attr->la_valid & ~LA_FLAGS) &&
- attr->la_flags & LUSTRE_SLAVE_DEAD_FL) {
- rc = lod_mark_dead_object(env, dt, th, false);
- RETURN(rc);
- }
-
/*
* apply changes to the local object
*/
const struct lu_attr *pattr, struct mdd_object *cobj,
bool check_perm)
{
- struct mdd_thread_info *info = mdd_env_info(env);
- struct lu_buf *xbuf;
int rc = 0;
ENTRY;
if (mdd_is_dead_obj(pobj))
RETURN(-ENOENT);
- /* If the parent is a sub-stripe, check whether it is dead */
- xbuf = mdd_buf_get(env, info->mti_key, sizeof(info->mti_key));
- rc = mdo_xattr_get(env, pobj, xbuf, XATTR_NAME_LMV);
- if (unlikely(rc > 0)) {
- struct lmv_mds_md_v1 *lmv1 = xbuf->lb_buf;
-
- if (le32_to_cpu(lmv1->lmv_magic) == LMV_MAGIC_STRIPE &&
- le32_to_cpu(lmv1->lmv_hash_type) & LMV_HASH_FLAG_DEAD)
- RETURN(-ESTALE);
- }
- rc = 0;
-
if (check_perm)
rc = mdd_permission_internal_locked(env, pobj, pattr,
MAY_WRITE | MAY_EXEC,
return rc;
}
-static int mdd_mark_dead_object(const struct lu_env *env,
+static int mdd_mark_orphan_object(const struct lu_env *env,
struct mdd_object *obj, struct thandle *handle,
bool declare)
{
struct lu_attr *attr = MDD_ENV_VAR(env, la_for_start);
int rc;
- if (!declare)
- obj->mod_flags |= DEAD_OBJ;
-
if (!S_ISDIR(mdd_object_type(obj)))
return 0;
attr->la_valid = LA_FLAGS;
- attr->la_flags = LUSTRE_SLAVE_DEAD_FL;
+ attr->la_flags = LUSTRE_ORPHAN_FL;
if (declare)
rc = mdo_declare_attr_set(env, obj, attr, handle);
{
int rc;
- rc = mdd_mark_dead_object(env, obj, handle, true);
+ /* Sigh, we do not know if the unlink object will become orphan in
+ * declare phase, but fortunately the flags here does not matter
+ * in current declare implementation */
+ rc = mdd_mark_orphan_object(env, obj, handle, true);
if (rc != 0)
return rc;
struct thandle *th)
{
int rc = 0;
- int is_dir = S_ISDIR(ma->ma_attr.la_mode);
- ENTRY;
+ int is_dir = S_ISDIR(ma->ma_attr.la_mode);
+ ENTRY;
- LASSERT(mdd_write_locked(env, obj) != 0);
+ LASSERT(mdd_write_locked(env, obj) != 0);
if (ma->ma_attr.la_nlink == 0 || is_dir) {
- rc = mdd_mark_dead_object(env, obj, th, false);
- if (rc != 0)
- RETURN(rc);
+ /* add new orphan and the object
+ * will be deleted during mdd_close() */
+ obj->mod_flags |= DEAD_OBJ;
+ if (obj->mod_count) {
+ rc = mdd_mark_orphan_object(env, obj, th, false);
+ if (rc != 0)
+ RETURN(rc);
- /* add new orphan and the object
- * will be deleted during mdd_close() */
- if (obj->mod_count) {
- rc = __mdd_orphan_add(env, obj, th);
- if (rc == 0)
- CDEBUG(D_HA, "Object "DFID" is inserted into "
- "orphan list, open count = %d\n",
- PFID(mdd_object_fid(obj)),
- obj->mod_count);
- else
- CERROR("Object "DFID" fail to be an orphan, "
- "open count = %d, maybe cause failed "
- "open replay\n",
- PFID(mdd_object_fid(obj)),
- obj->mod_count);
- } else {
+ rc = __mdd_orphan_add(env, obj, th);
+ if (rc == 0)
+ CDEBUG(D_HA, "Object "DFID" is inserted into "
+ "orphan list, open count = %d\n",
+ PFID(mdd_object_fid(obj)),
+ obj->mod_count);
+ else
+ CERROR("Object "DFID" fail to be an orphan, "
+ "open count = %d, maybe cause failed "
+ "open replay\n",
+ PFID(mdd_object_fid(obj)),
+ obj->mod_count);
+ } else {
rc = mdo_destroy(env, obj, th);
- }
+ }
} else if (!is_dir) {
/* old files may not have link ea; ignore errors */
mdd_links_del(env, obj, mdo2fid(pobj), lname, th);
rc = mdd_finish_unlink(env, mdd_cobj, ma, mdd_pobj, lname, handle);
/* fetch updated nlink */
- if (rc == 0)
- rc = mdd_la_get(env, mdd_cobj, cattr);
+ if (rc != 0)
+ GOTO(cleanup, rc);
+
+ rc = mdd_la_get(env, mdd_cobj, cattr);
+ /* if object is removed then we can't get its attrs,
+ * use last get */
+ if (rc == -ENOENT) {
+ cattr->la_nlink = 0;
+ rc = 0;
+ }
- /* if object is removed then we can't get its attrs, use last get */
if (cattr->la_nlink == 0) {
ma->ma_attr = *cattr;
ma->ma_valid |= MA_INODE;
}
+
EXIT;
cleanup:
if (likely(mdd_cobj != NULL))
int rc;
ENTRY;
- /* EEXIST check */
- if (mdd_is_dead_obj(obj) ||
- pattr->la_flags & LUSTRE_SLAVE_DEAD_FL)
- RETURN(-ENOENT);
+ /* EEXIST check */
+ if (mdd_is_dead_obj(obj))
+ RETURN(-ENOENT);
/*
* In some cases this lookup is not needed - we know before if name
/* fetch updated nlink */
rc = mdd_la_get(env, mdd_tobj, tattr);
- if (rc != 0) {
+ if (rc == -ENOENT) {
+ /* the object got removed, let's
+ * return the latest known attributes */
+ tattr->la_nlink = 0;
+ rc = 0;
+ } else if (rc != 0) {
CERROR("%s: Failed to get nlink for tobj "
DFID": rc = %d\n",
mdd2obd_dev(mdd)->obd_name,
int mdd_la_get(const struct lu_env *env, struct mdd_object *obj,
struct lu_attr *la)
{
- if (mdd_object_exists(obj) == 0) {
- CERROR("%s: object "DFID" not found: rc = -2\n",
- mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
- return -ENOENT;
- }
+ int rc;
+
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return -ENOENT;
+ }
+
+ rc = mdo_attr_get(env, obj, la);
+ if (unlikely(rc != 0)) {
+ if (rc == -ENOENT)
+ obj->mod_flags |= DEAD_OBJ;
+ return rc;
+ }
+
+ if (la->la_valid & LA_FLAGS &&
+ la->la_flags & LUSTRE_ORPHAN_FL)
+ obj->mod_flags |= ORPHAN_OBJ | DEAD_OBJ;
- return mdo_attr_get(env, obj, la);
+ return 0;
}
struct mdd_thread_info *mdd_env_info(const struct lu_env *env)
result = osd_fid_lookup(env, obj, lu_object_fid(l), conf);
obj->oo_dt.do_body_ops = &osd_body_ops_new;
- if (result == 0 && obj->oo_inode != NULL)
+ if (result == 0 && obj->oo_inode != NULL) {
+ struct osd_thread_info *oti = osd_oti_get(env);
+ struct lustre_mdt_attrs *lma = &oti->oti_mdt_attrs;
+
osd_object_init0(obj);
+ result = osd_get_lma(oti, obj->oo_inode,
+ &oti->oti_obj_dentry, lma);
+ if (result == 0) {
+ /* Convert LMAI flags to lustre LMA flags
+ * and cache it to oo_lma_flags */
+ obj->oo_lma_flags =
+ lma_to_lustre_flags(lma->lma_incompat);
+ } else if (result == -ENODATA) {
+ result = 0;
+ }
+ }
LINVRNT(osd_invariant(obj));
return result;
return t;
}
-
static void osd_inode_getattr(const struct lu_env *env,
struct inode *inode, struct lu_attr *attr)
{
attr->la_blocks = inode->i_blocks;
attr->la_uid = i_uid_read(inode);
attr->la_gid = i_gid_read(inode);
- attr->la_flags = LDISKFS_I(inode)->i_flags;
+ attr->la_flags = ll_inode_to_ext_flags(inode->i_flags);
attr->la_nlink = inode->i_nlink;
attr->la_rdev = inode->i_rdev;
attr->la_blksize = 1 << inode->i_blkbits;
{
struct osd_object *obj = osd_dt_obj(dt);
- if (!dt_object_exists(dt))
+ if (unlikely(!dt_object_exists(dt)))
+ return -ENOENT;
+ if (unlikely(obj->oo_destroyed))
return -ENOENT;
LASSERT(!dt_object_remote(dt));
spin_lock(&obj->oo_guard);
osd_inode_getattr(env, obj->oo_inode, attr);
+ if (obj->oo_lma_flags & LUSTRE_ORPHAN_FL)
+ attr->la_flags |= LUSTRE_ORPHAN_FL;
spin_unlock(&obj->oo_guard);
+
return 0;
}
osd_trans_declare_op(env, oh, OSD_OT_ATTR_SET,
osd_dto_credits_noquota[DTO_ATTR_SET_BASE]);
+ osd_trans_declare_op(env, oh, OSD_OT_XATTR_SET,
+ osd_dto_credits_noquota[DTO_XATTR_SET]);
+
if (attr == NULL || obj->oo_inode == NULL)
RETURN(rc);
spin_lock(&obj->oo_guard);
rc = osd_inode_setattr(env, inode, attr);
spin_unlock(&obj->oo_guard);
+ if (rc != 0)
+ GOTO(out, rc);
- if (!rc)
- ll_dirty_inode(inode, I_DIRTY_DATASYNC);
+ ll_dirty_inode(inode, I_DIRTY_DATASYNC);
+
+ if (!(attr->la_valid & LA_FLAGS))
+ GOTO(out, rc);
+
+ /* Let's check if there are extra flags need to be set into LMA */
+ if (attr->la_flags & LUSTRE_LMA_FL_MASKS) {
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct lustre_mdt_attrs *lma = &info->oti_mdt_attrs;
+
+ rc = osd_get_lma(info, inode, &info->oti_obj_dentry, lma);
+ if (rc != 0)
+ GOTO(out, rc);
+ lma->lma_incompat |=
+ lustre_to_lma_flags(attr->la_flags);
+ lustre_lma_swab(lma);
+ rc = __osd_xattr_set(info, inode, XATTR_NAME_LMA,
+ lma, sizeof(*lma), XATTR_REPLACE);
+ if (rc != 0) {
+ struct osd_device *osd = osd_obj2dev(obj);
+
+ CWARN("%s: set "DFID" lma flags %u failed: rc = %d\n",
+ osd_name(osd), PFID(lu_object_fid(&dt->do_lu)),
+ lma->lma_incompat, rc);
+ } else {
+ obj->oo_lma_flags =
+ attr->la_flags & LUSTRE_LMA_FL_MASKS;
+ }
+ osd_trans_exec_check(env, handle, OSD_OT_XATTR_SET);
+ }
+out:
osd_trans_exec_check(env, handle, OSD_OT_ATTR_SET);
return rc;
if (result)
return;
- if (attr->la_valid != 0) {
- result = osd_inode_setattr(info->oti_env, inode, attr);
- /*
- * The osd_inode_setattr() should always succeed here. The
- * only error that could be returned is EDQUOT when we are
- * trying to change the UID or GID of the inode. However, this
- * should not happen since quota enforcement is no longer
- * enabled on ldiskfs (lquota takes care of it).
- */
+ if (attr->la_valid != 0) {
+ result = osd_inode_setattr(info->oti_env, inode, attr);
+ /*
+ * The osd_inode_setattr() should always succeed here. The
+ * only error that could be returned is EDQUOT when we are
+ * trying to change the UID or GID of the inode. However, this
+ * should not happen since quota enforcement is no longer
+ * enabled on ldiskfs (lquota takes care of it).
+ */
LASSERTF(result == 0, "%d\n", result);
ll_dirty_inode(inode, I_DIRTY_DATASYNC);
- }
+ }
- attr->la_valid = valid;
+ attr->la_valid = valid;
}
/**
spinlock_t oo_guard;
__u32 oo_destroyed:1;
+
+ /* the i_flags in LMA */
+ __u32 oo_lma_flags;
/**
* Following two members are used to indicate the presence of dot and
* dotdot in the given directory. This is required for interop mode
enum osd_destroy_type oo_destroy;
__u32 oo_destroyed:1;
+
+ /* the i_flags in LMA */
+ __u32 oo_lma_flags;
/* record size for index file */
unsigned char oo_keysize;
unsigned char oo_recsize;
static inline uint64_t attrs_fs2zfs(const uint32_t flags)
{
- return (((flags & FS_APPEND_FL) ? ZFS_APPENDONLY : 0) |
- ((flags & FS_NODUMP_FL) ? ZFS_NODUMP : 0) |
- ((flags & FS_IMMUTABLE_FL) ? ZFS_IMMUTABLE : 0));
+ return (flags & LUSTRE_APPEND_FL ? ZFS_APPENDONLY : 0) |
+ (flags & LUSTRE_NODUMP_FL ? ZFS_NODUMP : 0) |
+ (flags & LUSTRE_IMMUTABLE_FL ? ZFS_IMMUTABLE : 0);
}
static inline uint32_t attrs_zfs2fs(const uint64_t flags)
{
- return (((flags & ZFS_APPENDONLY) ? FS_APPEND_FL : 0) |
- ((flags & ZFS_NODUMP) ? FS_NODUMP_FL : 0) |
- ((flags & ZFS_IMMUTABLE) ? FS_IMMUTABLE_FL : 0));
+ return (flags & ZFS_APPENDONLY ? LUSTRE_APPEND_FL : 0) |
+ (flags & ZFS_NODUMP ? LUSTRE_NODUMP_FL : 0) |
+ (flags & ZFS_IMMUTABLE ? LUSTRE_IMMUTABLE_FL : 0);
}
#endif
la->la_flags = attrs_zfs2fs(osa->flags);
la->la_size = osa->size;
+ /* Try to get extra flag from LMA. Right now, only LMAI_ORPHAN
+ * flags is stored in LMA, and it is only for orphan directory */
+ if (S_ISDIR(la->la_mode) && dt_object_exists(&obj->oo_dt)) {
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct lustre_mdt_attrs *lma;
+ struct lu_buf buf;
+
+ lma = (struct lustre_mdt_attrs *)info->oti_buf;
+ buf.lb_buf = lma;
+ buf.lb_len = sizeof(info->oti_buf);
+ rc = osd_xattr_get(env, &obj->oo_dt, &buf, XATTR_NAME_LMA);
+ if (rc > 0) {
+ rc = 0;
+ lma->lma_incompat = le32_to_cpu(lma->lma_incompat);
+ obj->oo_lma_flags =
+ lma_to_lustre_flags(lma->lma_incompat);
+
+ } else if (rc == -ENODATA) {
+ rc = 0;
+ }
+ }
+
if (S_ISCHR(la->la_mode) || S_ISBLK(la->la_mode)) {
rc = -sa_lookup(sa_hdl, SA_ZPL_RDEV(o), &osa->rdev, 8);
if (rc)
uint64_t blocks;
uint32_t blksize;
- LASSERT(dt_object_exists(dt));
+ if (unlikely(!dt_object_exists(dt)))
+ return -ENOENT;
+ if (unlikely(obj->oo_destroyed))
+ return -ENOENT;
+
LASSERT(osd_invariant(obj));
LASSERT(obj->oo_db);
read_lock(&obj->oo_attr_lock);
*attr = obj->oo_attr;
+ if (obj->oo_lma_flags & LUSTRE_ORPHAN_FL)
+ attr->la_flags |= LUSTRE_ORPHAN_FL;
read_unlock(&obj->oo_attr_lock);
/* with ZFS_DEBUG zrl_add_debug() called by DB_DNODE_ENTER()
sa_object_size(obj->oo_sa_hdl, &blksize, &bspace);
bspace = toqb(bspace * blksize);
+ __osd_xattr_declare_set(env, obj, sizeof(struct lustre_mdt_attrs),
+ XATTR_NAME_LMA, oh);
+
if (attr && attr->la_valid & LA_UID) {
/* account for user inode tracking ZAP update */
dmu_tx_hold_bonus(oh->ot_tx, osd->od_iusr_oid);
static int osd_attr_set(const struct lu_env *env, struct dt_object *dt,
const struct lu_attr *la, struct thandle *handle)
{
+ struct osd_thread_info *info = osd_oti_get(env);
struct osd_object *obj = osd_dt_obj(dt);
struct osd_device *osd = osd_obj2dev(obj);
struct osd_thandle *oh;
- struct osa_attr *osa = &osd_oti_get(env)->oti_osa;
+ struct osa_attr *osa = &info->oti_osa;
sa_bulk_attr_t *bulk;
__u64 valid = la->la_valid;
int cnt;
if (valid == 0)
RETURN(0);
+ if (valid & LA_FLAGS) {
+ struct lustre_mdt_attrs *lma;
+ struct lu_buf buf;
+
+ if (la->la_flags & LUSTRE_LMA_FL_MASKS) {
+ CLASSERT(sizeof(info->oti_buf) >= sizeof(*lma));
+ lma = (struct lustre_mdt_attrs *)&info->oti_buf;
+ buf.lb_buf = lma;
+ buf.lb_len = sizeof(info->oti_buf);
+ rc = osd_xattr_get(env, &obj->oo_dt, &buf,
+ XATTR_NAME_LMA);
+ if (rc > 0) {
+ lma->lma_incompat =
+ le32_to_cpu(lma->lma_incompat);
+ lma->lma_incompat |=
+ lustre_to_lma_flags(la->la_flags);
+ lma->lma_incompat =
+ cpu_to_le32(lma->lma_incompat);
+ buf.lb_buf = lma;
+ buf.lb_len = sizeof(*lma);
+ rc = osd_xattr_set_internal(env, obj, &buf,
+ XATTR_NAME_LMA,
+ LU_XATTR_REPLACE,
+ oh);
+ }
+ if (rc < 0) {
+ CWARN("%s: failed to set LMA flags: rc = %d\n",
+ osd->od_svname, rc);
+ RETURN(rc);
+ }
+ }
+ }
+
OBD_ALLOC(bulk, sizeof(sa_bulk_attr_t) * 10);
if (bulk == NULL)
RETURN(-ENOMEM);
GOTO(out, rc = -ERANGE);
memcpy(buf->lb_buf, rbuf->lb_buf, rbuf->lb_len);
- rc = rbuf->lb_len;
if (obj->opo_ooa == NULL || osp->opd_connect_mdt)
GOTO(out, rc);
(long long)(int)sizeof(((struct lustre_mdt_attrs *)0)->lma_self_fid));
LASSERTF(LMAI_RELEASED == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)LMAI_RELEASED);
+ LASSERTF(LMAI_AGENT == 0x00000002UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_AGENT);
+ LASSERTF(LMAI_REMOTE_PARENT == 0x00000004UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_REMOTE_PARENT);
+ LASSERTF(LMAI_STRIPED == 0x00000008UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_STRIPED);
+ LASSERTF(LMAI_ORPHAN == 0x00000010UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_ORPHAN);
LASSERTF(LMAC_HSM == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)LMAC_HSM);
LASSERTF(LMAC_NOT_IN_OI == 0x00000004UL, "found 0x%.8xUL\n",
(long long)MDS_OPEN_NEWSTRIPE);
LASSERTF(MDS_OPEN_VOLATILE == 00000000000400000000000ULL, "found 0%.22lloULL\n",
(long long)MDS_OPEN_VOLATILE);
- LASSERTF(LUSTRE_SYNC_FL == 0x00000008, "found 0x%.8x\n",
- LUSTRE_SYNC_FL);
- LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010, "found 0x%.8x\n",
- LUSTRE_IMMUTABLE_FL);
- LASSERTF(LUSTRE_APPEND_FL == 0x00000020, "found 0x%.8x\n",
- LUSTRE_APPEND_FL);
- LASSERTF(LUSTRE_NODUMP_FL == 0x00000040, "found 0x%.8x\n",
- LUSTRE_NODUMP_FL);
- LASSERTF(LUSTRE_NOATIME_FL == 0x00000080, "found 0x%.8x\n",
- LUSTRE_NOATIME_FL);
- LASSERTF(LUSTRE_INDEX_FL == 0x00001000, "found 0x%.8x\n",
- LUSTRE_INDEX_FL);
- LASSERTF(LUSTRE_DIRSYNC_FL == 0x00010000, "found 0x%.8x\n",
- LUSTRE_DIRSYNC_FL);
- LASSERTF(LUSTRE_TOPDIR_FL == 0x00020000, "found 0x%.8x\n",
- LUSTRE_TOPDIR_FL);
- LASSERTF(LUSTRE_DIRECTIO_FL == 0x00100000, "found 0x%.8x\n",
- LUSTRE_DIRECTIO_FL);
- LASSERTF(LUSTRE_INLINE_DATA_FL == 0x10000000, "found 0x%.8x\n",
- LUSTRE_INLINE_DATA_FL);
+ LASSERTF(LUSTRE_SYNC_FL == 0x00000008UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_SYNC_FL);
+ LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_IMMUTABLE_FL);
+ LASSERTF(LUSTRE_APPEND_FL == 0x00000020UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_APPEND_FL);
+ LASSERTF(LUSTRE_NODUMP_FL == 0x00000040UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_NODUMP_FL);
+ LASSERTF(LUSTRE_NOATIME_FL == 0x00000080UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_NOATIME_FL);
+ LASSERTF(LUSTRE_INDEX_FL == 0x00001000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_INDEX_FL);
+ LASSERTF(LUSTRE_ORPHAN_FL == 0x00002000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_ORPHAN_FL);
+ LASSERTF(LUSTRE_DIRSYNC_FL == 0x00010000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_DIRSYNC_FL);
+ LASSERTF(LUSTRE_TOPDIR_FL == 0x00020000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_TOPDIR_FL);
+ LASSERTF(LUSTRE_DIRECTIO_FL == 0x00100000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_DIRECTIO_FL);
+ LASSERTF(LUSTRE_INLINE_DATA_FL == 0x10000000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_INLINE_DATA_FL);
LASSERTF(MDS_INODELOCK_LOOKUP == 0x000001, "found 0x%.8x\n",
MDS_INODELOCK_LOOKUP);
LASSERTF(MDS_INODELOCK_UPDATE == 0x000002, "found 0x%.8x\n",
}
run_test 300p "create striped directory without space"
+test_300q() {
+ [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
+ [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
+
+ local fd=$(free_fd)
+ local cmd="exec $fd<$tdir"
+ cd $DIR
+ $LFS mkdir -c $MDSCOUNT $tdir || error "create $tdir fails"
+ eval $cmd
+ cmd="exec $fd<&-"
+ trap "eval $cmd" EXIT
+ cd $tdir || error "cd $tdir fails"
+ rmdir ../$tdir || error "rmdir $tdir fails"
+ mkdir local_dir && error "create dir succeeds"
+ $LFS setdirstripe -i1 remote_dir && error "create remote dir succeeds"
+ eval $cmd
+ return 0
+}
+run_test 300q "create remote directory under orphan directory"
+
prepare_remote_file() {
mkdir $DIR/$tdir/src_dir ||
error "create remote source failed"
}
run_test 91 "chmod and unlink striped directory"
+test_92() {
+ [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
+
+ local fd=$(free_fd)
+ local cmd="exec $fd<$DIR1/$tdir"
+ $LFS setdirstripe -c$MDSCOUNT $DIR1/$tdir || error "mkdir $tdir fails"
+ eval $cmd
+ cmd="exec $fd<&-"
+ trap "eval $cmd" EXIT
+ cd $DIR1/$tdir || error "cd $DIR1/$tdir fails"
+ rmdir ../$tdir || error "rmdir ../$tdir fails"
+
+ #define OBD_FAIL_LLITE_NO_CHECK_DEAD 0x1408
+ $LCTL set_param fail_loc=0x1408
+ mkdir $DIR2/$tdir/dir && error "create dir succeeds"
+ $LFS setdirstripe -i1 $DIR2/$tdir/remote_dir &&
+ error "create remote dir succeeds"
+ $LCTL set_param fail_loc=0
+ eval $cmd
+ return 0
+}
+run_test 92 "create remote directory under orphan directory"
+
log "cleanup: ======================================================"
# kill and wait in each test only guarentee script finish, but command in script
CHECK_MEMBER(lustre_mdt_attrs, lma_incompat);
CHECK_MEMBER(lustre_mdt_attrs, lma_self_fid);
CHECK_VALUE_X(LMAI_RELEASED);
+ CHECK_VALUE_X(LMAI_AGENT);
+ CHECK_VALUE_X(LMAI_REMOTE_PARENT);
+ CHECK_VALUE_X(LMAI_STRIPED);
+ CHECK_VALUE_X(LMAI_ORPHAN);
CHECK_VALUE_X(LMAC_HSM);
CHECK_VALUE_X(LMAC_NOT_IN_OI);
/* these should be identical to their EXT3_*_FL counterparts, and
* are redefined only to avoid dragging in ext3_fs.h */
- CHECK_DEFINE_X(LUSTRE_SYNC_FL);
- CHECK_DEFINE_X(LUSTRE_IMMUTABLE_FL);
- CHECK_DEFINE_X(LUSTRE_APPEND_FL);
- CHECK_DEFINE_X(LUSTRE_NODUMP_FL);
- CHECK_DEFINE_X(LUSTRE_NOATIME_FL);
- CHECK_DEFINE_X(LUSTRE_INDEX_FL);
- CHECK_DEFINE_X(LUSTRE_DIRSYNC_FL);
- CHECK_DEFINE_X(LUSTRE_TOPDIR_FL);
- CHECK_DEFINE_X(LUSTRE_DIRECTIO_FL);
- CHECK_DEFINE_X(LUSTRE_INLINE_DATA_FL);
+ CHECK_VALUE_X(LUSTRE_SYNC_FL);
+ CHECK_VALUE_X(LUSTRE_IMMUTABLE_FL);
+ CHECK_VALUE_X(LUSTRE_APPEND_FL);
+ CHECK_VALUE_X(LUSTRE_NODUMP_FL);
+ CHECK_VALUE_X(LUSTRE_NOATIME_FL);
+ CHECK_VALUE_X(LUSTRE_INDEX_FL);
+ CHECK_VALUE_X(LUSTRE_ORPHAN_FL);
+ CHECK_VALUE_X(LUSTRE_DIRSYNC_FL);
+ CHECK_VALUE_X(LUSTRE_TOPDIR_FL);
+ CHECK_VALUE_X(LUSTRE_DIRECTIO_FL);
+ CHECK_VALUE_X(LUSTRE_INLINE_DATA_FL);
CHECK_DEFINE_X(MDS_INODELOCK_LOOKUP);
CHECK_DEFINE_X(MDS_INODELOCK_UPDATE);
(long long)(int)sizeof(((struct lustre_mdt_attrs *)0)->lma_self_fid));
LASSERTF(LMAI_RELEASED == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)LMAI_RELEASED);
+ LASSERTF(LMAI_AGENT == 0x00000002UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_AGENT);
+ LASSERTF(LMAI_REMOTE_PARENT == 0x00000004UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_REMOTE_PARENT);
+ LASSERTF(LMAI_STRIPED == 0x00000008UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_STRIPED);
+ LASSERTF(LMAI_ORPHAN == 0x00000010UL, "found 0x%.8xUL\n",
+ (unsigned)LMAI_ORPHAN);
LASSERTF(LMAC_HSM == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)LMAC_HSM);
LASSERTF(LMAC_NOT_IN_OI == 0x00000004UL, "found 0x%.8xUL\n",
(long long)MDS_OPEN_NEWSTRIPE);
LASSERTF(MDS_OPEN_VOLATILE == 00000000000400000000000ULL, "found 0%.22lloULL\n",
(long long)MDS_OPEN_VOLATILE);
- LASSERTF(LUSTRE_SYNC_FL == 0x00000008, "found 0x%.8x\n",
- LUSTRE_SYNC_FL);
- LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010, "found 0x%.8x\n",
- LUSTRE_IMMUTABLE_FL);
- LASSERTF(LUSTRE_APPEND_FL == 0x00000020, "found 0x%.8x\n",
- LUSTRE_APPEND_FL);
- LASSERTF(LUSTRE_NODUMP_FL == 0x00000040, "found 0x%.8x\n",
- LUSTRE_NODUMP_FL);
- LASSERTF(LUSTRE_NOATIME_FL == 0x00000080, "found 0x%.8x\n",
- LUSTRE_NOATIME_FL);
- LASSERTF(LUSTRE_INDEX_FL == 0x00001000, "found 0x%.8x\n",
- LUSTRE_INDEX_FL);
- LASSERTF(LUSTRE_DIRSYNC_FL == 0x00010000, "found 0x%.8x\n",
- LUSTRE_DIRSYNC_FL);
- LASSERTF(LUSTRE_TOPDIR_FL == 0x00020000, "found 0x%.8x\n",
- LUSTRE_TOPDIR_FL);
- LASSERTF(LUSTRE_DIRECTIO_FL == 0x00100000, "found 0x%.8x\n",
- LUSTRE_DIRECTIO_FL);
- LASSERTF(LUSTRE_INLINE_DATA_FL == 0x10000000, "found 0x%.8x\n",
- LUSTRE_INLINE_DATA_FL);
+ LASSERTF(LUSTRE_SYNC_FL == 0x00000008UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_SYNC_FL);
+ LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_IMMUTABLE_FL);
+ LASSERTF(LUSTRE_APPEND_FL == 0x00000020UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_APPEND_FL);
+ LASSERTF(LUSTRE_NODUMP_FL == 0x00000040UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_NODUMP_FL);
+ LASSERTF(LUSTRE_NOATIME_FL == 0x00000080UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_NOATIME_FL);
+ LASSERTF(LUSTRE_INDEX_FL == 0x00001000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_INDEX_FL);
+ LASSERTF(LUSTRE_ORPHAN_FL == 0x00002000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_ORPHAN_FL);
+ LASSERTF(LUSTRE_DIRSYNC_FL == 0x00010000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_DIRSYNC_FL);
+ LASSERTF(LUSTRE_TOPDIR_FL == 0x00020000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_TOPDIR_FL);
+ LASSERTF(LUSTRE_DIRECTIO_FL == 0x00100000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_DIRECTIO_FL);
+ LASSERTF(LUSTRE_INLINE_DATA_FL == 0x10000000UL, "found 0x%.8xUL\n",
+ (unsigned)LUSTRE_INLINE_DATA_FL);
LASSERTF(MDS_INODELOCK_LOOKUP == 0x000001, "found 0x%.8x\n",
MDS_INODELOCK_LOOKUP);
LASSERTF(MDS_INODELOCK_UPDATE == 0x000002, "found 0x%.8x\n",