-/* -*- 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 <wangdi@clusterfs.com>
+ * 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 <wangdi@clusterfs.com>
*/
+
#ifndef EXPORT_SYMTAB
# define EXPORT_SYMTAB
#endif
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);
}
#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",
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)
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);
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);
}
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);
/* 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);
!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 <niemi@tux.org>
*
* 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;
!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 <niemi@tux.org>
*
* 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;
}
}
- 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) &&
(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,
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;
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;
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);
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);
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);
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);
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,
.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,
};