int mds_log_op_setattr(struct obd_device *obd, struct inode *inode,
struct lov_mds_md *lmm, int lmm_size,
struct llog_cookie *logcookies, int cookies_size);
+int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid,
+ struct lov_mds_md *lmm, int lmm_size,
+ struct llog_cookie *logcookies, __u64 id, __u32 gen);
/* ioctls for trying requests */
#define IOC_REQUEST_TYPE 'f'
};
struct md_attr {
- __u64 ma_valid;
+ __u64 ma_valid;
+ __u64 ma_need;
+ __u64 ma_attr_flags;
struct lu_attr ma_attr;
struct lov_mds_md *ma_lmm;
int ma_lmm_size;
struct llog_cookie *ma_cookie;
int ma_cookie_size;
};
+
+enum md_attr_flags {
+ MD_ATIME_SET = 1 << 0,
+ MD_MTIME_SET = 1 << 1,
+ MD_CTIME_SET = 1 << 2,
+ MD_ATTR_FLAG = 1 << 3,
+ MD_ATTR_RAW = 1 << 4
+};
+
/* additional parameters for create */
struct md_create_spec {
union {
static void mdd_trans_stop(const struct lu_context *ctxt,
struct mdd_device *mdd, struct thandle *handle);
static struct dt_object* mdd_object_child(struct mdd_object *o);
-static void mdd_lock(const struct lu_context *ctx,
- struct mdd_object *obj, enum dt_lock_mode mode);
-static void mdd_unlock(const struct lu_context *ctx,
- struct mdd_object *obj, enum dt_lock_mode mode);
static void __mdd_ref_add(const struct lu_context *ctxt, struct mdd_object *obj,
struct thandle *handle);
static void __mdd_ref_del(const struct lu_context *ctxt, struct mdd_object *obj,
lu_object_put(ctxt, &o->mod_obj.mo_lu);
}
-static umode_t mdd_object_type(const struct mdd_object *obj)
-{
- return lu_object_attr(&obj->mod_obj.mo_lu);
-}
-
static void mdd_set_dead_obj(struct mdd_object *obj)
{
if (obj)
RETURN(rc);
}
-static int __mdd_attr_get(const struct lu_context *ctxt,
- struct mdd_object *obj, struct md_attr *ma)
+static int __mdd_lmm_get(const struct lu_context *ctxt,
+ struct mdd_object *obj, struct md_attr *ma)
{
- struct dt_object *next;
- int rc;
-
- ENTRY;
-
- LASSERT(lu_object_exists(ctxt, mdd2lu_obj(obj)));
+ int rc;
- next = mdd_object_child(obj);
- rc = next->do_ops->do_attr_get(ctxt, next, &ma->ma_attr);
- if (rc == 0) {
- LASSERT((ma->ma_attr.la_mode & S_IFMT) ==
- (lu_object_attr(mdd2lu_obj(obj)) & S_IFMT));
- ma->ma_valid = MA_INODE;
+ LASSERT(ma->ma_lmm != NULL && ma->ma_lmm_size > 0);
+ rc = mdd_get_md(ctxt, obj, ma->ma_lmm, &ma->ma_lmm_size, 0);
+ if (rc > 0) {
+ ma->ma_valid |= MA_LOV;
+ rc = 0;
}
-
RETURN(rc);
}
-static int __mdd_lov_get(const struct lu_context *ctxt,
- struct mdd_object *obj, struct md_attr *ma)
+static int mdd_attr_get_internal (const struct lu_context *ctxt,
+ struct mdd_object *mdd_obj,
+ struct md_attr *ma, int need_locked)
{
struct dt_object *next;
- int rc = 0;
-
+ int rc = 0;
ENTRY;
- next = mdd_object_child(obj);
- if ((S_ISREG(ma->ma_attr.la_mode) || S_ISDIR(ma->ma_attr.la_mode))
- && ma->ma_lmm != 0 && ma->ma_lmm_size > 0) {
- rc = mdd_get_md(ctxt, &obj->mod_obj,
- ma->ma_lmm, &ma->ma_lmm_size);
- if (rc > 0) {
- ma->ma_valid |= MA_LOV;
- rc = 0;
- }
+ if (need_locked)
+ mdd_lock(ctxt, mdd_obj, DT_READ_LOCK);
+ if (ma->ma_need & MA_INODE) {
+ next = mdd_object_child(mdd_obj);
+ rc = next->do_ops->do_attr_get(ctxt, next, &ma->ma_attr);
+ if (rc)
+ GOTO(out, rc);
+ ma->ma_valid = MA_INODE;
}
+ if (ma->ma_need & MA_LOV) {
+ if ((S_ISREG(ma->ma_attr.la_mode)
+ || S_ISDIR(ma->ma_attr.la_mode))) {
+ rc = __mdd_lmm_get(ctxt, mdd_obj, ma);
+ }
+ }
+out:
+ CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64"\n",
+ rc, ma->ma_valid);
+ if (need_locked)
+ mdd_unlock(ctxt, mdd_obj, DT_READ_LOCK);
RETURN(rc);
}
-
+
static int mdd_attr_get(const struct lu_context *ctxt,
struct md_object *obj, struct md_attr *ma)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
- struct dt_object *next;
int rc;
ENTRY;
- next = mdd_object_child(mdd_obj);
- rc = __mdd_attr_get(ctxt, mdd_obj, ma);
- if (rc == 0) {
- /* get LOV EA also */
- rc = __mdd_lov_get(ctxt, mdd_obj, ma);
- }
- CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64"\n",
- rc, ma->ma_valid);
+ LASSERT(lu_object_exists(ctxt, &obj->mo_lu));
+
+ mdd_lock(ctxt, mdd_obj, DT_READ_LOCK);
+ rc = mdd_attr_get_internal(ctxt, mdd_obj, ma, 0);
+ mdd_unlock(ctxt, mdd_obj, DT_READ_LOCK);
RETURN(rc);
}
.loo_object_exists = mdd_object_exists,
};
-static void mdd_lock(const struct lu_context *ctxt,
- struct mdd_object *obj, enum dt_lock_mode mode)
+void mdd_lock(const struct lu_context *ctxt, struct mdd_object *obj,
+ enum dt_lock_mode mode)
{
struct dt_object *next = mdd_object_child(obj);
next->do_ops->do_lock(ctxt, next, mode);
}
-static void mdd_unlock(const struct lu_context *ctxt,
- struct mdd_object *obj, enum dt_lock_mode mode)
+void mdd_unlock(const struct lu_context *ctxt, struct mdd_object *obj,
+ enum dt_lock_mode mode)
{
struct dt_object *next = mdd_object_child(obj);
int fl, struct thandle *handle)
{
struct dt_object *next;
-
+ int rc = 0;
+
LASSERT(lu_object_exists(ctxt, mdd2lu_obj(o)));
next = mdd_object_child(o);
- return next->do_ops->do_xattr_set(ctxt, next, buf, buf_len, name, fl,
- handle);
+ if (buf && buf_len > 0) {
+ rc = next->do_ops->do_xattr_set(ctxt, next, buf, buf_len, name,
+ 0, handle);
+ }else if (buf == NULL && buf_len == 0) {
+ rc = next->do_ops->do_xattr_del(ctxt, next, name, handle);
+ }
+ RETURN(rc);
+}
+/* this gives the same functionality as the code between
+ * sys_chmod and inode_setattr
+ * chown_common and inode_setattr
+ * utimes and inode_setattr
+ * This API is ported from mds_fix_attr but remove some unnecesssary stuff.
+ * and port to
+ */
+int mdd_fix_attr(const struct lu_context *ctxt, struct mdd_object *obj,
+ const struct md_attr *ma)
+{
+ time_t now = CURRENT_SECONDS;
+ struct lu_attr *la = (struct lu_attr *)&ma->ma_attr;
+ struct lu_attr *tmp_la = &mdd_ctx_info(ctxt)->mti_la;
+ struct dt_object *next = mdd_object_child(obj);
+ int rc = 0;
+ ENTRY;
+
+ rc = next->do_ops->do_attr_get(ctxt, next, tmp_la);
+ if (rc)
+ RETURN(rc);
+
+ if (!(ma->ma_attr_flags & ATTR_CTIME_SET))
+ la->la_ctime = now;
+
+ if (!(ma->ma_attr_flags & ATTR_ATIME_SET))
+ la->la_atime = now;
+ if (!(ma->ma_attr_flags & ATTR_MTIME_SET))
+ la->la_mtime = now;
+
+ /*XXX Check permission */
+#if 0
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ RETURN((attr->ia_valid & ~ATTR_ATTR_FLAG) ? -EPERM : 0);
+
+ /* times */
+ if ((ia_valid & (ATTR_MTIME|ATTR_ATIME)) == (ATTR_MTIME|ATTR_ATIME)) {
+ if (current->fsuid != inode->i_uid &&
+ (error = ll_permission(inode, MAY_WRITE, NULL)) != 0)
+ RETURN(error);
+ }
+ if (ia_valid & ATTR_SIZE &&
+ /* NFSD hack for open(O_CREAT|O_TRUNC)=mknod+truncate (bug 5781) */
+ !(rec->ur_uc.luc_fsuid == inode->i_uid &&
+ ia_valid & MDS_OPEN_OWNEROVERRIDE)) {
+ if ((error = ll_permission(inode, MAY_WRITE, NULL)) != 0)
+ RETURN(error);
+ }
+#endif
+
+ if (la->la_valid & (LA_UID | LA_GID)) {
+ /* chown */
+
+ rc = -EPERM;
+
+ if (la->la_uid == (uid_t) -1)
+ la->la_uid = tmp_la->la_uid;
+ if (la->la_gid == (gid_t) -1)
+ la->la_gid = tmp_la->la_gid;
+ if (!(la->la_valid & ATTR_MODE))
+ la->la_mode = tmp_la->la_mode;
+ /*
+ * If the user or group of a non-directory has been
+ * changed by a non-root user, remove the setuid bit.
+ * 19981026 David C Niemi <niemi@tux.org>
+ *
+ * Changed this to apply to all users, including root,
+ * to avoid some races. This is the behavior we had in
+ * 2.0. The check for non-root was definitely wrong
+ * for 2.2 anyway, as it should have been using
+ * CAP_FSETID rather than fsuid -- 19990830 SD.
+ */
+ if ((tmp_la->la_mode & S_ISUID) == S_ISUID &&
+ !S_ISDIR(tmp_la->la_mode)) {
+ la->la_mode &= ~S_ISUID;
+ la->la_valid |= LA_MODE;
+ }
+ /*
+ * Likewise, if the user or group of a non-directory
+ * has been changed by a non-root user, remove the
+ * setgid bit UNLESS there is no group execute bit
+ * (this would be a file marked for mandatory
+ * locking). 19981026 David C Niemi <niemi@tux.org>
+ *
+ * Removed the fsuid check (see the comment above) --
+ * 19990830 SD.
+ */
+ if (((tmp_la->la_mode & (S_ISGID | S_IXGRP)) ==
+ (S_ISGID | S_IXGRP)) && !S_ISDIR(tmp_la->la_mode)) {
+ la->la_mode &= ~S_ISGID;
+ la->la_valid |= ATTR_MODE;
+ }
+ } else if (la->la_valid & LA_MODE) {
+ int mode = la->la_mode;
+ /* chmod */
+ if (la->la_mode == (umode_t)-1)
+ mode = tmp_la->la_mode;
+ la->la_mode =
+ (mode & S_IALLUGO) | (tmp_la->la_mode & ~S_IALLUGO);
+ }
+ RETURN(rc);
}
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct mdd_device *mdd = mdo2mdd(obj);
struct thandle *handle;
- int rc;
+ struct lov_mds_md *lmm = NULL;
+ int rc = 0, lmm_size = 0, max_size;
ENTRY;
mdd_txn_param_build(ctxt, &MDD_TXN_ATTR_SET);
handle = mdd_trans_start(ctxt, mdd);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
+ /*TODO: add lock here*/
+ /* start a log jounal handle if needed */
+ if (S_ISREG(mdd_object_type(mdd_obj)) &&
+ ma->ma_attr.la_valid & (LA_UID | LA_GID)) {
+ mdd_lov_mdsize(ctxt, mdd, &max_size);
+ OBD_ALLOC(lmm, max_size);
+ if (lmm == NULL)
+ GOTO(cleanup, rc = -ENOMEM);
+
+ rc = mdd_get_md(ctxt, mdd_obj, lmm, &lmm_size, 1);
+
+ if (rc < 0)
+ GOTO(cleanup, rc);
+ }
- mdd_lock(ctxt, mdd_obj, DT_WRITE_LOCK);
-
- rc = mdd_attr_set_internal(ctxt, mdd_obj, &ma->ma_attr, handle);
- if (rc == 0 && (ma->ma_valid & MA_LOV)) {
- /* set LOV ea now */
- rc = __mdd_xattr_set(ctxt, mdd_obj,
- ma->ma_lmm, ma->ma_lmm_size,
- XATTR_NAME_LOV, 0, handle);
+ if (ma->ma_attr.la_valid & (ATTR_MTIME | ATTR_CTIME))
+ CDEBUG(D_INODE, "setting mtime "LPU64", ctime "LPU64"\n",
+ ma->ma_attr.la_mtime, ma->ma_attr.la_ctime);
+
+ rc = mdd_fix_attr(ctxt, mdd_obj, ma);
+ if (rc)
+ GOTO(cleanup, rc);
+ if (ma->ma_attr_flags & MD_ATTR_FLAG) { /* ioctl */
+ rc = -ENOTSUPP;
+ } else if (ma->ma_attr.la_valid) { /* setattr */
+ mdd_lock(ctxt, mdd_obj, DT_WRITE_LOCK);
+ rc = mdd_attr_set_internal(ctxt, mdd_obj, &ma->ma_attr, handle);
+ mdd_unlock(ctxt, mdd_obj, DT_WRITE_LOCK);
+
+ /* journal chown/chgrp in llog, just like unlink */
+ if (rc == 0 && lmm_size){
+ /*TODO set_attr llog */
+ }
}
- /* XXX: llog cancel cookie? */
- mdd_unlock(ctxt, mdd_obj, DT_WRITE_LOCK);
+ if (rc == 0 && ma->ma_valid & MA_LOV) {
+ if ((S_ISREG(mdd_object_type(mdd_obj)) ||
+ S_ISDIR(mdd_object_type(mdd_obj)))) {
+ /*TODO check permission*/
+ rc = mdd_lov_set_md(ctxt, NULL, mdd_obj, ma->ma_lmm,
+ ma->ma_lmm_size, handle, 1);
+ }
+
+ }
+cleanup:
mdd_trans_stop(ctxt, mdd, handle);
-
+ if (rc == 0 && lmm_size) {
+ /*set obd attr, if needed*/
+ rc = mdd_lov_setattr_async(ctxt, mdd_obj, lmm, lmm_size);
+ }
+ if (lmm != NULL) {
+ OBD_FREE(lmm, max_size);
+ }
+
RETURN(rc);
}
-int mdd_xattr_set_txn(const struct lu_context *ctxt, struct md_object *obj,
+int mdd_xattr_set_txn(const struct lu_context *ctxt, struct mdd_object *obj,
const void *buf, int buf_len, const char *name, int fl,
struct thandle *handle)
{
- struct mdd_object *mdd_obj = md2mdd_obj(obj);
int rc;
ENTRY;
- mdd_lock(ctxt, mdd_obj, DT_WRITE_LOCK);
- rc = __mdd_xattr_set(ctxt, mdd_obj, buf, buf_len, name,
+ mdd_lock(ctxt, obj, DT_WRITE_LOCK);
+ rc = __mdd_xattr_set(ctxt, obj, buf, buf_len, name,
fl, handle);
- mdd_unlock(ctxt, mdd_obj, DT_WRITE_LOCK);
+ mdd_unlock(ctxt, obj, DT_WRITE_LOCK);
RETURN(rc);
}
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
- rc = mdd_xattr_set_txn(ctxt, obj, buf, buf_len, name, fl, handle);
+ rc = mdd_xattr_set_txn(ctxt, md2mdd_obj(obj), buf, buf_len, name,
+ fl, handle);
mdd_trans_stop(ctxt, mdd, handle);
{
int rc;
ENTRY;
- rc = __mdd_attr_get(ctxt, obj, ma);
+
+ rc = mdd_attr_get_internal(ctxt, obj, ma, 0);
if (rc)
RETURN(rc);
if (atomic_read(&obj->mod_count) == 0 &&
- ma->ma_attr.la_nlink == 0) {
- rc = __mdd_lov_get(ctxt, obj, ma);
- if (rc) {
- CERROR("Can't get LOV attr during unlink()\n");
- }
- if(S_ISREG(ma->ma_attr.la_mode) &&
- ma->ma_valid & MA_LOV)
+ ma->ma_attr.la_nlink == 0 && S_ISREG(mdd_object_type(obj))) {
+ rc = __mdd_lmm_get(ctxt, obj, ma);
+ if(S_ISREG(ma->ma_attr.la_mode) && ma->ma_valid & MA_LOV)
rc = mdd_unlink_log(ctxt, mdo2mdd(&obj->mod_obj),
- obj, ma);
+ obj, ma);
}
RETURN(rc);
}
/* unlink dotdot */
__mdd_ref_del(ctxt, mdd_pobj, handle);
}
+ rc = mdd_attr_get_internal(ctxt, mdd_cobj, ma, 0);
+ if (rc)
+ GOTO(cleanup, rc);
rc = __mdd_finish_unlink(ctxt, mdd_cobj, ma);
__mdd_ref_del(ctxt, mdd_tobj, handle);
if (S_ISDIR(mdd_object_type(mdd_tobj)))
__mdd_ref_del(ctxt, mdd_tpobj, handle);
- else
- rc = mdd_attr_get(ctxt, tobj, ma);
+ else {
+ rc = mdd_attr_get_internal(ctxt, mdd_tobj, ma, 0);
+ if (rc)
+ GOTO(cleanup, rc);
+ }
+
mdd_set_dead_obj(mdd_tobj);
}
cleanup:
int rc;
ENTRY;
+ rc = mdd_lov_create(ctxt, mdd, mdd_pobj, son, &lmm, &lmm_size, spec,
+ attr);
+ if (rc)
+ RETURN(rc);
+
mdd_txn_param_build(ctxt, &MDD_TXN_CREATE_DATA);
handle = mdd_trans_start(ctxt, mdd);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
- rc = mdd_lov_create(ctxt, mdd, mdd_pobj, son, &lmm, &lmm_size, spec,
- attr);
if (rc == 0) {
- rc = mdd_lov_set_md(ctxt, pobj, cobj, lmm,
- lmm_size, attr, handle);
+ rc = mdd_lov_set_md(ctxt, mdd_pobj, son, lmm, lmm_size,
+ handle, 0);
if (rc == 0)
- rc = mdd_attr_get(ctxt, cobj, ma);
+ rc = mdd_attr_get_internal(ctxt, son, ma, 1);
}
mdd_trans_stop(ctxt, mdd, handle);
GOTO(cleanup, rc);
inserted = 1;
- rc = mdd_lov_set_md(ctxt, pobj, child, lmm, lmm_size, attr, handle);
+ rc = mdd_lov_set_md(ctxt, mdd_pobj, son, lmm, lmm_size, handle, 0);
if (rc) {
CERROR("error on stripe info copy %d \n", rc);
GOTO(cleanup, rc);
rc = -EFAULT;
}
/* return attr back */
- mdd_attr_get(ctxt, child, ma);
+ rc = mdd_attr_get_internal(ctxt, son, ma, 1);
cleanup:
if (rc && created) {
int rc2 = 0;
/* XXX: parent fid is needed here
rc = __mdd_object_initialize(ctxt, mdo, son, ma, handle);
*/
- mdd_attr_get(ctxt, obj, ma);
+ if (rc)
+ GOTO(out, rc);
- mdd_trans_stop(ctxt, mdd, handle);
+ rc = mdd_attr_get_internal(ctxt, md2mdd_obj(obj), ma, 1);
+ mdd_trans_stop(ctxt, mdd, handle);
+out:
RETURN(rc);
}
/* partial operation */
}
__mdd_ref_del(ctxt, mdd_obj, handle);
+
if (S_ISDIR(lu_object_attr(&obj->mo_lu))) {
/* unlink dot */
__mdd_ref_del(ctxt, mdd_obj, handle);
int mdd_init_obd(const struct lu_context *ctxt, struct mdd_device *mdd,
char *dev);
-int mdd_xattr_set_txn(const struct lu_context *ctxt, struct md_object *obj,
+int mdd_xattr_set_txn(const struct lu_context *ctxt, struct mdd_object *obj,
const void *buf, int buf_len, const char *name, int fl,
struct thandle *txn);
-int mdd_lov_set_md(const struct lu_context *ctxt, struct md_object *pobj,
- struct md_object *child, struct lov_mds_md *lmm,
- int lmm_size, struct lu_attr *la, struct thandle *handle);
+int mdd_lov_set_md(const struct lu_context *ctxt, struct mdd_object *pobj,
+ struct mdd_object *child, struct lov_mds_md *lmm,
+ int lmm_size, struct thandle *handle, int set_stripe);
int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd,
struct mdd_object *parent, struct mdd_object *child,
struct lov_mds_md **lmm, int *lmm_size,
const struct md_create_spec *spec, struct lu_attr *la);
-int mdd_get_md(const struct lu_context *ctxt, struct md_object *obj,
- void *md, int *md_size);
+int mdd_get_md(const struct lu_context *ctxt, struct mdd_object *obj,
+ void *md, int *md_size, int need_locked);
int mdd_unlink_log(const struct lu_context *ctxt, struct mdd_device *mdd,
struct mdd_object *mdd_cobj, struct md_attr *ma);
int mdd_attr_set_internal(const struct lu_context *ctxt, struct mdd_object *o,
const struct lu_attr *attr, struct thandle *handle);
+int mdd_get_cookie_size(const struct lu_context *ctxt, struct mdd_device *mdd,
+ struct lov_mds_md *lmm);
+
+int mdd_lov_setattr_async(const struct lu_context *ctxt, struct mdd_object *obj,
+ struct lov_mds_md *lmm, int lmm_size);
struct mdd_thread_info *mdd_ctx_info(const struct lu_context *ctx);
+void mdd_lock(const struct lu_context *ctxt, struct mdd_object *obj,
+ enum dt_lock_mode mode);
+void mdd_unlock(const struct lu_context *ctxt, struct mdd_object *obj,
+ enum dt_lock_mode mode);
extern struct lu_device_operations mdd_lu_ops;
static inline int lu_device_is_mdd(struct lu_device *d)
{
return lu_object_fid(&obj->mod_obj.mo_lu);
}
+static inline umode_t mdd_object_type(const struct mdd_object *obj)
+{
+ return lu_object_attr(&obj->mod_obj.mo_lu);
+}
+
int mdd_lov_mdsize(const struct lu_context *ctxt, struct mdd_device *mdd,
int *md_size);
int mdd_lov_cookiesize(const struct lu_context *ctxt, struct mdd_device *mdd,
RETURN(rc);
}
-int mdd_get_md(const struct lu_context *ctxt, struct md_object *obj,
- void *md, int *md_size)
+int mdd_get_md(const struct lu_context *ctxt, struct mdd_object *obj,
+ void *md, int *md_size, int need_locked)
{
struct dt_object *next;
int rc = 0;
ENTRY;
- next = mdd_object_child(md2mdd_obj(obj));
+ if (need_locked)
+ mdd_lock(ctxt, obj, DT_READ_LOCK);
+ next = mdd_object_child(obj);
rc = next->do_ops->do_xattr_get(ctxt, next, md, *md_size,
MDS_LOV_MD_NAME);
/*
*md_size = rc;
}
+ if (need_locked)
+ mdd_unlock(ctxt, obj, DT_READ_LOCK);
+
RETURN (rc);
}
-int mdd_lov_set_md(const struct lu_context *ctxt, struct md_object *pobj,
- struct md_object *child, struct lov_mds_md *lmmp,
- int lmm_size, struct lu_attr *la, struct thandle *handle)
+static int mdd_lov_set_stripe_md(const struct lu_context *ctxt,
+ struct mdd_object *obj, struct lov_mds_md *lmmp,
+ int lmm_size, struct thandle *handle)
{
- struct lu_attr *tmp_la = &mdd_ctx_info(ctxt)->mti_la;
+ struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
+ struct obd_device *obd = mdd2_obd(mdd);
+ struct obd_export *lov_exp = obd->u.mds.mds_osc_exp;
+ struct lov_stripe_md *lsm = NULL;
+ int rc;
+ ENTRY;
+
+ LASSERT(S_ISDIR(mdd_object_type(obj)) && S_ISREG(mdd_object_type(obj)));
+
+ rc = obd_iocontrol(OBD_IOC_LOV_SETSTRIPE, lov_exp, 0, &lsm, lmmp);
+ if (rc)
+ RETURN(rc);
+ obd_free_memmd(lov_exp, &lsm);
+
+ rc = mdd_xattr_set_txn(ctxt, obj, lmmp, lmm_size, MDS_LOV_MD_NAME, 0,
+ handle);
+
+ CDEBUG(D_INFO, "set lov ea of "DFID" rc %d \n", PFID(mdo2fid(obj)), rc);
+ RETURN(rc);
+}
+
+static int mdd_lov_set_dir_md(const struct lu_context *ctxt,
+ struct mdd_object *obj, struct lov_mds_md *lmmp,
+ int lmm_size, struct thandle *handle)
+{
+ struct lov_user_md *lum = NULL;
int rc = 0;
ENTRY;
- LASSERT(la->la_valid & LA_MODE);
- if (S_ISREG(la->la_mode) && lmm_size > 0) {
- LASSERT(lmmp != NULL);
- rc = mdd_xattr_set_txn(ctxt, child, lmmp, lmm_size,
- MDS_LOV_MD_NAME, 0, handle);
- if (rc) {
- CERROR("error on set stripe info: rc = %d\n", rc);
- RETURN(rc);
- }
- if (la->la_valid & LA_BLKSIZE) {
- tmp_la->la_valid = LA_BLKSIZE;
- tmp_la->la_blksize = la->la_blksize;
- rc = mdd_attr_set_internal(ctxt, md2mdd_obj(child), tmp_la,
- handle);
+ /*TODO check permission*/
+ LASSERT(S_ISDIR(mdd_object_type(obj)));
+ lum = (struct lov_user_md*)lmmp;
+
+ /* if { size, offset, count } = { 0, -1, 0 } (i.e. all default
+ * values specified) then delete default striping from dir. */
+ if ((lum->lmm_stripe_size == 0 && lum->lmm_stripe_count == 0 &&
+ lum->lmm_stripe_offset == (typeof(lum->lmm_stripe_offset))(-1)) ||
+ /* lmm_stripe_size == -1 is deprecated in 1.4.6 */
+ lum->lmm_stripe_size == (typeof(lum->lmm_stripe_size))(-1)){
+ rc = mdd_xattr_set_txn(ctxt, obj, NULL, 0, MDS_LOV_MD_NAME, 0,
+ handle);
+ CDEBUG(D_INFO, "delete lov ea of "DFID" rc %d \n",
+ PFID(mdo2fid(obj)), rc);
+ } else {
+ rc = mdd_lov_set_stripe_md(ctxt, obj, lmmp, lmm_size, handle);
+ }
+ RETURN(rc);
+}
+
+int mdd_lov_set_md(const struct lu_context *ctxt, struct mdd_object *pobj,
+ struct mdd_object *child, struct lov_mds_md *lmmp,
+ int lmm_size, struct thandle *handle, int set_stripe)
+{
+ int rc = 0;
+ ENTRY;
+
+ if (S_ISREG(mdd_object_type(child)) && lmm_size > 0) {
+ if (set_stripe) {
+ rc = mdd_lov_set_stripe_md(ctxt, child, lmmp, lmm_size,
+ handle);
+ } else {
+ rc = mdd_xattr_set_txn(ctxt, child, lmmp, lmm_size,
+ MDS_LOV_MD_NAME, 0, handle);
}
- } else if (S_ISDIR(la->la_mode)) {
- struct lov_mds_md *lmm = &mdd_ctx_info(ctxt)->mti_lmm;
- int size = sizeof(lmm);
- rc = mdd_get_md(ctxt, pobj, &lmm, &size);
- if (rc > 0) {
- rc = mdd_xattr_set_txn(ctxt, child, lmm, size,
- /*
- * Flags are 0: we don't care
- * whether attribute exists
- * already.
- */
+ } else if (S_ISDIR(mdd_object_type(child))) {
+ if (lmmp == NULL && lmm_size == 0) {
+ struct lov_mds_md *lmm = &mdd_ctx_info(ctxt)->mti_lmm;
+ int size = sizeof(lmm);
+ /*Get parent dir stripe and set*/
+ rc = mdd_get_md(ctxt, pobj, &lmm, &size, 0);
+ if (rc > 0) {
+ rc = mdd_xattr_set_txn(ctxt, child, lmm, size,
MDS_LOV_MD_NAME, 0, handle);
- if (rc)
- CERROR("error on copy stripe info: rc = %d\n",
- rc);
+ if (rc)
+ CERROR("error on copy stripe info: rc = %d\n",
+ rc);
+ }
+ } else {
+ LASSERT(lmmp != NULL && lmm_size > 0);
+ /*delete lmm*/
+ rc = mdd_lov_set_dir_md(ctxt, child, lmmp, lmm_size, handle);
}
}
-
+ CDEBUG(D_INFO, "Set lov md %p size %d for fid "DFID" rc%d/n",
+ lmmp, lmm_size, PFID(mdo2fid(child)), rc);
RETURN(rc);
}
if (__lmm == NULL)
GOTO(out_oa, rc = -ENOMEM);
- rc = mdd_get_md(ctxt, &parent->mod_obj, __lmm,
- &returned_lmm_size);
+ rc = mdd_get_md(ctxt, parent, __lmm,
+ &returned_lmm_size, 1);
if (rc > 0)
rc = obd_iocontrol(OBD_IOC_LOV_SETSTRIPE,
lov_exp, 0, &lsm, __lmm);
* by filter_fid, but can not see what is the usages. So just
* pack o_seq o_ver here, maybe fix it after this cycle*/
oa->o_fid = lu_object_fid(mdd2lu_obj(child))->f_seq;
- oa->o_generation = lu_object_fid(mdd2lu_obj(child))->f_ver;
+ oa->o_generation = lu_object_fid(mdd2lu_obj(child))->f_oid;
oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
rc = obd_setattr(lov_exp, oa, lsm, NULL);
}
return 0;
}
+int mdd_lov_setattr_async(const struct lu_context *ctxt, struct mdd_object *obj,
+ struct lov_mds_md *lmm, int lmm_size)
+{
+ struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
+ struct obd_device *obd = mdd2_obd(mdd);
+ struct lu_attr *tmp_la = &mdd_ctx_info(ctxt)->mti_la;
+ struct dt_object *next = mdd_object_child(obj);
+ __u32 seq = lu_object_fid(mdd2lu_obj(obj))->f_seq;
+ __u32 oid = lu_object_fid(mdd2lu_obj(obj))->f_oid;
+ int rc = 0;
+ ENTRY;
+
+ rc = next->do_ops->do_attr_get(ctxt, next, tmp_la);
+ if (rc)
+ RETURN(rc);
+
+ rc = mds_osc_setattr_async(obd, tmp_la->la_uid, tmp_la->la_gid, lmm,
+ lmm_size, NULL, seq, oid);
+
+ RETURN(rc);
+}
int mdd_lov_mdsize(const struct lu_context *ctxt, struct mdd_device *mdd,
int *md_size)
__u64 child_lockpart);
int mds_lock_new_child(struct obd_device *obd, struct inode *inode,
struct lustre_handle *child_lockh);
-int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode,
- struct lov_mds_md *lmm, int lmm_size,
- struct llog_cookie *logcookies, struct ll_fid *fid);
int mds_get_parents_children_locked(struct obd_device *obd,
struct mds_obd *mds,
obd_free_memmd(mds->mds_osc_exp, &lsm);
RETURN(rc);
}
+EXPORT_SYMBOL(mds_log_op_setattr);
static struct llog_operations mds_ost_orig_logops = {
lop_add: mds_llog_origin_add,
l_dput(de);
}
-int mds_osc_setattr_async(struct obd_device *obd, struct inode *inode,
+int mds_osc_setattr_async(struct obd_device *obd, __u32 uid, __u32 gid,
struct lov_mds_md *lmm, int lmm_size,
- struct llog_cookie *logcookies, struct ll_fid *fid)
+ struct llog_cookie *logcookies, __u64 id, __u32 gen)
{
struct mds_obd *mds = &obd->u.mds;
struct lov_stripe_md *lsm = NULL;
rc = obd_unpackmd(mds->mds_osc_exp, &lsm, lmm, lmm_size);
if (rc < 0) {
- CERROR("Error unpack md %p for inode %lu\n", lmm, inode->i_ino);
+ CERROR("Error unpack md %p for inode "LPU64"\n", lmm, id);
GOTO(out, rc);
}
/* then fill oa */
oa->o_id = lsm->lsm_object_id;
- oa->o_uid = inode->i_uid;
- oa->o_gid = inode->i_gid;
+ oa->o_uid = uid;
+ oa->o_gid = gid;
oa->o_valid = OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;
if (logcookies) {
oa->o_valid |= OBD_MD_FLCOOKIE;
oti.oti_logcookies = logcookies;
}
- LASSERT(fid != NULL);
- oa->o_fid = fid->id;
- oa->o_generation = fid->generation;
+ oa->o_fid = id;
+ oa->o_generation = gen;
oa->o_valid |= OBD_MD_FLFID | OBD_MD_FLGENER;
/* do setattr from mds to ost asynchronously */
obdo_free(oa);
RETURN(rc);
}
+EXPORT_SYMBOL(mds_osc_setattr_async);
/* In the raw-setattr case, we lock the child inode.
* In the write-back case or if being called from open, the client holds a lock
err = mds_finish_transno(mds, inode, handle, req, rc, 0);
/* do mds to ost setattr if needed */
if (!rc && !err && lmm_size)
- mds_osc_setattr_async(obd, inode, lmm, lmm_size,
- logcookies, rec->ur_fid1);
+ mds_osc_setattr_async(obd, inode->i_ino, inode->i_generation, lmm,
+ lmm_size, logcookies, rec->ur_fid1->id,
+ rec->ur_fid1->generation);
switch (cleanup_phase) {
case 2:
ma->ma_lmm = req_capsule_server_get(pill, &RMF_MDT_MD);
ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_MDT_MD, RCL_SERVER);
- rc = mo_attr_get(ctxt, next, &info->mti_attr);
+ ma->ma_need = MA_INODE | MA_LOV;
+ rc = mo_attr_get(ctxt, next, ma);
if (rc == -EREMOTE) {
/* This object is located on remote node.*/
repbody->fid1 = *mdt_object_fid(o);
const struct lu_fid *fid;
next = mdt_object_child(info->mti_object);
fid = mdt_object_fid(info->mti_object);
+ info->mti_attr.ma_need = MA_INODE;
rc = mo_attr_get(info->mti_ctxt,
next, &info->mti_attr);
if (rc == 0) {
DEF_MDT_HNDL_F(0 |HABEO_REFERO, STATFS, mdt_statfs),
DEF_MDT_HNDL_F(0 |MUTABOR,
REINT, mdt_reint),
-DEF_MDT_HNDL_F(HABEO_CORPUS|HABEO_REFERO, CLOSE, mdt_close),
+DEF_MDT_HNDL_F(HABEO_CORPUS , CLOSE, mdt_close),
DEF_MDT_HNDL_0(0, DONE_WRITING, mdt_done_writing),
DEF_MDT_HNDL_F(0 |HABEO_REFERO, PIN, mdt_pin),
DEF_MDT_HNDL_0(0, SYNC, mdt_sync),
};
enum mdt_reint_flag {
- MRF_SETATTR_LOCKED = 1 << 0
+ MRF_SETATTR_LOCKED = 1 << 0,
};
enum {
RETURN(0);
}
-static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr)
+static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
+ struct md_attr *ma)
{
__u64 out;
if (in & ATTR_FROM_OPEN)
rr->rr_flags |= MRF_SETATTR_LOCKED;
+ if (in & ATTR_ATIME_SET)
+ ma->ma_attr_flags |= MD_ATIME_SET;
+
+ if (in & ATTR_CTIME_SET)
+ ma->ma_attr_flags |= MD_CTIME_SET;
+
+ if (in & ATTR_MTIME_SET)
+ ma->ma_attr_flags |= MD_MTIME_SET;
+
+ if (in & ATTR_ATTR_FLAG)
+ ma->ma_attr_flags |= MD_ATTR_FLAG;
+
+ if (in & ATTR_RAW)
+ ma->ma_attr_flags |= MD_ATTR_RAW;
+
in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|
- ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN);
+ ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
+ ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
+ ATTR_ATTR_FLAG|ATTR_RAW);
if (in != 0)
CERROR("Unknown attr bits: %#llx\n", in);
return out;
RETURN(-EFAULT);
rr->rr_fid1 = &rec->sa_fid;
- la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr);
+ la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
la->la_mode = rec->sa_mode;
la->la_uid = rec->sa_uid;
la->la_gid = rec->sa_gid;
OBD_FREE_PTR(mfd);
}
-static int mdt_create_data_obj(struct mdt_thread_info *info,
- struct mdt_object *p, struct mdt_object *o)
+static int mdt_create_data(struct mdt_thread_info *info,
+ struct mdt_object *p, struct mdt_object *o)
{
struct md_attr *ma = &info->mti_attr;
/* XXX: md_create_spec using should be made clear
*/
struct md_create_spec *spec = &info->mti_spec;
+ ma->ma_need = MA_INODE | MA_LOV;
return mdo_create_data(info->mti_ctxt, mdt_object_child(p),
mdt_object_child(o), spec, ma);
}
if (!created) {
/* we have to get attr & lov ea for this object*/
+ ma->ma_need = MA_INODE | MA_LOV;
rc = mo_attr_get(info->mti_ctxt, mdt_object_child(o), ma);
if (rc)
RETURN(rc);
&RMF_MDT_MD,
RCL_SERVER);
LASSERT(p != NULL);
- rc = mdt_create_data_obj(info, p, o);
+ rc = mdt_create_data(info, p, o);
if (rc)
RETURN(rc);
}
} else {
rc = -ENOENT;
if (flags & MDS_OPEN_CREAT) {
+ info->mti_attr.ma_need = MA_INODE | MA_LOV;
rc = mo_object_create(info->mti_ctxt,
mdt_object_child(o),
&info->mti_spec,
if (result == -ENOENT) {
/* not found and with MDS_OPEN_CREAT: let's create it */
+ ma->ma_need = MA_INODE | MA_LOV;
result = mdo_create(info->mti_ctxt,
mdt_object_child(parent),
rr->rr_name,
finish_open:
if (result != 0 && created) {
+ ma->ma_need = 0;
int rc2 = mdo_unlink(info->mti_ctxt, mdt_object_child(parent),
mdt_object_child(child), rr->rr_name,
&info->mti_attr);
int rc;
ENTRY;
+ req_capsule_set_size(&info->mti_pill, &RMF_MDT_MD, RCL_SERVER,
+ info->mti_mdt->mdt_max_mdsize);
+ req_capsule_set_size(&info->mti_pill, &RMF_LOGCOOKIES, RCL_SERVER,
+ info->mti_mdt->mdt_max_cookiesize);
+ rc = req_capsule_pack(&info->mti_pill);
+ if (rc)
+ RETURN(rc);
+
med = &mdt_info_req(info)->rq_export->exp_mdt_data;
spin_lock(&med->med_open_lock);
ma->ma_lmm_size = req_capsule_get_size(&info->mti_pill,
&RMF_MDT_MD,
RCL_SERVER);
+
+ ma->ma_cookie = req_capsule_server_get(&info->mti_pill,
+ &RMF_LOGCOOKIES);
+ ma->ma_cookie_size = req_capsule_get_size(&info->mti_pill,
+ &RMF_LOGCOOKIES,
+ RCL_SERVER);
+ ma->ma_need = MA_INODE;
o = mfd->mfd_object;
mdt_mfd_close(info->mti_ctxt, info->mti_mdt, mfd, ma);
rc = mdt_handle_last_unlink(info, o, ma);
if (!IS_ERR(child)) {
struct md_object *next = mdt_object_child(parent);
+ ma->ma_need = MA_INODE;
rc = mdo_create(info->mti_ctxt, next, rr->rr_name,
mdt_object_child(child), &info->mti_spec,
/* rr->rr_tgt, NULL, 0, */
if (!IS_ERR(o)) {
struct md_object *next = mdt_object_child(o);
+ ma->ma_need = MA_INODE | MA_LOV;
rc = mo_object_create(info->mti_ctxt, next,
&info->mti_spec, ma);
if (rc == 0) {
if (rc != 0)
GOTO(out_unlock, rc);
+ info->mti_attr.ma_need = MA_INODE;
rc = mo_attr_get(info->mti_ctxt, next, &info->mti_attr);
if (rc != 0)
GOTO(out_unlock, rc);
if (!ma->ma_lmm || !ma->ma_cookie)
GOTO(out_unlock_parent, rc = -EINVAL);
+ /*Now we can only make sure we need MA_INODE, in mdd layer,
+ *will check whether need MA_LOV and MA_COOKIE*/
+ ma->ma_need = MA_INODE;
rc = mdo_unlink(info->mti_ctxt, mdt_object_child(mp),
mdt_object_child(mc), rr->rr_name, ma);
if (rc)
GOTO(out_unlock_child, rc);
+
rc = mdt_handle_last_unlink(info, mc, ma);
GOTO(out_unlock_child, rc);
if (!ma->ma_lmm || !ma->ma_cookie)
GOTO(out_unlock_new, rc = -EINVAL);
+ ma->ma_need = MA_INODE | MA_LOV | MA_COOKIE;
rc = mdo_rename(info->mti_ctxt, mdt_object_child(msrcdir),
mdt_object_child(mtgtdir), old_fid,
rr->rr_name, mnew ? mdt_object_child(mnew): NULL,
rr->rr_tgt, ma);
- /*TODO: handle tgt object*/
+ /*TODO: handle last link of tgt object*/
out_unlock_new:
if (mnew) {