From c253b6e9a3fa11948f72c4570d83081646eb3049 Mon Sep 17 00:00:00 2001 From: liuduo Date: Thu, 26 Aug 2004 09:49:35 +0000 Subject: [PATCH] b: b_hd_bug3270 land branch b_hd_bug3270 into HEAD --- lustre/include/linux/lustre_lib.h | 1 + lustre/include/linux/obd.h | 3 + lustre/mds/handler.c | 49 +++- lustre/mds/mds_lov.c | 22 ++ lustre/smfs/journal.c | 544 ++++++++++++++++++++++++++++++++++++++ lustre/tests/checkstat.c | 33 ++- lustre/tests/sanity.sh | 63 +++++ lustre/utils/lconf | 24 ++ lustre/utils/lctl.c | 3 + lustre/utils/lmc | 16 +- lustre/utils/obd.c | 134 +++++++++- lustre/utils/obdctl.h | 1 + 12 files changed, 881 insertions(+), 12 deletions(-) create mode 100644 lustre/smfs/journal.c diff --git a/lustre/include/linux/lustre_lib.h b/lustre/include/linux/lustre_lib.h index 04de0a5..6f1f96d 100644 --- a/lustre/include/linux/lustre_lib.h +++ b/lustre/include/linux/lustre_lib.h @@ -436,6 +436,7 @@ static inline void obd_ioctl_freedata(char *buf, int len) #define OBD_IOC_NO_TRANSNO _IOW ('f', 140, long) #define OBD_IOC_SET_READONLY _IOW ('f', 141, long) #define OBD_IOC_ABORT_RECOVERY _IOR ('f', 142, long) +#define OBD_IOC_ROOT_SQUASH _IOWR('f', 143, long) #define OBD_GET_VERSION _IOWR ('f', 144, long) diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index d5f5459..7e7ccdc 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -359,6 +359,9 @@ struct mds_obd { struct obd_export *mds_lmv_exp; /* XXX lov_exp */ struct ptlrpc_service *mds_create_service; struct semaphore mds_lmv_sem; + uid_t mds_squash_uid; + gid_t mds_squash_gid; + ptl_nid_t mds_nosquash_nid; atomic_t mds_real_clients; struct obd_uuid mds_lmv_uuid; struct dentry *mds_fids_dir; diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 3bba6bb..d1fd5e1 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -67,6 +67,7 @@ static int mds_intent_policy(struct ldlm_namespace *ns, static int mds_postsetup(struct obd_device *obd); static int mds_cleanup(struct obd_device *obd, int flags); + /* Assumes caller has already pushed into the kernel filesystem context */ static int mds_sendpage(struct ptlrpc_request *req, struct file *file, loff_t offset, int count) @@ -682,6 +683,49 @@ int mds_pack_md(struct obd_device *obd, struct lustre_msg *msg, int offset, RETURN(rc); } +static void mds_root_squash_rec(struct mds_obd *mds, ptl_nid_t *peernid, + struct mds_update_record *rec) +{ + if (!mds->mds_squash_uid || rec->_ur_fsuid) + return; + + if (*peernid == mds->mds_nosquash_nid) + return; + + CDEBUG(D_OTHER, "squash req from 0x%llx, (%d:%d/%x)=>(%d:%d/%x)\n", + *peernid, + rec->_ur_fsuid, rec->_ur_fsgid, rec->_ur_cap, + mds->mds_squash_uid, mds->mds_squash_gid, + (rec->_ur_cap & ~CAP_FS_MASK)); + + rec->_ur_fsuid = mds->mds_squash_uid; + rec->_ur_fsgid = mds->mds_squash_gid; + /* XXX should we remove all capabilities? */ + rec->_ur_cap &= ~CAP_FS_MASK; + rec->_ur_suppgid1 = -1; + rec->_ur_suppgid2 = -1; +} +static void mds_root_squash_body(struct mds_obd *mds, ptl_nid_t *peernid, + struct mds_body *body) +{ + if (!mds->mds_squash_uid || body->fsuid) + return; + + if (*peernid == mds->mds_nosquash_nid) + return; + + CDEBUG(D_OTHER, "squash req from 0x%llx, (%d:%d/%x)=>(%d:%d/%x)\n", + *peernid, + body->fsuid, body->fsgid, body->capability, + mds->mds_squash_uid, mds->mds_squash_gid, + (body->capability & ~CAP_FS_MASK)); + + body->fsuid = mds->mds_squash_uid; + body->fsgid = mds->mds_squash_gid; + /* XXX should we remove all capabilities? */ + body->capability &= ~CAP_FS_MASK; + body->suppgid = -1; +} static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry, struct ptlrpc_request *req, struct mds_body *reqbody, int reply_off) @@ -902,7 +946,7 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req, rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*rep)); offset = 1; } - + mds_root_squash_body(&obd->u.mds, &req->rq_peer.peer_nid, body); uc.luc_fsuid = body->fsuid; uc.luc_fsgid = body->fsgid; uc.luc_cap = body->capability; @@ -1216,6 +1260,7 @@ static int mds_readpage(struct ptlrpc_request *req) if (body == NULL) GOTO (out, rc = -EFAULT); + mds_root_squash_body(&obd->u.mds, &req->rq_peer.peer_nid, body); uc.luc_fsuid = body->fsuid; uc.luc_fsgid = body->fsgid; uc.luc_cap = body->capability; @@ -1280,6 +1325,8 @@ int mds_reint(struct ptlrpc_request *req, int offset, CERROR("invalid record\n"); GOTO(out, req->rq_status = -EINVAL); } + mds_root_squash_rec(&req->rq_export->exp_obd->u.mds, + &req->rq_peer.peer_nid, rec); /* rc will be used to interrupt a for loop over multiple records */ rc = mds_reint_rec(rec, offset, req, lockh); out: diff --git a/lustre/mds/mds_lov.c b/lustre/mds/mds_lov.c index f935f42..a1ece50 100644 --- a/lustre/mds/mds_lov.c +++ b/lustre/mds/mds_lov.c @@ -528,7 +528,29 @@ int mds_iocontrol(unsigned int cmd, struct obd_export *exp, int len, case OBD_IOC_ABORT_RECOVERY: target_stop_recovery_thread(obd); RETURN(0); + case OBD_IOC_ROOT_SQUASH: { + __u32 *p = (__u32 *) data->ioc_inlbuf1; + if (data->ioc_inllen1 != + (sizeof(__u32) * 4 + sizeof(ptl_nid_t))) + RETURN(-EINVAL); + + if (*p == 0) { /* get */ + p += 2; + *p++ = mds->mds_squash_uid; + *p++ = mds->mds_squash_gid; + *((ptl_nid_t*) p) = mds->mds_nosquash_nid; + } else { /* set */ + p += 2; + mds->mds_squash_uid = *p++; + mds->mds_squash_gid = *p++; + mds->mds_nosquash_nid = *((ptl_nid_t*) p); + CWARN("MDS: squash root to %d:%d, except nid 0x%llx\n", + mds->mds_squash_uid, mds->mds_squash_gid, + mds->mds_nosquash_nid); + } + RETURN(0); + } default: RETURN(-EINVAL); } diff --git a/lustre/smfs/journal.c b/lustre/smfs/journal.c new file mode 100644 index 0000000..ab62e7a --- /dev/null +++ b/lustre/smfs/journal.c @@ -0,0 +1,544 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/smfs/journal.c + * Lustre filesystem abstraction routines + * + * Copyright (C) 2004 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free 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. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#define DEBUG_SUBSYSTEM S_SM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smfs_internal.h" + +#define KML_BUF_REC_INIT(buffer, pbuf, len) \ +do { \ + pbuf = buffer + sizeof(int); \ + len -= sizeof(int); \ +} while (0) + +#define KML_BUF_REC_END(buffer, length, pbuf) \ +do { \ + int len = length; \ + memcpy(buffer, &len, sizeof(len)); \ + length += sizeof(int); \ + pbuf = buffer + length; \ +} while (0) + +void *smfs_trans_start(struct inode *inode, int op, void *desc_private) +{ + struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt; + + CDEBUG(D_INFO, "trans start %p\n", fsfilt->fs_start); + + SMFS_TRANS_OP(inode, op); + + /* There are some problem here. fs_start in fsfilt is used by lustre + * the journal blocks of write rec are not counted in FIXME later */ + if (fsfilt->fs_start) + return fsfilt->fs_start(inode, op, desc_private, 0); + return NULL; +} + +void smfs_trans_commit(struct inode *inode, void *handle, int force_sync) +{ + struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt; + + if (!handle) + return; + + CDEBUG(D_INFO, "trans commit %p\n", fsfilt->fs_commit); + + if (fsfilt->fs_commit) + fsfilt->fs_commit(inode->i_sb, inode, handle, force_sync); +} + +/*smfs_path is gotten from intermezzo*/ +static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer, + int buflen) +{ + char * end = buffer + buflen; + char * name = buffer; + char * buf_end = buffer + buflen; + char * retval; + + *--end = '\0'; + buflen--; + /* Get '/' right */ + retval = end-1; + *retval = '/'; + + for (;;) { + struct dentry * parent; + int namelen; + + if (dentry == root) + break; + parent = dentry->d_parent; + if (dentry == parent) + break; + namelen = dentry->d_name.len; + buflen -= namelen + 1; + if (buflen < 0) + break; + end -= namelen; + memcpy(end, dentry->d_name.name, namelen); + *--end = '/'; + retval = end; + dentry = parent; + } + + while (end != buf_end) + *name++ = *end++; + *name = '\0'; + return retval; +} + +static int smfs_log_path(struct super_block *sb, + struct dentry *dentry, + char *buffer, + int buffer_len) +{ + struct dentry *root=sb->s_root; + char *p_name = buffer + sizeof(int); + char *name = NULL; + int namelen = 0; + if (dentry) { + name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int)); + namelen = cpu_to_le32(strlen(p_name)); + memcpy(buffer, &namelen, sizeof(int)); + } + namelen += sizeof(int); + RETURN(namelen); +} + +static inline int log_it(char *buffer, void *data, int length) +{ + memcpy(buffer, &length, sizeof(int)); + memcpy(buffer + sizeof(int), data, length); + return (sizeof(int) + length); +} + +static int smfs_pack_rec (char *buffer, struct dentry *dentry, + struct inode *dir, void *data1, + void *data2, int op) +{ + smfs_pack_rec_func pack_func; + int rc; + + pack_func = smfs_get_rec_pack_type(dir->i_sb); + if (!pack_func) { + return (0); + } + rc = pack_func(buffer, dentry, dir, data1, data2, op); + return rc; +} + +int smfs_post_rec_create(struct inode *dir, struct dentry *dentry, + void *data1, void *data2) +{ + struct smfs_super_info *sinfo; + char *buffer = NULL, *pbuf; + int rc = 0, length = 0, buf_len = 0; + + sinfo = S2SMI(dentry->d_inode->i_sb); + if (!sinfo) + RETURN(-EINVAL); + + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + GOTO(exit, rc = -ENOMEM); + + buf_len = PAGE_SIZE; + KML_BUF_REC_INIT(buffer, pbuf, buf_len); + rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len); + if (rc < 0) + GOTO(exit, rc); + length = rc; + KML_BUF_REC_END(buffer, length, pbuf); + + rc = smfs_pack_rec(pbuf, dentry, dir, + data1, data2, REINT_CREATE); + if (rc <= 0) + GOTO(exit, rc); + else + length += rc; + rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); +exit: + if (buffer) + OBD_FREE(buffer, PAGE_SIZE); + + RETURN(rc); +} + +static int smfs_post_rec_link(struct inode *dir, + struct dentry *dentry, + void *data1, + void *data2) +{ + struct smfs_super_info *sinfo; + struct dentry *old_dentry = (struct dentry *)data1; + char *buffer = NULL, *pbuf = NULL; + int rc = 0, length = 0, buf_len = 0; + + sinfo = S2SMI(dir->i_sb); + if (!sinfo) + RETURN(-EINVAL); + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + GOTO(exit, rc = -ENOMEM); + + buf_len = PAGE_SIZE; + KML_BUF_REC_INIT(buffer, pbuf, buf_len); + rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len); + if (rc < 0) + GOTO(exit, rc); + + length = rc; + KML_BUF_REC_END(buffer, length, pbuf); + + rc = smfs_pack_rec(pbuf, dentry, dir, dentry->d_parent, + old_dentry->d_parent, REINT_LINK); + if (rc <= 0) + GOTO(exit, rc); + else + length += rc; + rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); +exit: + if (buffer) + OBD_FREE(buffer, PAGE_SIZE); + + RETURN(rc); +} + +static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry, + void *data1, void *data2) +{ + struct smfs_super_info *sinfo; + int mode = *((int*)data1); + char *buffer = NULL, *pbuf = NULL; + int length = 0, rc = 0, buf_len = 0; + + sinfo = S2SMI(dentry->d_inode->i_sb); + if (!sinfo) + RETURN(-EINVAL); + + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + GOTO(exit, rc = -ENOMEM); + + buf_len = PAGE_SIZE; + KML_BUF_REC_INIT(buffer, pbuf, buf_len); + rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len); + if (rc < 0) + GOTO(exit, rc); + + length = rc; + KML_BUF_REC_END(buffer, length, pbuf); + rc = smfs_pack_rec(pbuf, dentry, dir, + &mode, NULL, REINT_UNLINK); + if (rc <= 0) + GOTO(exit, rc); + else + length += rc; + + rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); +exit: + if (buffer) + OBD_FREE(buffer, PAGE_SIZE); + + RETURN(rc); +} + +static int smfs_post_rec_rename(struct inode *dir, + struct dentry *dentry, + void *data1, + void *data2) +{ + struct smfs_super_info *sinfo; + struct inode *new_dir = (struct inode *)data1; + struct dentry *new_dentry = (struct dentry *)data2; + char *buffer = NULL, *pbuf = NULL; + int rc = 0, length = 0, buf_len = 0; + + sinfo = S2SMI(dir->i_sb); + if (!sinfo) + RETURN(-EINVAL); + + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + GOTO(exit, rc = -ENOMEM); + + buf_len = PAGE_SIZE; + KML_BUF_REC_INIT(buffer, pbuf, buf_len); + rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len); + if (rc < 0) + GOTO(exit, rc); + + pbuf += rc; + length += rc; + buf_len -= rc; + /*record new_dentry path*/ + rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len); + if (rc < 0) + GOTO(exit, rc); + + length += rc; + KML_BUF_REC_END(buffer, length, pbuf); + + rc = smfs_pack_rec(pbuf, dentry, dir, + new_dir, new_dentry, REINT_RENAME); + if (rc <= 0) + GOTO(exit, rc); + length += rc; + + rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); +exit: + if (buffer) + OBD_FREE(buffer, PAGE_SIZE); + RETURN(rc); +} + +static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num) +{ + struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt; + int rc = 0; + + if (SMFS_INODE_OVER_WRITE(inode)) + RETURN(rc); + + rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode), + SIZE2BLKS(num, inode)); + RETURN(rc); +} + +static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num) +{ + struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt; + int rc = 0; + + rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode), + SIZE2BLKS(num, inode)); + + RETURN(rc); +} + +static int smfs_remove_all_extents_ea(struct inode *inode) +{ + struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt; + int rc = 0; + + rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff); + RETURN(rc); +} +static int smfs_init_extents_ea(struct inode *inode) +{ + struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt; + int rc = 0; + + rc = fsfilt->fs_init_extents_ea(inode); + + RETURN(rc); +} +static int smfs_set_dirty_flags(struct inode *inode, int flags) +{ + struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt; + void *handle; + int rc = 0; + + if (SMFS_INODE_OVER_WRITE(inode)) + RETURN(rc); + /*FIXME later, the blocks needed in journal here will be recalculated*/ + handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL); + if (IS_ERR(handle)) { + CERROR("smfs_set_dirty_flag:no space for transaction\n"); + RETURN(-ENOSPC); + } + if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) || + ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) { + rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS, + &flags, sizeof(int)); + if (rc) + GOTO(out, rc); + } + if (flags == SMFS_OVER_WRITE) + SMFS_SET_INODE_OVER_WRITE(inode); + else + SMFS_SET_INODE_DIRTY_WRITE(inode); +out: + smfs_trans_commit(inode, handle, 0); + RETURN(rc); +} + +int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry, + void *data1, void *data2) +{ + struct smfs_super_info *sinfo; + struct iattr *attr = (struct iattr *)data1; + char *buffer = NULL, *pbuf; + int rc = 0, length = 0, buf_len = 0; + + sinfo = S2SMI(inode->i_sb); + if (!sinfo) + RETURN(-EINVAL); + + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + GOTO(exit, rc = -ENOMEM); + + buf_len = PAGE_SIZE; + KML_BUF_REC_INIT(buffer, pbuf, buf_len); + rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len); + if (rc < 0) + GOTO(exit, rc); + + length = rc; + KML_BUF_REC_END(buffer, length, pbuf); + + rc = smfs_pack_rec(pbuf, dentry, inode, + data1, data2, REINT_SETATTR); + if (rc <= 0) + GOTO(exit, rc); + else + length += rc; + + rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); + if (!rc) { + if (attr && attr->ia_valid & ATTR_SIZE) { + smfs_remove_extents_ea(inode, attr->ia_size, + 0xffffffff); + if (attr->ia_size == 0) + smfs_set_dirty_flags(inode, SMFS_OVER_WRITE); + else + smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE); + } + } +exit: + if (buffer) + OBD_FREE(buffer, PAGE_SIZE); + RETURN(rc); +} + +static int all_blocks_present_ea(struct inode *inode) +{ + int rc = 0; + + RETURN(rc); +} +int smfs_post_rec_write(struct inode *dir, struct dentry *dentry, + void *data1, void *data2) +{ + struct smfs_super_info *sinfo; + char *buffer = NULL, *pbuf; + int rc = 0, length = 0, buf_len = 0; + + if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) && + !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) { + sinfo = S2SMI(dentry->d_inode->i_sb); + if (!sinfo) + RETURN(-EINVAL); + + OBD_ALLOC(buffer, PAGE_SIZE); + if (!buffer) + GOTO(exit, rc = -ENOMEM); + + buf_len = PAGE_SIZE; + KML_BUF_REC_INIT(buffer, pbuf, buf_len); + rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len); + + if (rc < 0) + GOTO(exit, rc); + pbuf += rc; + memcpy(buffer, &rc, sizeof(int)); + length = rc + sizeof(int); + + rc = smfs_pack_rec(pbuf, dentry, dir, + data1, data2, REINT_WRITE); + if (rc <= 0) + GOTO(exit, rc); + else + length += rc; + + rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); + if (rc) + GOTO(exit, rc); + rc = smfs_init_extents_ea(dentry->d_inode); + if (rc) + GOTO(exit, rc); + } + if (dentry->d_inode->i_size == 0) { + smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE); + } else { + /*insert extent EA*/ + loff_t off = *((loff_t*)data1); + size_t count = *((size_t*)data2); + + rc = smfs_insert_extents_ea(dentry->d_inode, off, count); + if (rc < 0) + GOTO(exit, rc); + if (all_blocks_present_ea(dentry->d_inode)){ + smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE); + smfs_remove_all_extents_ea(dentry->d_inode); + } else { + smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE); + } + } +exit: + if (buffer) + OBD_FREE(buffer, PAGE_SIZE); + RETURN(rc); +} + +typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry, + void *data1, void *data2); + +static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = { + [HOOK_CREATE] smfs_post_rec_create, + [HOOK_LOOKUP] NULL, + [HOOK_LINK] smfs_post_rec_link, + [HOOK_UNLINK] smfs_post_rec_unlink, + [HOOK_SYMLINK] smfs_post_rec_create, + [HOOK_MKDIR] smfs_post_rec_create, + [HOOK_RMDIR] smfs_post_rec_unlink, + [HOOK_MKNOD] smfs_post_rec_create, + [HOOK_RENAME] smfs_post_rec_rename, + [HOOK_SETATTR] smfs_post_rec_setattr, + [HOOK_WRITE] smfs_post_rec_write, +}; + +int smfs_post_kml_rec(struct inode *dir, struct dentry *dst_dentry, + void *data1, void *data2, int op) +{ + if (smfs_kml_post[op]) { + return smfs_kml_post[op](dir, dst_dentry, data1, data2); + } + return 0; +} diff --git a/lustre/tests/checkstat.c b/lustre/tests/checkstat.c index c98d6aa..acfdfa8 100644 --- a/lustre/tests/checkstat.c +++ b/lustre/tests/checkstat.c @@ -90,15 +90,34 @@ main (int argc, char **argv) fprintf (stderr, "Can't parse numeric uid %s\n", optarg); return (1); } - } else { - struct passwd *pw = getpwnam (optarg); - - if (pw == NULL) + }else { + int i,flag=0; + char * temp ; + temp = optarg; + for(i=0;ipw_uid; + } - uid = pw->pw_uid; + else + uid=(uid_t)atol(optarg); } break; diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index ed4a78e..7c8f2cc 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -203,6 +203,69 @@ test_0() { $CHECKSTAT -a $DIR/f || error } run_test 0 "touch .../f ; rm .../f =============================" +#bug3270 root_squash check +mdsdevice(){ + lctl << EOF + dl + quit +EOF +} +mynidstr(){ + lctl << EOF + network tcp + mynid + quit +EOF +} +test_0a(){ + mdsnum=`mdsdevice|awk ' $3=="mds" {print $1}'` + if [ ! -z "$mdsnum" ];then + mynid=`mynidstr|awk '{print $4}'` + mkdir $DIR/test_0a_dir1 + touch $DIR/test_0a_file1 + ln -s $DIR/test_0a_file1 $DIR/test_0a_filelink1 + chmod 0777 $DIR + lctl << EOF + device $mdsnum + root_squash 500:500 + root_squash + quit +EOF + mkdir $DIR/test_0a_dir2 + touch $DIR/test_0a_file2 + ln -s $DIR/test_0a_file2 $DIR/test_0a_filelink2 + $CHECKSTAT -t dir -u 500 $DIR/test_0a_dir2 || error + $CHECKSTAT -t file -u 500 $DIR/test_0a_file2 || error + $CHECKSTAT -t link -u 500 $DIR/test_0a_filelink2 || error + lctl << EOF + device $mdsnum + root_squash 500:500 $mynid + root_squash + quit +EOF + mkdir $DIR/test_0a_dir3 + touch $DIR/test_0a_file3 + ln -s $DIR/test_0a_file3 $DIR/test_0a_filelink3 + $CHECKSTAT -t dir -u root $DIR/test_0a_dir3 || error + $CHECKSTAT -t file -u root $DIR/test_0a_file3 || error + $CHECKSTAT -t link -u root $DIR/test_0a_filelink3 || error + lctl << EOF + device $mdsnum + root_squash root:root + root_squash + quit +EOF + mkdir $DIR/test_0a_dir4 + touch $DIR/test_0a_file4 + ln -s $DIR/test_0a_file4 $DIR/test_0a_filelink4 + $CHECKSTAT -t dir -u root $DIR/test_0a_dir4 || error + $CHECKSTAT -t file -u root $DIR/test_0a_file4 || error + $CHECKSTAT -t link -u root $DIR/test_0a_filelink4 || error + rm -rf $DIR/test_0a* + fi +} + +run_test 0a "test root_squash ============================" test_1a() { mkdir $DIR/d1 diff --git a/lustre/utils/lconf b/lustre/utils/lconf index ff9c71b..f2c97aa 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -421,6 +421,13 @@ class LCTLInterface: quit """ % (net, nid) self.run(cmds) + def root_squash(self, name, uid, nid): + cmds = """ + device $%s + root_squash %s %s + quit""" % (name, uid, nid) + self.run(cmds) + # create a new connection def add_uuid(self, net_type, uuid, nid): cmds = "\n add_uuid %s %s %s" %(uuid, nid, net_type) @@ -1495,6 +1502,8 @@ class MDSDEV(Module): self.nspath = self.db.get_val('nspath', '') self.mkfsoptions = self.db.get_val('mkfsoptions', '') self.mountfsoptions = self.db.get_val('mountfsoptions', '') + self.root_squash = self.db.get_val('root_squash', '') + self.no_root_squash = self.db.get_val('no_root_squash', '') self.cachetype = self.db.get_val('cachetype', '') # overwrite the orignal MDSDEV name and uuid with the MDS name and uuid target_uuid = self.db.get_first_ref('target') @@ -1679,6 +1688,17 @@ class MDSDEV(Module): "lconf --write_conf.") else: raise e + + if config.root_squash == None: + config.root_squash = self.root_squash + if config.no_root_squash == None: + config.no_root_squash = self.no_root_squash + if config.root_squash: + if config.no_root_squash: + nsnid = config.no_root_squash + else: + nsnid = "0" + lctl.root_squash(self.name, config.root_squash, nsnid) def write_conf(self): do_cleanup = 0 @@ -3295,6 +3315,10 @@ lconf_options = [ ('record_log', "Name of config record log.", PARAM), ('record_device', "MDS device name that will record the config commands", PARAM), + ('root_squash', "MDS squash root to appointed uid", + PARAM), + ('no_root_squash', "Don't squash root for appointed nid", + PARAM), ('minlevel', "Minimum level of services to configure/cleanup", INTPARAM, 0), ('maxlevel', """Maximum level of services to configure/cleanup diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index 95421d2..cc62982 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -230,6 +230,9 @@ command_t cmdlist[] = { "disable writes to the underlying device\n"}, {"abort_recovery", jt_obd_abort_recovery, 0, "abort recovery on MDS device\n"}, + {"root_squash", jt_obd_root_squash, 0, + "squash root to 'uid:gid' except client 'nid'\n" + "usage: root_squash [uid:gid [nid]]\n"}, {"mount_option", jt_lcfg_mount_option, 0, "usage: mount_option profile osc_name [mdc_name] \n"}, {"del_mount_option", jt_lcfg_del_mount_option, 0, diff --git a/lustre/utils/lmc b/lustre/utils/lmc index 335572a..d03fd01 100755 --- a/lustre/utils/lmc +++ b/lustre/utils/lmc @@ -96,6 +96,8 @@ Object creation command summary: --lmv lmv_name --mkfsoptions options --mountfsoptions options + --root_squash uid:gid + --no_root_squash ptl_nid --add lov --lov lov_name @@ -230,6 +232,8 @@ lmc_options = [ ('backfstype', "Optional argument to specify the backing filesystem type.", PARAM, "ext3"), ('mkfsoptions', "Optional argument to mkfs.", PARAM, ""), ('mountfsoptions', "Optional argument to mount fs.", PARAM, ""), + ('root_squash', "MDS squash root to appointed uid.", PARAM, ""), + ('no_root_squash', "Don't squash root for appointed nid.", PARAM, ""), ('ostuuid', "", PARAM,""), ('nspath', "Local mount point of server namespace.", PARAM,""), ('format', ""), @@ -523,7 +527,7 @@ class GenConfig: def mdsdev(self, name, uuid, fstype, devname, format, node_uuid, mds_uuid, dev_size=0, journal_size=0, inode_size=256, nspath="", mkfsoptions="", mountfsoptions="", backfstype="", - backdevname="", lmv_uuid=""): + backdevname="",lmv_uuid="", root_squash="", no_root_squash=""): mdd = self.newService("mdsdev", name, uuid) self.addElement(mdd, "fstype", fstype) if backfstype: @@ -544,7 +548,10 @@ class GenConfig: self.addElement(mdd, "mkfsoptions", mkfsoptions) if mountfsoptions: self.addElement(mdd, "mountfsoptions", mountfsoptions) - + if root_squash: + self.addElement(mdd, "root_squash", root_squash) + if no_root_squash: + self.addElement(mdd, "no_root_squash", no_root_squash) mdd.appendChild(self.ref("node", node_uuid)) mdd.appendChild(self.ref("target", mds_uuid)) mdd.appendChild(self.dev(devname)) @@ -1011,6 +1018,8 @@ def add_mds(gen, lustre, options): nspath = get_option(options, 'nspath') mkfsoptions = get_option(options, 'mkfsoptions') mountfsoptions = get_option(options, 'mountfsoptions') + root_squash = get_option(options, 'root_squash') + no_root_squash = get_option(options, 'no_root_squash') node_uuid = name2uuid(lustre, node_name, 'node') @@ -1026,7 +1035,8 @@ def add_mds(gen, lustre, options): mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname, get_format_flag(options), node_uuid, mds_uuid, size, journal_size, inode_size, nspath, mkfsoptions, - mountfsoptions, backfstype, backdevname, lmv_uuid) + mountfsoptions, backfstype, backdevname,lmv_uuid, + root_squash, no_root_squash) lustre.appendChild(mdd) diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 6ba7578..b0f2643 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -35,7 +35,9 @@ #include #include #include - +#include +#include +#include #include "obdctl.h" #include /* for struct lov_stripe_md */ @@ -747,6 +749,136 @@ int jt_obd_abort_recovery(int argc, char **argv) return rc; } +static int is_number(char *str) +{ + int i, len; + + if (*str == '-' || *str == '+') + str++; + + if (!strncmp(str, "0x", 2)) + str += 2; + + len = strlen(str); + if (!len) + return 0; + + for (i = 0; i < len; i++) + if (!isdigit(str[i])) + return 0; + return 1; +} + +static int str2ugid(char *str, uint32_t *uid, uint32_t *gid) +{ + struct passwd *pwd; + struct group *grp; + char *p; + + p = strchr(str, ':'); + if (!p) + return -1; + *p++ = 0; + + pwd = getpwnam(str); + if (pwd) + *uid = pwd->pw_uid; + else { + if (!is_number(str)) + return -1; + *uid = atoi(str); + } + + grp = getgrnam(p); + if (grp) + *gid = grp->gr_gid; + else { + if (!is_number(p)) + return -1; + *gid = atoi(p); + } + return 0; +} + +static void ugid2str(char *uidname, char *gidname, uint32_t uid, uint32_t gid) +{ + struct passwd *pwd; + struct group *grp; + + pwd = getpwuid(uid); + if (pwd) + snprintf(uidname, 128, "%s", pwd->pw_name); + else + snprintf(uidname, 128, "%d", uid); + + grp = getgrgid(gid); + if (grp) + snprintf(gidname, 128, "%s", grp->gr_name); + else + snprintf(uidname, 128, "%d", gid); +} + +#define SQUASH_IOC_SIZE (4 * 4 + sizeof(ptl_nid_t)) +int jt_obd_root_squash(int argc, char **argv) +{ + struct obd_ioctl_data data; + char mybuf[SQUASH_IOC_SIZE]; + uint32_t *dir, *uid, *gid; + ptl_nid_t *nid; + int rc; + + IOC_INIT(data); + + if (argc > 3) + return CMD_HELP; + + memset(mybuf, 0, sizeof(mybuf)); + dir = (uint32_t *) mybuf; + uid = dir + 2; + gid = dir + 3; + nid = (ptl_nid_t *) (dir + 4); + + if (argc == 1) { + *dir = 0; + } else { + *dir = 1; + if (str2ugid(argv[1], uid, gid)) { + fprintf(stderr, "error: %s: can't parse ugid %s\n", + jt_cmdname(argv[0]), argv[1]); + return -1; + } + if (argc == 3) { + if (ptl_parse_nid(nid, argv[2])) { + fprintf(stderr, + "error: %s: can't parse nid %s\n", + jt_cmdname(argv[0]), argv[2]); + return -1; + } + } else + *nid = 0; + } + + data.ioc_inllen1= SQUASH_IOC_SIZE; + data.ioc_inlbuf1 = mybuf; + + IOC_PACK(argv[0], data); + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_ROOT_SQUASH, buf); + IOC_UNPACK(argv[0], data); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + else if (argc == 1) { + char uidname[128], gidname[128]; + char nidstr[256] = {0, }; + + ugid2str(uidname, gidname, *uid, *gid); + ptl_nid2str(nidstr, *nid); + printf("squash (root:root) => (%s:%s), except nid %s\n", + uidname, gidname, nidstr); + } + + return rc; +} int jt_get_version(int argc, char **argv) { diff --git a/lustre/utils/obdctl.h b/lustre/utils/obdctl.h index 3004651..daa8989 100644 --- a/lustre/utils/obdctl.h +++ b/lustre/utils/obdctl.h @@ -53,6 +53,7 @@ int jt_obd_cleanup(int argc, char **argv); int jt_obd_no_transno(int argc, char **argv); int jt_obd_set_readonly(int argc, char **argv); int jt_obd_abort_recovery(int argc, char **argv); +int jt_obd_root_squash(int argc, char **argv); int jt_obd_list(int argc, char **argv); int jt_obd_create(int argc, char **argv); int jt_obd_setattr(int argc, char **argv); -- 1.8.3.1