X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fmdd%2Fmdd_object.c;h=39d3814ab6609642f50a91f248aa316d35c8fb1b;hb=1a24137e8f26eaae9a2dac39a1e8a8a0bed46b6b;hp=83e4a3822eaa965dd6ddf76af8c35422ffdd2cec;hpb=45c1f367a1379cb7adf9e2ed79c1221913eaf2e2;p=fs%2Flustre-release.git diff --git a/lustre/mdd/mdd_object.c b/lustre/mdd/mdd_object.c index 83e4a38..39d3814 100644 --- a/lustre/mdd/mdd_object.c +++ b/lustre/mdd/mdd_object.c @@ -1,30 +1,45 @@ -/* -*- MODE: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * mdd/mdd_handler.c - * Lustre Metadata Server (mdd) routines + * GPL HEADER START * - * Copyright (C) 2006 Cluster File Systems, Inc. - * Author: Wang Di + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This file is part of the Lustre file system, http://www.lustre.org - * Lustre is a trademark of Cluster File Systems, Inc. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. * - * You may have signed or agreed to another license before downloading - * this software. If so, you are bound by the terms and conditions - * of that agreement, and the following does not apply to you. See the - * LICENSE file included with this distribution for more information. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * If you did not agree to a different license, then this copy of Lustre - * is open source software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf * - * In either case, Lustre is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * license text for more details. + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lustre/mdd/mdd_object.c + * + * Lustre Metadata Server (mdd) routines + * + * Author: Wang Di */ + #ifndef EXPORT_SYMTAB # define EXPORT_SYMTAB #endif @@ -263,8 +278,11 @@ int mdd_get_flags(const struct lu_env *env, struct mdd_object *obj) ENTRY; rc = mdd_la_get(env, obj, la, BYPASS_CAPA); - if (rc == 0) + if (rc == 0) { mdd_flags_xlate(obj, la->la_flags); + if (S_ISDIR(la->la_mode) && la->la_nlink == 1) + obj->mod_flags |= MNLINK_OBJ; + } RETURN(rc); } @@ -386,7 +404,7 @@ static int mdd_attr_get_internal(const struct lu_env *env, #ifdef CONFIG_FS_POSIX_ACL if (rc == 0 && ma->ma_need & MA_ACL_DEF) { if (S_ISDIR(mdd_object_type(mdd_obj))) - rc = mdd_acl_def_get(env, mdd_obj, ma); + rc = mdd_def_acl_get(env, mdd_obj, ma); } #endif CDEBUG(D_INODE, "after getattr rc = %d, ma_valid = "LPX64"\n", @@ -510,6 +528,9 @@ int mdd_object_create_internal(const struct lu_env *env, struct mdd_object *p, RETURN(rc); } +/** + * Make sure the ctime is increased only. + */ static inline int mdd_attr_check(const struct lu_env *env, struct mdd_object *obj, struct lu_attr *attr) @@ -577,12 +598,9 @@ static int mdd_attr_set_internal_locked(const struct lu_env *env, ENTRY; needacl = needacl && (attr->la_valid & LA_MODE); - if (needacl) mdd_write_lock(env, obj); - rc = mdd_attr_set_internal(env, obj, attr, handle, needacl); - if (needacl) mdd_write_unlock(env, obj); RETURN(rc); @@ -597,13 +615,12 @@ int mdd_attr_check_set_internal_locked(const struct lu_env *env, int rc; ENTRY; - rc = mdd_attr_check(env, obj, attr); - if (rc) - RETURN(rc); - - if (attr->la_valid) - rc = mdd_attr_set_internal_locked(env, obj, attr, handle, - needacl); + needacl = needacl && (attr->la_valid & LA_MODE); + if (needacl) + mdd_write_lock(env, obj); + rc = mdd_attr_check_set_internal(env, obj, attr, handle, needacl); + if (needacl) + mdd_write_unlock(env, obj); RETURN(rc); } @@ -653,9 +670,12 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, if (rc) RETURN(rc); - /* This is only for set ctime when rename's source is on remote MDS. */ - if (unlikely(la->la_valid == LA_CTIME)) { - rc = mdd_may_delete(env, NULL, obj, (struct md_attr *)ma, 1, 0); + if (la->la_valid == LA_CTIME) { + if (!(ma->ma_attr_flags & MDS_PERM_BYPASS)) + /* This is only for set ctime when rename's source is + * on remote MDS. */ + rc = mdd_may_delete(env, NULL, obj, + (struct md_attr *)ma, 1, 0); if (rc == 0 && la->la_ctime <= tmp_la->la_ctime) la->la_valid &= ~LA_CTIME; RETURN(rc); @@ -712,11 +732,10 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, /* Make sure a caller can chmod. */ if (la->la_valid & LA_MODE) { - /* - * Bypass la_vaild == LA_MODE, - * this is for changing file with SUID or SGID. - */ + /* Bypass la_vaild == LA_MODE, + * this is for changing file with SUID or SGID. */ if ((la->la_valid & ~LA_MODE) && + !(ma->ma_attr_flags & MDS_PERM_BYPASS) && (uc->mu_fsuid != tmp_la->la_uid) && !mdd_capable(uc, CAP_FOWNER)) RETURN(-EPERM); @@ -744,8 +763,7 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, !mdd_capable(uc, CAP_CHOWN)) RETURN(-EPERM); - /* - * If the user or group of a non-directory has been + /* 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 * @@ -753,8 +771,7 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, * 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. - */ + * 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; @@ -772,16 +789,14 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, !mdd_capable(uc, CAP_CHOWN)) RETURN(-EPERM); - /* - * Likewise, if the user or group of a non-directory + /* 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 * * Removed the fsuid check (see the comment above) -- - * 19990830 SD. - */ + * 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; @@ -789,11 +804,13 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, } } - if (la->la_valid & (LA_SIZE | LA_BLOCKS) && - !(la->la_valid & LA_TRUNC)) { - /* For "Size-on-MDS" case, the MAY_WRITE perm - * has been checked when file open. */ - + /* For both Size-on-MDS case and truncate case, + * "la->la_valid & (LA_SIZE | LA_BLOCKS)" are ture. + * We distinguish them by "ma->ma_attr_flags & MDS_SOM". + * For SOM case, it is true, the MAY_WRITE perm has been checked + * when open, no need check again. For truncate case, it is false, + * the MAY_WRITE perm should be checked here. */ + if (ma->ma_attr_flags & MDS_SOM) { /* For the "Size-on-MDS" setattr update, merge coming * attributes with the set in the inode. BUG 10641 */ if ((la->la_valid & LA_ATIME) && @@ -806,9 +823,8 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, (la->la_ctime <= tmp_la->la_ctime)) la->la_valid &= ~(LA_MTIME | LA_CTIME); } else { - if (la->la_valid & LA_TRUNC) { - /* For truncate, we should have MAY_WRITE perm. */ - if (!((la->la_valid & MDS_OPEN_OWNEROVERRIDE) && + if (la->la_valid & (LA_SIZE | LA_BLOCKS)) { + if (!((ma->ma_attr_flags & MDS_OPEN_OWNEROVERRIDE) && (uc->mu_fsuid == tmp_la->la_uid)) && !(ma->ma_attr_flags & MDS_PERM_BYPASS)) { rc = mdd_permission_internal_locked(env, obj, @@ -951,11 +967,14 @@ static int mdd_xattr_sanity_check(const struct lu_env *env, RETURN(rc); } +/** + * The caller should guarantee to update the object ctime + * after xattr_set if needed. + */ static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj, const struct lu_buf *buf, const char *name, - int fl, const struct lu_attr *la) + int fl) { - struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix; struct mdd_object *mdd_obj = md2mdd_obj(obj); struct mdd_device *mdd = mdo2mdd(obj); struct thandle *handle; @@ -972,22 +991,18 @@ static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj, RETURN(PTR_ERR(handle)); rc = mdd_xattr_set_txn(env, mdd_obj, buf, name, fl, handle); - if (rc == 0 && likely(la != NULL)) { - LASSERT(la->la_valid & LA_CTIME); - la_copy->la_ctime = la->la_ctime; - la_copy->la_valid = LA_CTIME; - rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la_copy, - handle, 0); - } mdd_trans_stop(env, mdd, rc, handle); RETURN(rc); } +/** + * 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, const struct lu_attr *la) + const char *name) { - struct lu_attr *la_copy = &mdd_env_info(env)->mti_la_for_fix; struct mdd_object *mdd_obj = md2mdd_obj(obj); struct mdd_device *mdd = mdo2mdd(obj); struct thandle *handle; @@ -1007,14 +1022,6 @@ int mdd_xattr_del(const struct lu_env *env, struct md_object *obj, rc = mdo_xattr_del(env, mdd_obj, name, handle, mdd_object_capa(env, mdd_obj)); mdd_write_unlock(env, mdd_obj); - if (rc == 0 && likely(la != NULL)) { - LASSERT(la->la_valid & LA_CTIME); - la_copy->la_ctime = la->la_ctime; - la_copy->la_valid = LA_CTIME; - rc = mdd_attr_check_set_internal_locked(env, mdd_obj, la_copy, - handle, 0); - } - mdd_trans_stop(env, mdd, rc, handle); RETURN(rc); @@ -1054,11 +1061,11 @@ static int mdd_ref_del(const struct lu_env *env, struct md_object *obj, if (rc) GOTO(cleanup, rc); - mdo_ref_del(env, mdd_obj, handle); + __mdd_ref_del(env, mdd_obj, handle, 0); if (S_ISDIR(lu_object_attr(&obj->mo_lu))) { /* unlink dot */ - mdo_ref_del(env, mdd_obj, handle); + __mdd_ref_del(env, mdd_obj, handle, 1); } LASSERT(ma->ma_attr.la_valid & LA_CTIME); @@ -1197,7 +1204,7 @@ static int mdd_ref_add(const struct lu_env *env, struct md_object *obj, mdd_write_lock(env, mdd_obj); rc = mdd_link_sanity_check(env, NULL, NULL, mdd_obj); if (rc == 0) - mdo_ref_add(env, mdd_obj, handle); + __mdd_ref_add(env, mdd_obj, handle); mdd_write_unlock(env, mdd_obj); if (rc == 0) { LASSERT(ma->ma_attr.la_valid & LA_CTIME); @@ -1464,12 +1471,12 @@ static int __mdd_readpage(const struct lu_env *env, struct mdd_object *obj, struct dt_object *next = mdd_object_child(obj); struct dt_it_ops *iops; struct page *pg; - struct lu_dirent *last; + struct lu_dirent *last = NULL; int i; int rc; int nob; __u64 hash_start; - __u64 hash_end; + __u64 hash_end = 0; LASSERT(rdpg->rp_pages != NULL); LASSERT(next->do_index_ops != NULL); @@ -1596,6 +1603,16 @@ out_unlock: return rc; } +static int mdd_object_sync(const struct lu_env *env, struct md_object *obj) +{ + struct mdd_object *mdd_obj = md2mdd_obj(obj); + struct dt_object *next; + + LASSERT(mdd_object_exists(mdd_obj)); + next = mdd_object_child(mdd_obj); + return next->do_ops->do_object_sync(env, next); +} + struct md_object_operations mdd_obj_ops = { .moo_permission = mdd_permission, .moo_attr_get = mdd_attr_get, @@ -1611,5 +1628,6 @@ struct md_object_operations mdd_obj_ops = { .moo_close = mdd_close, .moo_readpage = mdd_readpage, .moo_readlink = mdd_readlink, - .moo_capa_get = mdd_capa_get + .moo_capa_get = mdd_capa_get, + .moo_object_sync = mdd_object_sync, };