#include <lprocfs_status.h>
/* fid_be_cpu(), fid_cpu_to_be(). */
#include <lustre_fid.h>
-#include <obd_lov.h>
#include <lustre_idmap.h>
#include <lustre_param.h>
#include <lustre_mds.h>
#include "mdd_internal.h"
static const struct lu_object_operations mdd_lu_obj_ops;
-extern struct kmem_cache *mdd_object_kmem;
static int mdd_xattr_get(const struct lu_env *env,
struct md_object *obj, struct lu_buf *buf,
const char *name);
-int mdd_data_get(const struct lu_env *env, struct mdd_object *obj,
- void **data)
-{
- 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;
- }
- mdo_data_get(env, obj, data);
- return 0;
-}
-
int mdd_la_get(const struct lu_env *env, struct mdd_object *obj,
struct lu_attr *la, struct lustre_capa *capa)
{
return mdo_attr_get(env, obj, la, capa);
}
-static void mdd_flags_xlate(struct mdd_object *obj, __u32 flags)
+void mdd_flags_xlate(struct mdd_object *obj, __u32 flags)
{
obj->mod_flags &= ~(APPEND_OBJ|IMMUTE_OBJ);
return info;
}
-const struct lu_name *mdd_name_get_const(const struct lu_env *env,
- const void *area, ssize_t len)
-{
- struct lu_name *lname;
-
- lname = &mdd_env_info(env)->mti_name;
- lname->ln_name = area;
- lname->ln_namelen = len;
- return lname;
-}
-
struct lu_buf *mdd_buf_get(const struct lu_env *env, void *area, ssize_t len)
{
struct lu_buf *buf;
}
struct lu_object *mdd_object_alloc(const struct lu_env *env,
- const struct lu_object_header *hdr,
- struct lu_device *d)
+ const struct lu_object_header *hdr,
+ struct lu_device *d)
{
- struct mdd_object *mdd_obj;
-
- OBD_SLAB_ALLOC_PTR_GFP(mdd_obj, mdd_object_kmem, __GFP_IO);
- if (mdd_obj != NULL) {
- struct lu_object *o;
-
- o = mdd2lu_obj(mdd_obj);
- lu_object_init(o, NULL, d);
- mdd_obj->mod_obj.mo_ops = &mdd_obj_ops;
- mdd_obj->mod_obj.mo_dir_ops = &mdd_dir_ops;
- mdd_obj->mod_count = 0;
- o->lo_ops = &mdd_lu_obj_ops;
- return o;
- } else {
- return NULL;
- }
+ struct mdd_object *mdd_obj;
+
+ OBD_SLAB_ALLOC_PTR_GFP(mdd_obj, mdd_object_kmem, GFP_NOFS);
+ if (mdd_obj != NULL) {
+ struct lu_object *o;
+
+ o = mdd2lu_obj(mdd_obj);
+ lu_object_init(o, NULL, d);
+ mdd_obj->mod_obj.mo_ops = &mdd_obj_ops;
+ mdd_obj->mod_obj.mo_dir_ops = &mdd_dir_ops;
+ mdd_obj->mod_count = 0;
+ o->lo_ops = &mdd_lu_obj_ops;
+ return o;
+ } else {
+ return NULL;
+ }
}
static int mdd_object_init(const struct lu_env *env, struct lu_object *o,
if (lu_object_exists(o)) {
struct mdd_object *mdd_obj = lu2mdd_obj(o);
- struct lu_attr *attr = MDD_ENV_VAR(env, cattr);
+ struct lu_attr *attr = MDD_ENV_VAR(env, la_for_start);
rc = mdd_la_get(env, mdd_obj, attr, BYPASS_CAPA);
if (rc == 0)
* Permission check is done when open,
* no need check again.
*/
-static int mdd_readlink(const struct lu_env *env, struct md_object *obj,
- struct lu_buf *buf)
+int mdd_readlink(const struct lu_env *env, struct md_object *obj,
+ struct lu_buf *buf)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct dt_object *next;
}
next = mdd_object_child(mdd_obj);
- mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
+ LASSERT(next != NULL);
+ LASSERT(next->do_body_ops != NULL);
+ LASSERT(next->do_body_ops->dbo_read != NULL);
+ mdd_read_lock(env, mdd_obj, MOR_TGT_CHILD);
rc = next->do_body_ops->dbo_read(env, next, buf, &pos,
mdd_object_capa(env, mdd_obj));
mdd_read_unlock(env, mdd_obj);
struct mdd_object *c,
struct lu_attr *attr,
struct thandle *handle,
- const struct md_op_spec *spec)
+ const struct md_op_spec *spec,
+ struct dt_allocation_hint *hint)
{
struct dt_object_format *dof = &mdd_env_info(env)->mti_dof;
- struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
const struct dt_index_features *feat = spec->sp_feat;
int rc;
ENTRY;
int mdd_object_create_internal(const struct lu_env *env, struct mdd_object *p,
struct mdd_object *c, struct lu_attr *attr,
- struct thandle *handle,
- const struct md_op_spec *spec)
+ struct thandle *handle,
+ const struct md_op_spec *spec,
+ struct dt_allocation_hint *hint)
{
- struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
struct dt_object_format *dof = &mdd_env_info(env)->mti_dof;
int rc;
ENTRY;
RETURN(rc);
}
-int mdd_changelog(const struct lu_env *env, enum changelog_rec_type type,
- int flags, struct md_object *obj)
+static int mdd_changelog(const struct lu_env *env, enum changelog_rec_type type,
+ int flags, struct md_object *obj)
{
struct thandle *handle;
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct mdd_device *mdd = mdo2mdd(obj);
int bits, type = 0;
- bits = (valid & ~(LA_CTIME|LA_MTIME|LA_ATIME)) ? 1 << CL_SETATTR : 0;
+ bits = (valid & LA_SIZE) ? 1 << CL_TRUNC : 0;
+ bits |= (valid & ~(LA_CTIME|LA_MTIME|LA_ATIME)) ? 1 << CL_SETATTR : 0;
bits |= (valid & LA_MTIME) ? 1 << CL_MTIME : 0;
bits |= (valid & LA_CTIME) ? 1 << CL_CTIME : 0;
bits |= (valid & LA_ATIME) ? 1 << CL_ATIME : 0;
bits = bits & mdd->mdd_cl.mc_mask;
+ /* This is an implementation limit rather than a protocol limit */
+ CLASSERT(CL_LAST <= sizeof(int) * 8);
if (bits == 0)
return 0;
/* The record type is the lowest non-masked set bit */
- while (bits && ((bits & 1) == 0)) {
- bits = bits >> 1;
- type++;
- }
+ type = __ffs(bits);
/* FYI we only store the first CLF_FLAGMASK bits of la_valid */
return mdd_changelog_data_store(env, mdd, type, (int)valid,
CDEBUG(D_INODE, "setting mtime "LPU64", ctime "LPU64"\n",
la->la_mtime, la->la_ctime);
- if (la_copy->la_valid & LA_FLAGS) {
+ mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+ if (la_copy->la_valid & LA_FLAGS) {
rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 1);
- if (rc == 0)
- mdd_flags_xlate(mdd_obj, la_copy->la_flags);
- } else if (la_copy->la_valid) { /* setattr */
+ if (rc == 0)
+ mdd_flags_xlate(mdd_obj, la_copy->la_flags);
+ } else if (la_copy->la_valid) { /* setattr */
rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 1);
- }
+ }
+ mdd_write_unlock(env, mdd_obj);
+
+ if (rc == 0)
+ rc = mdd_attr_set_changelog(env, obj, handle, la->la_valid);
+
+ GOTO(stop, rc);
- if (rc == 0)
- rc = mdd_attr_set_changelog(env, obj, handle,
- la->la_valid);
stop:
- mdd_trans_stop(env, mdd, rc, handle);
- RETURN(rc);
+ mdd_trans_stop(env, mdd, rc, handle);
+ return rc;
}
static int mdd_xattr_sanity_check(const struct lu_env *env,
return(rc);
}
+static int mdd_xattr_del(const struct lu_env *env, struct md_object *obj,
+ const char *name);
+
/**
* The caller should guarantee to update the object ctime
* after xattr_set if needed.
if (rc)
RETURN(rc);
- if (!strcmp(name, XATTR_NAME_ACL_ACCESS)) {
- rc = mdd_acl_set(env, mdd_obj, attr, buf, fl);
+ rc = mdd_xattr_sanity_check(env, mdd_obj, attr);
+ if (rc)
RETURN(rc);
+
+ if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0 ||
+ strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) {
+ struct posix_acl *acl;
+
+ /* user may set empty ACL, which should be treated as removing
+ * ACL. */
+ acl = posix_acl_from_xattr(&init_user_ns, buf->lb_buf,
+ buf->lb_len);
+ if (acl == NULL) {
+ rc = mdd_xattr_del(env, obj, name);
+ RETURN(rc);
+ }
+ posix_acl_release(acl);
}
- rc = mdd_xattr_sanity_check(env, mdd_obj, attr);
- if (rc)
+ if (!strcmp(name, XATTR_NAME_ACL_ACCESS)) {
+ rc = mdd_acl_set(env, mdd_obj, attr, buf, fl);
RETURN(rc);
+ }
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
* The caller should guarantee to update the object ctime
* after xattr_set if needed.
*/
-int mdd_xattr_del(const struct lu_env *env, struct md_object *obj,
- const char *name)
+static int mdd_xattr_del(const struct lu_env *env, struct md_object *obj,
+ const char *name)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct lu_attr *attr = MDD_ENV_VAR(env, cattr);
* read lov EA of an object
* return the lov EA in an allocated lu_buf
*/
-static int mdd_get_lov_ea(const struct lu_env *env,
- struct mdd_object *obj,
- struct lu_buf *lmm_buf)
+int mdd_get_lov_ea(const struct lu_env *env, struct mdd_object *obj,
+ struct lu_buf *lmm_buf)
{
struct lu_buf *buf = &mdd_env_info(env)->mti_big_buf;
- int rc, sz;
+ int rc, bufsize;
ENTRY;
repeat:
}
if (rc < 0)
- GOTO(out, rc);
+ RETURN(rc);
if (rc == 0)
- GOTO(out, rc = -ENODATA);
+ RETURN(-ENODATA);
- sz = rc;
+ bufsize = rc;
if (memcmp(buf, &LU_BUF_NULL, sizeof(*buf)) == 0) {
/* mti_big_buf was not allocated, so we have to
* allocate it based on the ea size */
buf = lu_buf_check_and_alloc(&mdd_env_info(env)->mti_big_buf,
- sz);
+ bufsize);
if (buf->lb_buf == NULL)
GOTO(out, rc = -ENOMEM);
goto repeat;
}
- lu_buf_alloc(lmm_buf, sz);
+ lu_buf_alloc(lmm_buf, bufsize);
if (lmm_buf->lb_buf == NULL)
GOTO(out, rc = -ENOMEM);
- memcpy(lmm_buf->lb_buf, buf->lb_buf, sz);
+ memcpy(lmm_buf->lb_buf, buf->lb_buf, bufsize);
rc = 0;
EXIT;
}
void mdd_object_make_hint(const struct lu_env *env, struct mdd_object *parent,
- struct mdd_object *child, struct lu_attr *attr)
+ struct mdd_object *child, const struct lu_attr *attr,
+ const struct md_op_spec *spec,
+ struct dt_allocation_hint *hint)
{
- struct dt_allocation_hint *hint = &mdd_env_info(env)->mti_hint;
- struct dt_object *np = parent ? mdd_object_child(parent) : NULL;
+ struct dt_object *np = parent ? mdd_object_child(parent) : NULL;
struct dt_object *nc = mdd_object_child(child);
+ memset(hint, 0, sizeof(*hint));
+
+ /* For striped directory, give striping EA to lod_ah_init, which will
+ * decide the stripe_offset and stripe count by it. */
+ if (S_ISDIR(attr->la_mode) &&
+ unlikely(spec != NULL && spec->sp_cr_flags & MDS_OPEN_HAS_EA)) {
+ hint->dah_eadata = spec->u.sp_ea.eadata;
+ hint->dah_eadata_len = spec->u.sp_ea.eadatalen;
+ } else {
+ hint->dah_eadata = NULL;
+ hint->dah_eadata_len = 0;
+ }
+
+ CDEBUG(D_INFO, DFID" eadata %p len %d\n", PFID(mdd_object_fid(child)),
+ hint->dah_eadata, hint->dah_eadata_len);
/* @hint will be initialized by underlying device. */
nc->do_ops->do_ah_init(env, hint, np, nc, attr->la_mode & S_IFMT);
}
return rc;
}
-int mdd_declare_object_kill(const struct lu_env *env, struct mdd_object *obj,
- struct md_attr *ma, struct thandle *handle)
-{
- return mdo_declare_destroy(env, obj, handle);
-}
-
-/* return md_attr back,
- * if it is last unlink then return lov ea + llog cookie*/
-int mdd_object_kill(const struct lu_env *env, struct mdd_object *obj,
- struct md_attr *ma, struct thandle *handle)
-{
- int rc;
- ENTRY;
-
- rc = mdo_destroy(env, obj, handle);
-
- RETURN(rc);
-}
-
static int mdd_declare_close(const struct lu_env *env,
struct mdd_object *obj,
struct md_attr *ma,
__u64 hash = 0;
struct lu_dirent *ent;
struct lu_dirent *last = NULL;
+ struct lu_fid fid;
int first = 1;
memset(area, 0, sizeof (*dp));
/* osd might not able to pack all attributes,
* so recheck rec length */
recsize = le16_to_cpu(ent->lde_reclen);
+
+ if (le32_to_cpu(ent->lde_attrs) & LUDA_FID) {
+ fid_le_to_cpu(&fid, &ent->lde_fid);
+ if (fid_is_dot_lustre(&fid))
+ goto next;
+ }
} else {
result = (last != NULL) ? 0 :-EINVAL;
goto out;
* No pages were processed, mark this for first page
* and send back.
*/
+ dp->ldp_hash_end = cpu_to_le64(MDS_DIR_END_OFF);
dp->ldp_flags = cpu_to_le32(LDF_EMPTY);
rc = min_t(unsigned int, LU_PAGE_SIZE, rdpg->rp_count);
}
static int mdd_object_sync(const struct lu_env *env, struct md_object *obj)
{
- struct mdd_object *mdd_obj = md2mdd_obj(obj);
+ struct mdd_object *mdd_obj = md2mdd_obj(obj);
- if (mdd_object_exists(mdd_obj) == 0) {
- CERROR("%s: object "DFID" not found: rc = -2\n",
- mdd_obj_dev_name(mdd_obj),PFID(mdd_object_fid(mdd_obj)));
- return -ENOENT;
- }
- return dt_object_sync(env, mdd_object_child(mdd_obj));
+ if (mdd_object_exists(mdd_obj) == 0) {
+ int rc = -ENOENT;
+
+ CERROR("%s: object "DFID" not found: rc = %d\n",
+ mdd_obj_dev_name(mdd_obj),
+ PFID(mdd_object_fid(mdd_obj)), rc);
+ return rc;
+ }
+ return dt_object_sync(env, mdd_object_child(mdd_obj),
+ 0, OBD_OBJECT_EOF);
}
static int mdd_object_lock(const struct lu_env *env,
struct md_object *obj,
struct lustre_handle *lh,
struct ldlm_enqueue_info *einfo,
- void *policy)
+ ldlm_policy_data_t *policy)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
return dt_object_lock(env, mdd_object_child(mdd_obj), lh,
einfo, policy);
}
+static int mdd_object_unlock(const struct lu_env *env,
+ struct md_object *obj,
+ struct ldlm_enqueue_info *einfo,
+ ldlm_policy_data_t *policy)
+{
+ struct mdd_object *mdd_obj = md2mdd_obj(obj);
+ return dt_object_unlock(env, mdd_object_child(mdd_obj), einfo, policy);
+}
+
const struct md_object_operations mdd_obj_ops = {
.moo_permission = mdd_permission,
.moo_attr_get = mdd_attr_get,
.moo_capa_get = mdd_capa_get,
.moo_object_sync = mdd_object_sync,
.moo_object_lock = mdd_object_lock,
+ .moo_object_unlock = mdd_object_unlock,
};