Whamcloud - gitweb
- more systematic unpacking/packing and handling of update records
authorbraam <braam>
Thu, 24 Jan 2002 08:04:57 +0000 (08:04 +0000)
committerbraam <braam>
Thu, 24 Jan 2002 08:04:57 +0000 (08:04 +0000)
- create working on MDS (needs some refinements to store data object id)

lustre/include/linux/lustre_idl.h
lustre/include/linux/lustre_mds.h
lustre/lib/mds_updates.c
lustre/mdc/mdc_reint.c
lustre/mdc/mdc_request.c
lustre/mds/handler.c
lustre/mds/mds_reint.c
lustre/tests/testreq.c

index 518c1c9..f1d966d 100644 (file)
@@ -198,7 +198,9 @@ struct obd_bufref {
 #define MDS_REINT     2
 #define MDS_READPAGE  3
 
-#define REINT_SETATTR 1
+#define REINT_SETATTR 0
+#define REINT_CREATE  1
+#define REINT_MAX     1
 
 struct mds_req_hdr { 
        __u32 opc;
@@ -268,8 +270,15 @@ struct mds_rep_packed {
 };
 
 
+/* MDS update records */ 
+
+struct mds_update_record_hdr { 
+        __u32 ur_reclen;
+        __u32 ur_opcode;
+};
+
 struct mds_rec_setattr { 
-        __u32           sa_len;
+        __u32           sa_reclen;
         __u32           sa_opcode;
        struct ll_fid   sa_fid;
        __u32           sa_valid;
@@ -283,6 +292,20 @@ struct mds_rec_setattr {
        __u32           sa_attr_flags;
 };
 
+struct mds_rec_create { 
+        __u32           cr_reclen;
+        __u32           cr_opcode;
+       struct ll_fid   cr_fid;
+        __u32           cr_uid;
+        __u32           cr_gid;
+        __u64           cr_time;
+       __u32           cr_mode;
+        /* overloaded: id for create, tgtlen for symlink, rdev for mknod */ 
+       __u64           cr_id; 
+        __u32           cr_namelen;
+        /* name here */
+};
+
 #ifdef __KERNEL__ 
 
 static inline void ll_ino2fid(struct ll_fid *fid, ino_t ino, __u32 generation, int type)
index 66ec13b..1ee99b5 100644 (file)
@@ -123,6 +123,22 @@ struct mds_rep {
         __u32                       generation;
 };
 
+struct mds_update_record { 
+        __u32 ur_reclen;
+        __u32 ur_opcode;
+        struct ll_fid *ur_fid1;
+        struct ll_fid *ur_fid2;
+        int ur_namelen;
+        char *ur_name;
+        int ur_tgtlen;
+        char *ur_tgt;
+        struct iattr ur_iattr;
+        __u64 ur_id;
+        __u32 ur_mode;
+        __u32 ur_uid;
+        __u32 ur_gid;
+        __u64 ur_time;
+}; 
 
 /* mds/mds_pack.c */
 void *mds_req_tgt(struct mds_req *req);
@@ -132,11 +148,13 @@ int mds_pack_rep(char *name, int namelen, char *tgt, int tgtlen, struct mds_rep_
 int mds_unpack_rep(char *buf, int len, struct mds_rep_hdr **hdr, struct mds_rep **rep);
 
 /* mds/mds_reint.c  */
-int mds_reint_setattr(struct mds_request *req);
+int mds_reint_rec(struct mds_update_record *r, struct mds_request *req); 
 
 /* lib/mds_updates.c */
-void mds_setattr_unpack(struct mds_rec_setattr *rec, struct iattr *attr);
+int mds_update_unpack(char *buf, int len, struct mds_update_record *r); 
+
 void mds_setattr_pack(struct mds_rec_setattr *rec, struct inode *inode, struct iattr *iattr);
+void mds_create_pack(struct mds_rec_create *rec, struct inode *inode, char *name, __u32 mode, __u64 id, __u32 uid, __u32 gid, __u64 time);
 
 /* mds/handler.c */
 struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid, struct vfsmount **mnt);
@@ -149,6 +167,9 @@ int mdc_setattr(struct inode *inode, struct iattr *iattr,
                struct mds_rep  **mds_reply, struct mds_rep_hdr **hdr);
 int mdc_readpage(ino_t ino, int type, __u64 offset, char *addr, 
                  struct mds_rep  **rep, struct mds_rep_hdr **hdr);
+int mdc_create(struct inode *dir, char *name, int mode, __u64 id, 
+               __u32 uid, __u32 gid, __u64 time, 
+               struct mds_rep **rep, struct mds_rep_hdr **hdr);
 
 
 
@@ -159,7 +180,8 @@ int mdc_readpage(ino_t ino, int type, __u64 offset, char *addr,
 #define IOC_REQUEST_GETATTR            _IOWR('f', 30, long)
 #define IOC_REQUEST_READPAGE           _IOWR('f', 31, long)
 #define IOC_REQUEST_SETATTR            _IOWR('f', 32, long)
-#define IOC_REQUEST_MAX_NR               32
+#define IOC_REQUEST_CREATE             _IOWR('f', 33, long)
+#define IOC_REQUEST_MAX_NR               33
 
 #endif
 
index ef38466..802e909 100644 (file)
 #include <linux/lustre_idl.h>
 #include <linux/lustre_light.h>
 
+/* packing of MDS records */
+
+void mds_create_pack(struct mds_rec_create *rec, struct inode *inode, char *name, __u32 mode, __u64 id, __u32 uid, __u32 gid, __u64 time)
+{
+       char *tmp = (char *)rec + sizeof(*rec); 
+       /* XXX do something about time, uid, gid */
+       rec->cr_reclen = 
+               HTON__u32(sizeof(*rec)) + size_round(strlen(name) + 1);
+       rec->cr_opcode = HTON__u32(REINT_CREATE);
+
+       ll_inode2fid(&rec->cr_fid, inode); 
+       rec->cr_mode = HTON__u32(mode);
+       rec->cr_id = HTON__u64(id);
+       rec->cr_uid = HTON__u32(uid);
+       rec->cr_gid = HTON__u32(gid);
+       rec->cr_time = HTON__u64(time);
+       rec->cr_namelen = strlen(name);
+       LOGL(name, rec->cr_namelen + 1, tmp); 
+}
+
 
 void mds_setattr_pack(struct mds_rec_setattr *rec, struct inode *inode, struct iattr *iattr)
 {
-       rec->sa_len = HTON__u32(sizeof(*rec));
-       rec->sa_opcode = HTON__u32(sizeof(REINT_SETATTR));
+       rec->sa_reclen = HTON__u32(sizeof(*rec));
+       rec->sa_opcode = HTON__u32(REINT_SETATTR);
+
        ll_inode2fid(&rec->sa_fid, inode); 
        rec->sa_valid = HTON__u32(iattr->ia_valid);
        rec->sa_mode = HTON__u32(iattr->ia_mode);
@@ -50,8 +71,33 @@ void mds_setattr_pack(struct mds_rec_setattr *rec, struct inode *inode, struct i
        rec->sa_attr_flags = HTON__u32(iattr->ia_attr_flags);
 }
 
-void mds_setattr_unpack(struct mds_rec_setattr *rec, struct iattr *attr)
+/* unpacking */
+
+static int mds_update_hdr_unpack(char *buf, int len, struct mds_update_record *r)
 {
+       struct mds_update_record_hdr *hdr = (struct mds_update_record_hdr *)buf;
+       
+       r->ur_reclen = NTOH__u32(hdr->ur_reclen);
+       if (len < sizeof(*hdr) || len != r->ur_reclen) { 
+               printk(__FUNCTION__ "invalid buffer length\n"); 
+               return -EFAULT;
+       }
+       r->ur_opcode = NTOH__u32(hdr->ur_opcode); 
+       return 0;
+}
+
+static int mds_setattr_unpack(char *buf, int len, struct mds_update_record *r)
+{
+
+       struct iattr *attr = &r->ur_iattr;
+       struct mds_rec_setattr *rec = (struct mds_rec_setattr *)buf; 
+
+       if (len < sizeof(*rec)) { 
+               printk(__FUNCTION__ "invalid buffer length\n"); 
+               return -EFAULT;
+       }
+
+       r->ur_fid1 = &rec->sa_fid; 
        attr->ia_valid = NTOH__u32(rec->sa_valid);
        attr->ia_mode = NTOH__u32(rec->sa_mode);
        attr->ia_uid = NTOH__u32(rec->sa_uid);
@@ -61,4 +107,59 @@ void mds_setattr_unpack(struct mds_rec_setattr *rec, struct iattr *attr)
        attr->ia_mtime = NTOH__u64(rec->sa_mtime);
        attr->ia_ctime = NTOH__u64(rec->sa_ctime);
        attr->ia_attr_flags = NTOH__u32(rec->sa_attr_flags);
+       return 0; 
+}
+
+static int mds_create_unpack(char *buf, int len, struct mds_update_record *r)
+{
+       struct mds_rec_create *rec = (struct mds_rec_create *)buf; 
+       char *ptr, *end;
+
+       if (len < sizeof(*rec)) { 
+               printk(__FUNCTION__ "invalid buffer length\n"); 
+               return -EFAULT;
+       }
+       
+       ptr = (char *)rec + sizeof(*rec); 
+       end = ptr + len - sizeof(*rec); 
+       
+       r->ur_fid1 = &rec->cr_fid;
+       r->ur_mode = NTOH__u32(rec->cr_mode);
+       r->ur_id = NTOH__u64(rec->cr_id);
+       r->ur_uid = NTOH__u32(rec->cr_uid);
+       r->ur_gid = NTOH__u32(rec->cr_gid);
+       r->ur_time = NTOH__u64(rec->cr_time);
+       r->ur_namelen = NTOH__u64(rec->cr_namelen);
+
+       UNLOGL(r->ur_name, char, r->ur_namelen, ptr, end); 
+       return 0;
+}
+
+typedef int (*update_unpacker)(char *, int , struct mds_update_record *); 
+
+static update_unpacker mds_unpackers[REINT_MAX + 1] = {
+       [REINT_SETATTR] mds_setattr_unpack,     
+        [REINT_CREATE] mds_create_unpack
+};
+
+int mds_update_unpack(char *buf, int len, struct mds_update_record *r)
+{
+       int rc; 
+       ENTRY;
+
+       rc = mds_update_hdr_unpack(buf, len, r);
+
+       if (rc) { 
+               EXIT;
+               return -EFAULT;
+       }
+
+       if ( r->ur_opcode<0 || r->ur_opcode > REINT_MAX) { 
+               EXIT;
+               return EFAULT; 
+       }
+       
+       rc = mds_unpackers[r->ur_opcode](buf, len, r);
+       EXIT;
+       return rc;
 }
index a39c56a..734ccad 100644 (file)
@@ -63,3 +63,35 @@ int mdc_setattr(struct inode *inode, struct iattr *iattr,
        kfree(request); 
        return rc;
 }
+
+int mdc_create(struct inode *dir, char *name, int mode, __u64 id, 
+              __u32 uid, __u32 gid, __u64 time, 
+               struct mds_rep **rep, struct mds_rep_hdr **hdr)
+{
+       int rc; 
+       struct mds_request *request;
+       struct mds_rec_create *rec;
+
+       request = mds_prep_req(MDS_REINT, 0, NULL, 
+                              sizeof(*rec) + size_round(strlen(name)), 
+                              NULL);
+       if (!request) { 
+               printk("mdc_create: cannot pack\n");
+               return -ENOMEM;
+       }
+
+       rec = mds_req_tgt(request->rq_req);
+       mds_create_pack(rec, dir, name, mode, id, uid, gid, time); 
+
+       rc = mdc_reint(request);
+
+       if (rep) { 
+               *rep = request->rq_rep;
+       }
+       if (hdr) { 
+               *hdr = request->rq_rephdr;
+       }
+
+       kfree(request); 
+       return rc;
+}
index 4930ee9..1eee16c 100644 (file)
@@ -266,6 +266,27 @@ static int request_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
+       case IOC_REQUEST_CREATE: { 
+               struct inode inode;
+               struct mds_rep_hdr *hdr;
+               struct iattr iattr; 
+
+               inode.i_ino = 2;
+               iattr.ia_mode = 040777;
+               iattr.ia_atime = 0;
+               iattr.ia_valid = ATTR_MODE | ATTR_ATIME;
+
+               err = mdc_create(&inode, "foofile", 0100707, 47114711, 
+                                11, 47, 0, NULL, &hdr);
+               printk("-- done err %d\n", err);
+               if (!err) { 
+                       printk("-- status: %d\n", hdr->status); 
+                       err = hdr->status;
+               }
+               kfree(hdr); 
+               break;
+       }
+
        default:                
                err = -EINVAL;
                EXIT;
@@ -304,6 +325,7 @@ MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
 MODULE_DESCRIPTION("Lustre MDS Request Tester v1.0");
 MODULE_LICENSE("GPL");
 
+EXPORT_SYMBOL(mdc_create); 
 EXPORT_SYMBOL(mdc_getattr); 
 EXPORT_SYMBOL(mdc_readpage); 
 EXPORT_SYMBOL(mdc_setattr); 
index 3585f8c..c66f26c 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/lustre_mds.h>
 #include <linux/obd_class.h>
 
-// for testing
+// XXX for testing
 static struct mds_obd *MDS;
 
 // XXX make this networked!  
@@ -133,16 +133,7 @@ int mds_error(struct mds_request *req)
 
 struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid, struct vfsmount **mnt)
 {
-
-       /* iget isn't really right if the inode is currently unallocated!!
-        * This should really all be done inside each filesystem
-        *
-        * ext2fs' read_inode has been strengthed to return a bad_inode if the inode
-        *   had been deleted.
-        *
-        * Currently we don't know the generation for parent directory, so a generation
-        * of 0 means "accept any"
-        */
+       /* stolen from NFS */ 
        struct super_block *sb = mds->mds_sb; 
        unsigned long ino = fid->id;
        //__u32 generation = fid->generation;
@@ -157,6 +148,7 @@ struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid, struct vf
 
        if (ino == 0)
                return ERR_PTR(-ESTALE);
+
        inode = iget(sb, ino);
        if (inode == NULL)
                return ERR_PTR(-ENOMEM);
@@ -167,15 +159,16 @@ struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid, struct vf
            || (generation && inode->i_generation != generation)
                ) {
                /* we didn't find the right inode.. */
-               printk("mds_fid2dentry: Inode %lu, Bad count: %d %d or version  %u %u\n",
+               printk(__FUNCTION__ 
+                      "bad inode %lu, link: %d ct: %d or version  %u/%u\n",
                        inode->i_ino,
                        inode->i_nlink, atomic_read(&inode->i_count),
                        inode->i_generation,
                        generation);
-
                iput(inode);
                return ERR_PTR(-ESTALE);
        }
+
        /* now to find a dentry.
         * If possible, get a well-connected one
         */
@@ -293,16 +286,18 @@ int mds_readpage(struct mds_request *req)
 
 int mds_reint(struct mds_request *req)
 {
-       int opc = NTOH__u32(req->rq_req->opcode);
+       int rc;
+       char *buf = mds_req_tgt(req->rq_req);
+       int len = req->rq_req->tgtlen;
+       struct mds_update_record rec;
        
-       switch (opc) { 
-       case REINT_SETATTR: 
-               return mds_reint_setattr(req);
-       default: 
-               printk(__FUNCTION__ "opcode %d not handled.\n", opc); 
+       rc = mds_update_unpack(buf, len, &rec);
+       if (rc) { 
+               printk(__FUNCTION__ ": invalid record\n");
                return -EINVAL;
        }
 
+       rc = mds_reint_rec(&rec, req); 
        return 0; 
 }
 
index 48a86f6..d51e669 100644 (file)
@@ -1,19 +1,17 @@
 /*
- *  linux/mds/handler.c
+ *  linux/mds/mds_reint.c
  *  
- *  Lustre Metadata Server (mds) request handler
+ *  Lustre Metadata Server (mds) reintegration routines
  * 
- *  Copyright (C) 2001  Cluster File Systems, Inc.
+ *  Copyright (C) 2002  Cluster File Systems, Inc.
+ *  author: Peter Braam <braam@clusterfs.com>
  *
  *  This code is issued under the GNU General Public License.
  *  See the file COPYING in this distribution
  *
- *  by Peter Braam <braam@clusterfs.com>
- * 
- *  This server is single threaded at present (but can easily be multi threaded). 
- * 
  */
 
+// XXX - add transaction sequence numbers
 
 #define EXPORT_SYMTAB
 
 
 extern struct mds_request *mds_prep_req(int size, int opcode, int namelen, char *name, int tgtlen, char *tgt);
 
+static int mds_reint_setattr(struct mds_update_record *rec, struct mds_request *req)
+{
+       struct vfsmount *mnt;
+       struct dentry *de;
+
+       de = mds_fid2dentry(req->rq_obd, rec->ur_fid1, &mnt);
+       if (IS_ERR(de)) { 
+               req->rq_rephdr->status = -ESTALE;
+               return 0;
+       }
+
+       printk("mds_setattr: ino %ld\n", de->d_inode->i_ino);
+       req->rq_rephdr->status = notify_change(de, &rec->ur_iattr);
+
+       dput(de);
+       EXIT;
+       return 0;
+}
 
-int mds_reint_setattr(struct mds_request *req)
+static int mds_reint_create(struct mds_update_record *rec, 
+                           struct mds_request *req)
 {
        struct vfsmount *mnt;
+       int type = rec->ur_mode & S_IFMT;
        struct dentry *de;
-       struct mds_rep *rep;
-       struct mds_rec_setattr *rec;
-       struct iattr attr;
+       struct dentry *dchild; 
        int rc;
 
-       if (req->rq_req->tgtlen != sizeof(struct mds_rec_setattr) ) { 
-               EXIT;
-               printk("mds: out of memory\n");
-               req->rq_status = -EINVAL;
-               return -EINVAL;
+       de = mds_fid2dentry(req->rq_obd, rec->ur_fid1, &mnt);
+       if (IS_ERR(de)) { 
+               req->rq_rephdr->status = -ESTALE;
+               return 0;
        }
-       rec = mds_req_tgt(req->rq_req);
+       printk("mds_reint_create: ino %ld\n", de->d_inode->i_ino);
 
-       mds_setattr_unpack(rec, &attr); 
-       de = mds_fid2dentry(req->rq_obd, &rec->sa_fid, &mnt);
+       dchild = lookup_one_len(rec->ur_name, de, rec->ur_namelen);
+       rc = PTR_ERR(dchild);
+       if (IS_ERR(dchild)) { 
+               printk(__FUNCTION__ "child lookup error %d\n", rc);
+               dput(de); 
+               req->rq_rephdr->status = -ESTALE;
+               return 0;
+       }
+
+       if (dchild->d_inode) {
+               printk(__FUNCTION__ "child exists (dir %ld, name %s\n", 
+                      de->d_inode->i_ino, rec->ur_name);
+               dput(de); 
+               req->rq_rephdr->status = -ESTALE;
+               return 0;
+       }
+
+       switch (type) {
+       case S_IFREG: { 
+               rc = vfs_create(de->d_inode, dchild, rec->ur_mode);
+               break;
+       }
+       case S_IFDIR: { 
+               rc = vfs_mkdir(de->d_inode, dchild, rec->ur_mode);
+               break;
+       } 
+       case S_IFCHR:
+       case S_IFBLK:
+       case S_IFIFO:
+       case S_IFSOCK: { 
+               int rdev = rec->ur_id;
+               rc = vfs_mknod(de->d_inode, dchild, rec->ur_mode, rdev); 
+               break;
+       }
+       }
+       req->rq_rephdr->status = rc;
+
+       dput(de);
+       dput(dchild); 
+       EXIT;
+       return 0;
+}
+
+typedef int (*mds_reinter)(struct mds_update_record *, struct mds_request*); 
+
+static mds_reinter  reinters[REINT_MAX+1] = { 
+       [REINT_SETATTR]   mds_reint_setattr, 
+       [REINT_CREATE]   mds_reint_create
+};
+
+int mds_reint_rec(struct mds_update_record *rec, struct mds_request *req)
+{
+       int rc; 
+
+       if (rec->ur_opcode < 0 || rec->ur_opcode > REINT_MAX) { 
+               printk(__FUNCTION__ "opcode %d not valid\n", 
+                      rec->ur_opcode); 
+               return -EINVAL;
+       }
 
-       printk("mds_setattr: ino %ld\n", de->d_inode->i_ino);
-       
        rc = mds_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep, 
                          &req->rq_replen, &req->rq_repbuf);
        if (rc) { 
@@ -66,14 +136,9 @@ int mds_reint_setattr(struct mds_request *req)
                req->rq_status = -ENOMEM;
                return -ENOMEM;
        }
-
        req->rq_rephdr->seqno = req->rq_reqhdr->seqno;
-       rep = req->rq_rep;
-       req->rq_rephdr->status = notify_change(de, &attr);
-
-       dput(de);
-       EXIT;
-       return 0;
-}
 
+       rc = reinters[rec->ur_opcode](rec, req); 
+       return rc;
+} 
 
index 00f7a6b..aeacddf 100644 (file)
@@ -7,6 +7,7 @@
 #define IOC_REQUEST_GETATTR            _IOWR('f', 30, long)
 #define IOC_REQUEST_READPAGE           _IOWR('f', 31, long)
 #define IOC_REQUEST_SETATTR            _IOWR('f', 32, long)
+#define IOC_REQUEST_CREATE             _IOWR('f', 33, long)
 
 int main(int argc, char **argv)
 {
@@ -33,5 +34,9 @@ int main(int argc, char **argv)
        printf("setattr test... ");
        rc = ioctl(fd, IOC_REQUEST_SETATTR, NULL); 
        printf("result: %d\n", rc); 
+
+       printf("create test... ");
+       rc = ioctl(fd, IOC_REQUEST_CREATE, NULL); 
+       printf("result: %d\n", rc); 
        return 0;
 }