From d6ffcf90116f431a1924225ad1db4c74617fd767 Mon Sep 17 00:00:00 2001 From: braam Date: Thu, 24 Jan 2002 08:04:57 +0000 Subject: [PATCH] - more systematic unpacking/packing and handling of update records - create working on MDS (needs some refinements to store data object id) --- lustre/include/linux/lustre_idl.h | 27 ++++++++- lustre/include/linux/lustre_mds.h | 28 ++++++++- lustre/lib/mds_updates.c | 107 ++++++++++++++++++++++++++++++++- lustre/mdc/mdc_reint.c | 32 ++++++++++ lustre/mdc/mdc_request.c | 22 +++++++ lustre/mds/handler.c | 33 +++++----- lustre/mds/mds_reint.c | 123 +++++++++++++++++++++++++++++--------- lustre/tests/testreq.c | 5 ++ 8 files changed, 321 insertions(+), 56 deletions(-) diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 518c1c9..f1d966d 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -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) diff --git a/lustre/include/linux/lustre_mds.h b/lustre/include/linux/lustre_mds.h index 66ec13b..1ee99b5 100644 --- a/lustre/include/linux/lustre_mds.h +++ b/lustre/include/linux/lustre_mds.h @@ -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 diff --git a/lustre/lib/mds_updates.c b/lustre/lib/mds_updates.c index ef38466..802e909 100644 --- a/lustre/lib/mds_updates.c +++ b/lustre/lib/mds_updates.c @@ -33,11 +33,32 @@ #include #include +/* 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; } diff --git a/lustre/mdc/mdc_reint.c b/lustre/mdc/mdc_reint.c index a39c56a..734ccad 100644 --- a/lustre/mdc/mdc_reint.c +++ b/lustre/mdc/mdc_reint.c @@ -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; +} diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 4930ee9..1eee16c 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -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 "); 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); diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 3585f8c..c66f26c 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -33,7 +33,7 @@ #include #include -// 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; } diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 48a86f6..d51e669 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -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 * * This code is issued under the GNU General Public License. * See the file COPYING in this distribution * - * by Peter Braam - * - * This server is single threaded at present (but can easily be multi threaded). - * */ +// XXX - add transaction sequence numbers #define EXPORT_SYMTAB @@ -35,29 +33,101 @@ 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; +} diff --git a/lustre/tests/testreq.c b/lustre/tests/testreq.c index 00f7a6b..aeacddf 100644 --- a/lustre/tests/testreq.c +++ b/lustre/tests/testreq.c @@ -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; } -- 1.8.3.1