Whamcloud - gitweb
b: b_hd_bug3270 land branch b_hd_bug3270 into HEAD
authorliuduo <liuduo>
Thu, 26 Aug 2004 09:49:35 +0000 (09:49 +0000)
committerliuduo <liuduo>
Thu, 26 Aug 2004 09:49:35 +0000 (09:49 +0000)
12 files changed:
lustre/include/linux/lustre_lib.h
lustre/include/linux/obd.h
lustre/mds/handler.c
lustre/mds/mds_lov.c
lustre/smfs/journal.c [new file with mode: 0644]
lustre/tests/checkstat.c
lustre/tests/sanity.sh
lustre/utils/lconf
lustre/utils/lctl.c
lustre/utils/lmc
lustre/utils/obd.c
lustre/utils/obdctl.h

index 04de0a5..6f1f96d 100644 (file)
@@ -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)
 
index d5f5459..7e7ccdc 100644 (file)
@@ -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;
index 3bba6bb..d1fd5e1 100644 (file)
@@ -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:
index f935f42..a1ece50 100644 (file)
@@ -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 (file)
index 0000000..ab62e7a
--- /dev/null
@@ -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 <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
+#include <linux/lvfs.h>
+#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;
+}
index c98d6aa..acfdfa8 100644 (file)
@@ -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;i<strlen(optarg);i++)
                                {
-                                       fprintf (stderr, "Can't find user %s\n", optarg);
-                                       return (1);
+                                       if(!isdigit(*temp))     
+                                       {
+                                               flag=1;
+                                               break;
+                                       }
+                                       else
+                                               temp++; 
+                               }
+                               if(flag)
+                               {
+                                      struct passwd *pw = getpwnam (optarg);
+
+                                       if (pw == NULL)
+                                       {
+                                               fprintf (stderr, "Can't find user %s\n", optarg);
+                                               return (1);
+                                       }
+                                       uid = pw->pw_uid;
+       
                                }
-                               uid = pw->pw_uid;
+                               else
+                                       uid=(uid_t)atol(optarg);
                        }
                        break;
 
index ed4a78e..7c8f2cc 100644 (file)
@@ -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
index ff9c71b..f2c97aa 100755 (executable)
@@ -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
index 95421d2..cc62982 100644 (file)
@@ -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,
index 335572a..d03fd01 100755 (executable)
@@ -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)
 
 
index 6ba7578..b0f2643 100644 (file)
@@ -35,7 +35,9 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <signal.h>
-
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
 #include "obdctl.h"
 
 #include <linux/obd.h>          /* 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)
 {
index 3004651..daa8989 100644 (file)
@@ -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);