X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fmdd%2Fmdd_dir.c;h=5f210b86e4d3148cb4ed046535f9c0fdd4c4fc20;hp=b4994b46cfc5df5829e4bb9ef7de8b023ee90435;hb=f4547f0569774eb794fb143362e201f658415f4c;hpb=5cf3db0c06c2a659683b9ec3271bb4797a70c480 diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index b4994b4..5f210b8 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -27,7 +27,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Whamcloud, Inc. + * Copyright (c) 2011, 2012, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -345,31 +345,31 @@ int mdd_may_unlink(const struct lu_env *env, struct mdd_object *pobj, * VTX feature has been checked already, no need check again. */ static inline int mdd_is_sticky(const struct lu_env *env, - struct mdd_object *pobj, - struct mdd_object *cobj) + struct mdd_object *pobj, + struct mdd_object *cobj) { - struct lu_attr *tmp_la = &mdd_env_info(env)->mti_la; - struct md_ucred *uc = md_ucred(env); - int rc; + struct lu_attr *tmp_la = &mdd_env_info(env)->mti_la; + struct lu_ucred *uc = lu_ucred_assert(env); + int rc; - if (pobj) { - rc = mdd_la_get(env, pobj, tmp_la, BYPASS_CAPA); - if (rc) - return rc; + if (pobj) { + rc = mdd_la_get(env, pobj, tmp_la, BYPASS_CAPA); + if (rc) + return rc; - if (!(tmp_la->la_mode & S_ISVTX) || - (tmp_la->la_uid == uc->mu_fsuid)) - return 0; - } + if (!(tmp_la->la_mode & S_ISVTX) || + (tmp_la->la_uid == uc->uc_fsuid)) + return 0; + } - rc = mdd_la_get(env, cobj, tmp_la, BYPASS_CAPA); - if (rc) - return rc; + rc = mdd_la_get(env, cobj, tmp_la, BYPASS_CAPA); + if (rc) + return rc; - if (tmp_la->la_uid == uc->mu_fsuid) - return 0; + if (tmp_la->la_uid == uc->uc_fsuid) + return 0; - return !mdd_capable(uc, CFS_CAP_FOWNER); + return !mdd_capable(uc, CFS_CAP_FOWNER); } /* @@ -499,27 +499,28 @@ static int __mdd_index_delete_only(const struct lu_env *env, struct mdd_object * } static int __mdd_index_insert_only(const struct lu_env *env, - struct mdd_object *pobj, - const struct lu_fid *lf, const char *name, - struct thandle *handle, - struct lustre_capa *capa) + struct mdd_object *pobj, + const struct lu_fid *lf, const char *name, + struct thandle *handle, + struct lustre_capa *capa) { - struct dt_object *next = mdd_object_child(pobj); - int rc; - ENTRY; + struct dt_object *next = mdd_object_child(pobj); + int rc; + ENTRY; - if (dt_try_as_dir(env, next)) { - struct md_ucred *uc = md_ucred(env); + if (dt_try_as_dir(env, next)) { + struct lu_ucred *uc = lu_ucred_check(env); + int ignore_quota; - rc = next->do_index_ops->dio_insert(env, next, - (struct dt_rec*)lf, - (const struct dt_key *)name, - handle, capa, uc->mu_cap & - CFS_CAP_SYS_RESOURCE_MASK); - } else { - rc = -ENOTDIR; - } - RETURN(rc); + ignore_quota = uc ? uc->uc_cap & CFS_CAP_SYS_RESOURCE_MASK : 1; + rc = next->do_index_ops->dio_insert(env, next, + (struct dt_rec*)lf, + (const struct dt_key *)name, + handle, capa, ignore_quota); + } else { + rc = -ENOTDIR; + } + RETURN(rc); } /* insert named index, add reference if isdir */ @@ -703,12 +704,12 @@ int mdd_changelog_store(const struct lu_env *env, struct mdd_device *mdd, rec->cr_hdr.lrh_type = CHANGELOG_REC; rec->cr.cr_time = cl_time(); - cfs_spin_lock(&mdd->mdd_cl.mc_lock); + spin_lock(&mdd->mdd_cl.mc_lock); /* NB: I suppose it's possible llog_add adds out of order wrt cr_index, * but as long as the MDD transactions are ordered correctly for e.g. * rename conflicts, I don't think this should matter. */ rec->cr.cr_index = ++mdd->mdd_cl.mc_index; - cfs_spin_unlock(&mdd->mdd_cl.mc_lock); + spin_unlock(&mdd->mdd_cl.mc_lock); ctxt = llog_get_context(obd, LLOG_CHANGELOG_ORIG_CTXT); if (ctxt == NULL) @@ -741,12 +742,12 @@ int mdd_changelog_ext_store(const struct lu_env *env, struct mdd_device *mdd, rec->cr_hdr.lrh_type = CHANGELOG_REC; rec->cr.cr_time = cl_time(); - cfs_spin_lock(&mdd->mdd_cl.mc_lock); + spin_lock(&mdd->mdd_cl.mc_lock); /* NB: I suppose it's possible llog_add adds out of order wrt cr_index, * but as long as the MDD transactions are ordered correctly for e.g. * rename conflicts, I don't think this should matter. */ rec->cr.cr_index = ++mdd->mdd_cl.mc_index; - cfs_spin_unlock(&mdd->mdd_cl.mc_lock); + spin_unlock(&mdd->mdd_cl.mc_lock); ctxt = llog_get_context(obd, LLOG_CHANGELOG_ORIG_CTXT); if (ctxt == NULL) @@ -877,7 +878,6 @@ static int mdd_changelog_ext_ns_store(const struct lu_env *env, rec->cr.cr_namelen = tname->ln_namelen; memcpy(rec->cr.cr_name, tname->ln_name, tname->ln_namelen); if (sname) { - LASSERT(sfid != NULL); rec->cr.cr_name[tname->ln_namelen] = '\0'; memcpy(rec->cr.cr_name + tname->ln_namelen + 1, sname->ln_name, sname->ln_namelen); @@ -970,17 +970,17 @@ static int mdd_link(const struct lu_env *env, struct md_object *tgt_obj, if (rc) GOTO(out_unlock, rc); - rc = __mdd_index_insert_only(env, mdd_tobj, mdo2fid(mdd_sobj), - name, handle, - mdd_object_capa(env, mdd_tobj)); - if (rc) - GOTO(out_unlock, rc); - rc = mdo_ref_add(env, mdd_sobj, handle); + if (rc) + GOTO(out_unlock, rc); + + + rc = __mdd_index_insert_only(env, mdd_tobj, mdo2fid(mdd_sobj), + name, handle, + mdd_object_capa(env, mdd_tobj)); if (rc != 0) { - __mdd_index_delete_only(env, mdd_tobj, name, handle, - mdd_object_capa(env, mdd_tobj)); - GOTO(out_unlock, rc); + mdo_ref_del(env, mdd_sobj, handle); + GOTO(out_unlock, rc); } LASSERT(ma->ma_attr.la_valid & LA_CTIME); @@ -1013,15 +1013,15 @@ out_pending: } int mdd_declare_finish_unlink(const struct lu_env *env, - struct mdd_object *obj, - struct md_attr *ma, - struct thandle *handle) + struct mdd_object *obj, + struct md_attr *ma, + struct thandle *handle) { - int rc; + int rc; - rc = orph_declare_index_insert(env, obj, handle); - if (rc) - return rc; + rc = orph_declare_index_insert(env, obj, mdd_object_type(obj), handle); + if (rc) + return rc; return mdo_declare_destroy(env, obj, handle); } @@ -1168,6 +1168,11 @@ static int mdd_unlink(const struct lu_env *env, struct md_object *pobj, if (rc) GOTO(cleanup, rc); + rc = __mdd_index_delete(env, mdd_pobj, name, is_dir, handle, + mdd_object_capa(env, mdd_pobj)); + if (rc) + GOTO(cleanup, rc); + rc = mdo_ref_del(env, mdd_cobj, handle); if (rc != 0) { __mdd_index_insert_only(env, mdd_pobj, mdo2fid(mdd_cobj), @@ -1176,11 +1181,6 @@ static int mdd_unlink(const struct lu_env *env, struct md_object *pobj, GOTO(cleanup, rc); } - rc = __mdd_index_delete(env, mdd_pobj, name, is_dir, handle, - mdd_object_capa(env, mdd_pobj)); - if (rc) - GOTO(cleanup, rc); - if (is_dir) /* unlink dot */ mdo_ref_del(env, mdd_cobj, handle); @@ -1315,21 +1315,12 @@ static int mdd_create_data(const struct lu_env *env, struct md_object *pobj, spec->u.sp_ea.eadata, spec->u.sp_ea.eadatalen, spec->sp_cr_flags, spec->no_create); - if (spec->no_create) { - /* replay case */ + if (spec->no_create || spec->sp_cr_flags & MDS_OPEN_HAS_EA) { + /* replay case or lfs setstripe */ buf = mdd_buf_get_const(env, spec->u.sp_ea.eadata, spec->u.sp_ea.eadatalen); - } else if (!(spec->sp_cr_flags & MDS_OPEN_HAS_OBJS)) { - if (spec->sp_cr_flags & MDS_OPEN_HAS_EA) { - /* lfs setstripe */ - buf = mdd_buf_get_const(env, spec->u.sp_ea.eadata, - spec->u.sp_ea.eadatalen); - } else { - buf = &LU_BUF_NULL; - } } else { - /* MDS_OPEN_HAS_OBJS is not used anymore ? */ - LBUG(); + buf = &LU_BUF_NULL; } rc = dt_declare_xattr_set(env, mdd_object_child(son), buf, @@ -1406,7 +1397,16 @@ int mdd_declare_object_initialize(const struct lu_env *env, { int rc; + /* + * inode mode has been set in creation time, and it's based on umask, + * la_mode and acl, don't set here again! (which will go wrong + * because below function doesn't consider umask). + * I'd suggest set all object attributes in creation time, see above. + */ + LASSERT(attr->la_valid & (LA_MODE | LA_TYPE)); + attr->la_valid &= ~(LA_MODE | LA_TYPE); rc = mdo_declare_attr_set(env, child, attr, handle); + attr->la_valid |= LA_MODE | LA_TYPE; if (rc == 0 && S_ISDIR(attr->la_mode)) { rc = mdo_declare_index_insert(env, child, mdo2fid(child), dot, handle); @@ -1442,10 +1442,13 @@ int mdd_object_initialize(const struct lu_env *env, const struct lu_fid *pfid, * because below function doesn't consider umask). * I'd suggest set all object attributes in creation time, see above. */ - attr->la_valid &= ~LA_MODE; + LASSERT(attr->la_valid & (LA_MODE | LA_TYPE)); + attr->la_valid &= ~(LA_MODE | LA_TYPE); rc = mdd_attr_set_internal(env, child, attr, handle, 0); - if (rc != 0) - RETURN(rc); + /* arguments are supposed to stay the same */ + attr->la_valid |= LA_MODE | LA_TYPE; + if (rc != 0) + RETURN(rc); if (S_ISDIR(attr->la_mode)) { /* Add "." and ".." for newly created dir */ @@ -1477,7 +1480,6 @@ static int mdd_create_sanity_check(const struct lu_env *env, struct lu_fid *fid = &info->mti_fid; struct mdd_object *obj = md2mdd_obj(pobj); struct mdd_device *m = mdo2mdd(pobj); - int lookup = spec->sp_cr_lookup; int rc; ENTRY; @@ -1485,12 +1487,12 @@ static int mdd_create_sanity_check(const struct lu_env *env, if (mdd_is_dead_obj(obj)) RETURN(-ENOENT); - /* + /* * In some cases this lookup is not needed - we know before if name * exists or not because MDT performs lookup for it. * name length check is done in lookup. */ - if (lookup) { + if (spec->sp_cr_lookup) { /* * Check if the name already exist, though it will be checked in * _index_insert also, for avoiding rolling back if exists @@ -1553,8 +1555,7 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd, struct thandle *handle, const struct md_op_spec *spec) { - struct mdd_thread_info *info = mdd_env_info(env); - int rc = 0; + int rc; rc = mdd_declare_object_create_internal(env, p, c, attr, handle, spec); if (rc) @@ -1574,7 +1575,7 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd, GOTO(out, rc); } - rc = mdo_declare_attr_set(env, c, &info->mti_pattr, handle); + rc = mdo_declare_attr_set(env, c, attr, handle); if (rc) GOTO(out, rc); @@ -1592,13 +1593,16 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd, } rc = mdd_declare_object_initialize(env, c, attr, handle); - if (rc) - GOTO(out, rc); + if (rc) + GOTO(out, rc); - rc = mdo_declare_index_insert(env, p, mdo2fid(c), - name->ln_name, handle); - if (rc) - GOTO(out, rc); + if (spec->sp_cr_flags & MDS_OPEN_VOLATILE) + rc = orph_declare_index_insert(env, c, attr->la_mode, handle); + else + rc = mdo_declare_index_insert(env, p, mdo2fid(c), + name->ln_name, handle); + if (rc) + GOTO(out, rc); /* replay case, create LOV EA from client data */ if (spec->no_create || (spec->sp_cr_flags & MDS_OPEN_HAS_EA)) { @@ -1620,9 +1624,11 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd, GOTO(out, rc); } - rc = mdo_declare_attr_set(env, p, attr, handle); - if (rc) - return rc; + if (!(spec->sp_cr_flags & MDS_OPEN_VOLATILE)) { + rc = mdo_declare_attr_set(env, p, attr, handle); + if (rc) + return rc; + } rc = mdd_declare_changelog_store(env, mdd, name, handle); if (rc) @@ -1640,19 +1646,19 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj, const struct lu_name *lname, struct md_object *child, struct md_op_spec *spec, struct md_attr* ma) { - struct mdd_thread_info *info = mdd_env_info(env); - struct lu_attr *la = &info->mti_la_for_fix; - struct mdd_object *mdd_pobj = md2mdd_obj(pobj); - struct mdd_object *son = md2mdd_obj(child); - struct mdd_device *mdd = mdo2mdd(pobj); - struct lu_attr *attr = &ma->ma_attr; - struct thandle *handle; - struct lu_attr *pattr = &info->mti_pattr; - struct dynlock_handle *dlh; - const char *name = lname->ln_name; - int rc, created = 0, initialized = 0, inserted = 0; - int got_def_acl = 0; - ENTRY; + struct mdd_thread_info *info = mdd_env_info(env); + struct lu_attr *la = &info->mti_la_for_fix; + struct mdd_object *mdd_pobj = md2mdd_obj(pobj); + struct mdd_object *son = md2mdd_obj(child); + struct mdd_device *mdd = mdo2mdd(pobj); + struct lu_attr *attr = &ma->ma_attr; + struct thandle *handle; + struct lu_attr *pattr = &info->mti_pattr; + struct dynlock_handle *dlh; + const char *name = lname->ln_name; + int rc, created = 0, initialized = 0, inserted = 0; + int got_def_acl = 0; + ENTRY; /* * Two operations have to be performed: @@ -1732,21 +1738,21 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj, if (rc) GOTO(out_stop, rc); - dlh = mdd_pdo_write_lock(env, mdd_pobj, name, MOR_TGT_PARENT); - if (dlh == NULL) - GOTO(out_trans, rc = -ENOMEM); + dlh = mdd_pdo_write_lock(env, mdd_pobj, name, MOR_TGT_PARENT); + if (dlh == NULL) + GOTO(out_trans, rc = -ENOMEM); - mdd_write_lock(env, son, MOR_TGT_CHILD); - rc = mdd_object_create_internal(env, mdd_pobj, son, attr, handle, spec); - if (rc) { - mdd_write_unlock(env, son); - GOTO(cleanup, rc); - } + mdd_write_lock(env, son, MOR_TGT_CHILD); + rc = mdd_object_create_internal(env, NULL, son, attr, handle, spec); + if (rc) { + mdd_write_unlock(env, son); + GOTO(cleanup, rc); + } - created = 1; + created = 1; #ifdef CONFIG_FS_POSIX_ACL - if (got_def_acl) { + if (got_def_acl) { struct lu_buf *acl_buf; acl_buf = mdd_buf_get(env, info->mti_xattr_buf, got_def_acl); @@ -1755,10 +1761,10 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj, mdd_write_unlock(env, son); GOTO(cleanup, rc); } - } + } #endif - rc = mdd_object_initialize(env, mdo2fid(mdd_pobj), lname, + rc = mdd_object_initialize(env, mdo2fid(mdd_pobj), lname, son, attr, handle, spec); /* @@ -1767,8 +1773,8 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj, * MDT calls this xattr_set(LOV) in a different transaction. * probably this way we code can be made better. */ - if (rc == 0 && - (spec->no_create || (spec->sp_cr_flags & MDS_OPEN_HAS_EA))) { + if (rc == 0 && (spec->no_create || + (spec->sp_cr_flags & MDS_OPEN_HAS_EA))) { const struct lu_buf *buf; buf = mdd_buf_get_const(env, spec->u.sp_ea.eadata, @@ -1776,26 +1782,33 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj, rc = mdo_xattr_set(env, son, buf, XATTR_NAME_LOV, 0, handle, BYPASS_CAPA); } - mdd_write_unlock(env, son); - if (rc) - /* - * Object has no links, so it will be destroyed when last - * reference is released. (XXX not now.) - */ - GOTO(cleanup, rc); - initialized = 1; + if (rc == 0 && spec->sp_cr_flags & MDS_OPEN_VOLATILE) + rc = __mdd_orphan_add(env, son, handle); - rc = __mdd_index_insert(env, mdd_pobj, mdo2fid(son), - name, S_ISDIR(attr->la_mode), handle, - mdd_object_capa(env, mdd_pobj)); - if (rc) - GOTO(cleanup, rc); + mdd_write_unlock(env, son); + + if (rc != 0) + /* + * Object has no links, so it will be destroyed when last + * reference is released. (XXX not now.) + */ + GOTO(cleanup, rc); + + initialized = 1; + + if (!(spec->sp_cr_flags & MDS_OPEN_VOLATILE)) + rc = __mdd_index_insert(env, mdd_pobj, mdo2fid(son), + name, S_ISDIR(attr->la_mode), handle, + mdd_object_capa(env, mdd_pobj)); + + if (rc != 0) + GOTO(cleanup, rc); - inserted = 1; + inserted = 1; if (S_ISLNK(attr->la_mode)) { - struct md_ucred *uc = md_ucred(env); + struct lu_ucred *uc = lu_ucred_assert(env); struct dt_object *dt = mdd_object_child(son); const char *target_name = spec->u.sp_symname; int sym_len = strlen(target_name); @@ -1803,10 +1816,10 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj, loff_t pos = 0; buf = mdd_buf_get_const(env, target_name, sym_len); - rc = dt->do_body_ops->dbo_write(env, dt, buf, &pos, handle, - mdd_object_capa(env, son), - uc->mu_cap & - CFS_CAP_SYS_RESOURCE_MASK); + rc = dt->do_body_ops->dbo_write(env, dt, buf, &pos, handle, + mdd_object_capa(env, son), + uc->uc_cap & + CFS_CAP_SYS_RESOURCE_MASK); if (rc == sym_len) rc = 0; @@ -1814,11 +1827,16 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj, GOTO(cleanup, rc = -EFAULT); } + /* volatile file creation does not update parent directory times */ + if (spec->sp_cr_flags & MDS_OPEN_VOLATILE) + GOTO(cleanup, rc = 0); + + /* update parent directory mtime/ctime */ *la = *attr; - la->la_valid = LA_CTIME | LA_MTIME; + la->la_valid = LA_CTIME | LA_MTIME; rc = mdd_attr_check_set_internal(env, mdd_pobj, la, handle, 0); - if (rc) - GOTO(cleanup, rc); + if (rc) + GOTO(cleanup, rc); EXIT; cleanup: @@ -1826,9 +1844,12 @@ cleanup: int rc2; if (inserted != 0) { - rc2 = __mdd_index_delete(env, mdd_pobj, name, - S_ISDIR(attr->la_mode), - handle, BYPASS_CAPA); + if (spec->sp_cr_flags & MDS_OPEN_VOLATILE) + rc2 = __mdd_orphan_del(env, son, handle); + else + rc2 = __mdd_index_delete(env, mdd_pobj, name, + S_ISDIR(attr->la_mode), + handle, BYPASS_CAPA); if (rc2 != 0) goto out_stop; } @@ -1867,7 +1888,7 @@ out_stop: out_free: /* The child object shouldn't be cached anymore */ if (rc) - cfs_set_bit(LU_OBJECT_HEARD_BANSHEE, + set_bit(LU_OBJECT_HEARD_BANSHEE, &child->mo_lu.lo_header->loh_flags); return rc; } @@ -2744,16 +2765,22 @@ out: if (rc == 0) rc = rc2; if (rc) { + int error = 1; + if (rc == -EOVERFLOW || rc == - ENOENT) + error = 0; if (oldpfid == NULL) - CERROR("link_ea add '%.*s' failed %d "DFID"\n", + CDEBUG(error ? D_ERROR : D_OTHER, + "link_ea add '%.*s' failed %d "DFID"\n", newlname->ln_namelen, newlname->ln_name, rc, PFID(mdd_object_fid(mdd_obj))); else if (newpfid == NULL) - CERROR("link_ea del '%.*s' failed %d "DFID"\n", + CDEBUG(error ? D_ERROR : D_OTHER, + "link_ea del '%.*s' failed %d "DFID"\n", oldlname->ln_namelen, oldlname->ln_name, rc, PFID(mdd_object_fid(mdd_obj))); else - CERROR("link_ea rename '%.*s'->'%.*s' failed %d " + CDEBUG(error ? D_ERROR : D_OTHER, + "link_ea rename '%.*s'->'%.*s' failed %d " DFID"\n", oldlname->ln_namelen, oldlname->ln_name, newlname->ln_namelen, newlname->ln_name,