From: braam Date: Wed, 27 Mar 2002 23:35:45 +0000 (+0000) Subject: There was a race between ll_unlink and ll_create_node: notably, X-Git-Tag: 0.4.2~465 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=448aa258e18e2cd9f7d826069a6b493d0feb5882;p=fs%2Flustre-release.git There was a race between ll_unlink and ll_create_node: notably, ll_unlink would make the inode available on the MDS before the local dentry/inode on the client was put away. This could lead to re-using inode numbers with a concurrent create going on. We fixed this using the generation number. We also added the inode/generation to unlink as a sanity check. --- diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index bfc239b..d4e5941 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -43,32 +43,32 @@ */ struct lustre_msg { - __u32 opc; - __u32 xid; - __u32 status; - __u32 type; - __u32 connid; - __u32 bufcount; + __u32 opc; + __u32 xid; + __u32 status; + __u32 type; + __u32 connid; + __u32 bufcount; __u32 buflens[0]; }; struct ptlreq_hdr { - __u32 opc; - __u32 xid; - __u32 status; - __u32 type; - __u32 connid; - __u32 bufcount; + __u32 opc; + __u32 xid; + __u32 status; + __u32 type; + __u32 connid; + __u32 bufcount; __u32 buflens[0]; }; struct ptlrep_hdr { - __u32 opc; - __u32 xid; - __u32 status; - __u32 type; - __u32 connid; - __u32 bufcount; + __u32 opc; + __u32 xid; + __u32 status; + __u32 type; + __u32 connid; + __u32 bufcount; __u32 buflens[0]; }; @@ -159,19 +159,19 @@ struct obdo { #define OST_REQ_HAS_OA1 0x1 struct ost_req { - __u32 connid; - __u32 cmd; - struct obdo oa; - __u32 buflen1; - __u32 buflen2; + __u32 connid; + __u32 cmd; + struct obdo oa; + __u32 buflen1; + __u32 buflen2; }; struct ost_rep { - __u32 result; - __u32 connid; - struct obdo oa; - __u32 buflen1; - __u32 buflen2; + __u32 result; + __u32 connid; + struct obdo oa; + __u32 buflen1; + __u32 buflen2; }; struct obd_ioobj { @@ -200,9 +200,9 @@ struct obd_ioobj { #define REINT_MAX 4 struct ll_fid { - __u64 id; - __u32 generation; - __u32 f_type; + __u64 id; + __u32 generation; + __u32 f_type; }; struct niobuf { @@ -215,13 +215,13 @@ struct niobuf { }; struct mds_req { - struct ll_fid fid1; - struct ll_fid fid2; + struct ll_fid fid1; + struct ll_fid fid2; __u32 namelen; __u32 tgtlen; __u32 opcode; __u32 valid; - __u32 mode; + __u32 mode; __u32 uid; __u32 gid; __u64 objid; @@ -238,12 +238,12 @@ struct mds_req { }; struct mds_rep { - struct ll_fid fid1; - struct ll_fid fid2; + struct ll_fid fid1; + struct ll_fid fid2; __u32 namelen; __u32 tgtlen; __u32 valid; - __u32 mode; + __u32 mode; __u32 uid; __u32 gid; __u64 objid; @@ -268,28 +268,28 @@ struct mds_update_record_hdr { struct mds_rec_setattr { __u32 sa_reclen; __u32 sa_opcode; - struct ll_fid sa_fid; - __u32 sa_valid; - __u32 sa_mode; - __u32 sa_uid; - __u32 sa_gid; - __u64 sa_size; - __u64 sa_atime; - __u64 sa_mtime; - __u64 sa_ctime; - __u32 sa_attr_flags; + struct ll_fid sa_fid; + __u32 sa_valid; + __u32 sa_mode; + __u32 sa_uid; + __u32 sa_gid; + __u64 sa_size; + __u64 sa_atime; + __u64 sa_mtime; + __u64 sa_ctime; + __u32 sa_attr_flags; }; struct mds_rec_create { __u32 cr_reclen; __u32 cr_opcode; - struct ll_fid cr_fid; + struct ll_fid cr_fid; __u32 cr_uid; __u32 cr_gid; __u64 cr_time; - __u32 cr_mode; + __u32 cr_mode; /* overloaded: id for create, tgtlen for symlink, rdev for mknod */ - __u64 cr_id; + __u64 cr_id; __u32 cr_namelen; __u32 cr_tgtlen; /* name here */ @@ -299,23 +299,24 @@ struct mds_rec_create { struct mds_rec_link { __u32 lk_reclen; __u32 lk_opcode; - struct ll_fid lk_fid1; - struct ll_fid lk_fid2; + struct ll_fid lk_fid1; + struct ll_fid lk_fid2; __u32 lk_namelen; }; struct mds_rec_unlink { __u32 ul_reclen; __u32 ul_opcode; - struct ll_fid ul_fid1; + struct ll_fid ul_fid1; + struct ll_fid ul_fid2; __u32 ul_namelen; }; struct mds_rec_rename { __u32 rn_reclen; __u32 rn_opcode; - struct ll_fid rn_fid1; - struct ll_fid rn_fid2; + struct ll_fid rn_fid1; + struct ll_fid rn_fid2; __u32 rn_namelen; __u32 rn_tgtlen; }; @@ -332,7 +333,8 @@ static inline void ll_ino2fid(struct ll_fid *fid, ino_t ino, __u32 generation, static inline void ll_inode2fid(struct ll_fid *fid, struct inode *inode) { - ll_ino2fid(fid, inode->i_ino, inode->i_generation, inode->i_mode &S_IFMT); + ll_ino2fid(fid, inode->i_ino, inode->i_generation, + inode->i_mode & S_IFMT); } #endif @@ -386,74 +388,74 @@ struct ldlm_reply { #define OBD_IOCTL_VERSION 0x00010001 struct obd_ioctl_data { - uint32_t ioc_len; - uint32_t ioc_version; + uint32_t ioc_len; + uint32_t ioc_version; uint32_t ioc_conn1; uint32_t ioc_conn2; - struct obdo ioc_obdo1; - struct obdo ioc_obdo2; + struct obdo ioc_obdo1; + struct obdo ioc_obdo2; obd_size ioc_count; obd_off ioc_offset; - uint32_t ioc_dev; + uint32_t ioc_dev; - /* buffers the kernel will treat as user pointers */ - uint32_t ioc_plen1; - char *ioc_pbuf1; - uint32_t ioc_plen2; - char *ioc_pbuf2; + /* buffers the kernel will treat as user pointers */ + uint32_t ioc_plen1; + char *ioc_pbuf1; + uint32_t ioc_plen2; + char *ioc_pbuf2; - /* two inline buffers */ - uint32_t ioc_inllen1; - char *ioc_inlbuf1; - uint32_t ioc_inllen2; - char *ioc_inlbuf2; + /* two inline buffers */ + uint32_t ioc_inllen1; + char *ioc_inlbuf1; + uint32_t ioc_inllen2; + char *ioc_inlbuf2; - char ioc_bulk[0]; + char ioc_bulk[0]; }; struct obd_ioctl_hdr { - uint32_t ioc_len; - uint32_t ioc_version; + uint32_t ioc_len; + uint32_t ioc_version; }; static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) { - int len = sizeof(struct obd_ioctl_data); - len += size_round(data->ioc_inllen1); - len += size_round(data->ioc_inllen2); - return len; + int len = sizeof(struct obd_ioctl_data); + len += size_round(data->ioc_inllen1); + len += size_round(data->ioc_inllen2); + return len; } static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) { - if (data->ioc_len > (1<<30)) { - printk("OBD ioctl: ioc_len larger than 1<<30\n"); - return 1; - } - if (data->ioc_inllen1 > (1<<30)) { - printk("OBD ioctl: ioc_inllen1 larger than 1<<30\n"); - return 1; - } - if (data->ioc_inllen2 > (1<<30)) { - printk("OBD ioctl: ioc_inllen2 larger than 1<<30\n"); - return 1; - } - if (data->ioc_inlbuf1 && !data->ioc_inllen1) { - printk("OBD ioctl: inlbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf2 && !data->ioc_inllen2) { - printk("OBD ioctl: inlbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf1 && !data->ioc_plen1) { - printk("OBD ioctl: pbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf2 && !data->ioc_plen2) { - printk("OBD ioctl: pbuf2 pointer but 0 length\n"); - return 1; - } + if (data->ioc_len > (1<<30)) { + printk("OBD ioctl: ioc_len larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen1 > (1<<30)) { + printk("OBD ioctl: ioc_inllen1 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen2 > (1<<30)) { + printk("OBD ioctl: ioc_inllen2 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inlbuf1 && !data->ioc_inllen1) { + printk("OBD ioctl: inlbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_inlbuf2 && !data->ioc_inllen2) { + printk("OBD ioctl: inlbuf2 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf1 && !data->ioc_plen1) { + printk("OBD ioctl: pbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf2 && !data->ioc_plen2) { + printk("OBD ioctl: pbuf2 pointer but 0 length\n"); + return 1; + } /* if (data->ioc_inllen1 && !data->ioc_inlbuf1) { printk("OBD ioctl: inllen1 set but NULL pointer\n"); @@ -472,51 +474,51 @@ static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) return 1; } */ - if (obd_ioctl_packlen(data) != data->ioc_len ) { - printk("OBD ioctl: packlen exceeds ioc_len\n"); - return 1; - } - if (data->ioc_inllen1 && - data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { - printk("OBD ioctl: inlbuf1 not 0 terminated\n"); - return 1; - } - if (data->ioc_inllen2 && - data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2 - 1] != '\0') { - printk("OBD ioctl: inlbuf2 not 0 terminated\n"); - return 1; - } - return 0; + if (obd_ioctl_packlen(data) != data->ioc_len ) { + printk("OBD ioctl: packlen exceeds ioc_len\n"); + return 1; + } + if (data->ioc_inllen1 && + data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { + printk("OBD ioctl: inlbuf1 not 0 terminated\n"); + return 1; + } + if (data->ioc_inllen2 && + data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2 - 1] != '\0') { + printk("OBD ioctl: inlbuf2 not 0 terminated\n"); + return 1; + } + return 0; } #ifndef __KERNEL__ static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, int max) { - char *ptr; - struct obd_ioctl_data *overlay; - data->ioc_len = obd_ioctl_packlen(data); - data->ioc_version = OBD_IOCTL_VERSION; - - if (*pbuf && obd_ioctl_packlen(data) > max) - return 1; - if (*pbuf == NULL) { - *pbuf = malloc(data->ioc_len); - } - if (!*pbuf) - return 1; - overlay = (struct obd_ioctl_data *)*pbuf; - memcpy(*pbuf, data, sizeof(*data)); - - ptr = overlay->ioc_bulk; - if (data->ioc_inlbuf1) - LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr); - if (data->ioc_inlbuf2) - LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr); - if (obd_ioctl_is_invalid(overlay)) - return 1; - - return 0; + char *ptr; + struct obd_ioctl_data *overlay; + data->ioc_len = obd_ioctl_packlen(data); + data->ioc_version = OBD_IOCTL_VERSION; + + if (*pbuf && obd_ioctl_packlen(data) > max) + return 1; + if (*pbuf == NULL) { + *pbuf = malloc(data->ioc_len); + } + if (!*pbuf) + return 1; + overlay = (struct obd_ioctl_data *)*pbuf; + memcpy(*pbuf, data, sizeof(*data)); + + ptr = overlay->ioc_bulk; + if (data->ioc_inlbuf1) + LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr); + if (data->ioc_inlbuf2) + LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr); + if (obd_ioctl_is_invalid(overlay)) + return 1; + + return 0; } #else @@ -524,57 +526,57 @@ static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, /* buffer MUST be at least the size of obd_ioctl_hdr */ static inline int obd_ioctl_getdata(char *buf, char *end, void *arg) { - struct obd_ioctl_hdr *hdr; - struct obd_ioctl_data *data; - int err; - ENTRY; - - hdr = (struct obd_ioctl_hdr *)buf; - data = (struct obd_ioctl_data *)buf; - - err = copy_from_user(buf, (void *)arg, sizeof(*hdr)); - if ( err ) { - EXIT; - return err; - } - - if (hdr->ioc_version != OBD_IOCTL_VERSION) { - printk("OBD: version mismatch kernel vs application\n"); - return -EINVAL; - } - - if (hdr->ioc_len + buf >= end) { - printk("OBD: user buffer exceeds kernel buffer\n"); - return -EINVAL; - } - - - if (hdr->ioc_len < sizeof(struct obd_ioctl_data)) { - printk("OBD: user buffer too small for ioctl\n"); - return -EINVAL; - } - - err = copy_from_user(buf, (void *)arg, hdr->ioc_len); - if ( err ) { - EXIT; - return err; - } - - if (obd_ioctl_is_invalid(data)) { - printk("OBD: ioctl not correctly formatted\n"); - return -EINVAL; - } - - if (data->ioc_inllen1) { - data->ioc_inlbuf1 = &data->ioc_bulk[0]; - } - - if (data->ioc_inllen2) { - data->ioc_inlbuf2 = &data->ioc_bulk[0] + size_round(data->ioc_inllen1); - } - - EXIT; - return 0; + struct obd_ioctl_hdr *hdr; + struct obd_ioctl_data *data; + int err; + ENTRY; + + hdr = (struct obd_ioctl_hdr *)buf; + data = (struct obd_ioctl_data *)buf; + + err = copy_from_user(buf, (void *)arg, sizeof(*hdr)); + if ( err ) { + EXIT; + return err; + } + + if (hdr->ioc_version != OBD_IOCTL_VERSION) { + printk("OBD: version mismatch kernel vs application\n"); + return -EINVAL; + } + + if (hdr->ioc_len + buf >= end) { + printk("OBD: user buffer exceeds kernel buffer\n"); + return -EINVAL; + } + + + if (hdr->ioc_len < sizeof(struct obd_ioctl_data)) { + printk("OBD: user buffer too small for ioctl\n"); + return -EINVAL; + } + + err = copy_from_user(buf, (void *)arg, hdr->ioc_len); + if ( err ) { + EXIT; + return err; + } + + if (obd_ioctl_is_invalid(data)) { + printk("OBD: ioctl not correctly formatted\n"); + return -EINVAL; + } + + if (data->ioc_inllen1) { + data->ioc_inlbuf1 = &data->ioc_bulk[0]; + } + + if (data->ioc_inllen2) { + data->ioc_inlbuf2 = &data->ioc_bulk[0] + size_round(data->ioc_inllen1); + } + + EXIT; + return 0; } #endif diff --git a/lustre/include/linux/lustre_mds.h b/lustre/include/linux/lustre_mds.h index 79ae98c..ac98f7a 100644 --- a/lustre/include/linux/lustre_mds.h +++ b/lustre/include/linux/lustre_mds.h @@ -71,7 +71,7 @@ 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, const char *name, int namelen, __u32 mode, __u64 id, __u32 uid, __u32 gid, __u64 time, const char *tgt, int tgtlen); -void mds_unlink_pack(struct mds_rec_unlink *rec, struct inode *inode, const char *name, int namelen); +void mds_unlink_pack(struct mds_rec_unlink *rec, struct inode *inode, struct inode *child, const char *name, int namelen); void mds_link_pack(struct mds_rec_link *rec, struct inode *inode, struct inode *dir, const char *name, int namelen); void mds_rename_pack(struct mds_rec_rename *rec, struct inode *srcdir, struct inode *tgtdir, const char *name, int namelen, const char *tgt, int tgtlen); @@ -80,7 +80,7 @@ struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid, struct vf /* llight/request.c */ int mdc_getattr(struct ptlrpc_client *peer, ino_t ino, int type, int valid, - struct ptlrpc_request **); + struct ptlrpc_request **); int mdc_setattr(struct ptlrpc_client *peer, struct inode *inode, struct iattr *iattr, struct ptlrpc_request **); int mdc_open(struct ptlrpc_client *cl, ino_t ino, int type, int flags, @@ -90,19 +90,19 @@ int mdc_close(struct ptlrpc_client *cl, ino_t ino, int type, __u64 fh, int mdc_readpage(struct ptlrpc_client *peer, ino_t ino, int type, __u64 offset, char *addr, struct ptlrpc_request **); int mdc_create(struct ptlrpc_client *peer, - struct inode *dir, const char *name, int namelen, - const char *tgt, int tgtlen, - int mode, __u64 id, __u32 uid, __u32 gid, __u64 time, + struct inode *dir, const char *name, int namelen, + const char *tgt, int tgtlen, + int mode, __u64 id, __u32 uid, __u32 gid, __u64 time, struct ptlrpc_request **); -int mdc_unlink(struct ptlrpc_client *peer, - struct inode *dir, const char *name, int namelen, +int mdc_unlink(struct ptlrpc_client *peer, struct inode *dir, + struct inode *child, const char *name, int namelen, struct ptlrpc_request **); int mdc_link(struct ptlrpc_client *peer, struct dentry *src, - struct inode *dir, const char *name, int namelen, + struct inode *dir, const char *name, int namelen, struct ptlrpc_request **); int mdc_rename(struct ptlrpc_client *peer, struct inode *src, - struct inode *tgt, const char *old, int oldlen, - const char *new, int newlen, + struct inode *tgt, const char *old, int oldlen, + const char *new, int newlen, struct ptlrpc_request **); int mdc_create_client(char *uuid, struct ptlrpc_client *cl); @@ -110,10 +110,10 @@ int mdc_create_client(char *uuid, struct ptlrpc_client *cl); #define IOC_REQUEST_TYPE 'f' #define IOC_REQUEST_MIN_NR 30 -#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) +#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) #define IOC_REQUEST_MAX_NR 33 #endif diff --git a/lustre/lib/mds_updates.c b/lustre/lib/mds_updates.c index 645679c..80397f6 100644 --- a/lustre/lib/mds_updates.c +++ b/lustre/lib/mds_updates.c @@ -34,91 +34,95 @@ #include /* packing of MDS records */ -void mds_create_pack(struct mds_rec_create *rec, struct inode *inode, const char *name, int namelen, __u32 mode, __u64 id, __u32 uid, __u32 gid, __u64 time, const char *tgt, int tgtlen) +void mds_create_pack(struct mds_rec_create *rec, struct inode *inode, + const char *name, int namelen, __u32 mode, __u64 id, + __u32 uid, __u32 gid, __u64 time, const char *tgt, + int tgtlen) { - char *tmp = (char *)rec + sizeof(*rec); - /* XXX do something about time, uid, gid */ - rec->cr_reclen = - HTON__u32(sizeof(*rec) + size_round0(namelen) + - size_round0(tgtlen)); - 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 = HTON__u32(namelen + 1); /* for terminating \0 */ - LOGL0(name, namelen, tmp); - if (tgt) { - rec->cr_tgtlen = HTON__u32(tgtlen + 1); - LOGL0(tgt, tgtlen, tmp); - } + char *tmp = (char *)rec + sizeof(*rec); + /* XXX do something about time, uid, gid */ + rec->cr_reclen = + HTON__u32(sizeof(*rec) + size_round0(namelen) + + size_round0(tgtlen)); + 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 = HTON__u32(namelen + 1); /* for terminating \0 */ + LOGL0(name, namelen, tmp); + if (tgt) { + rec->cr_tgtlen = HTON__u32(tgtlen + 1); + LOGL0(tgt, tgtlen, tmp); + } } void mds_setattr_pack(struct mds_rec_setattr *rec, struct inode *inode, struct iattr *iattr) { - 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); - rec->sa_uid = HTON__u32(iattr->ia_uid); - rec->sa_gid = HTON__u32(iattr->ia_gid); - rec->sa_size = HTON__u64(iattr->ia_size); - rec->sa_atime = HTON__u64(iattr->ia_atime); - rec->sa_mtime = HTON__u64(iattr->ia_mtime); - rec->sa_ctime = HTON__u64(iattr->ia_ctime); - rec->sa_attr_flags = HTON__u32(iattr->ia_attr_flags); + 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); + rec->sa_uid = HTON__u32(iattr->ia_uid); + rec->sa_gid = HTON__u32(iattr->ia_gid); + rec->sa_size = HTON__u64(iattr->ia_size); + rec->sa_atime = HTON__u64(iattr->ia_atime); + rec->sa_mtime = HTON__u64(iattr->ia_mtime); + rec->sa_ctime = HTON__u64(iattr->ia_ctime); + rec->sa_attr_flags = HTON__u32(iattr->ia_attr_flags); } -void mds_unlink_pack(struct mds_rec_unlink *rec, - struct inode *inode, const char *name, int namelen) +void mds_unlink_pack(struct mds_rec_unlink *rec, struct inode *inode, + struct inode *child, const char *name, int namelen) { - char *tmp = (char *)rec + sizeof(*rec); + char *tmp = (char *)rec + sizeof(*rec); - rec->ul_reclen = HTON__u32(sizeof(*rec)) + size_round0(namelen); - rec->ul_opcode = HTON__u32(REINT_UNLINK); + rec->ul_reclen = HTON__u32(sizeof(*rec)) + size_round0(namelen); + rec->ul_opcode = HTON__u32(REINT_UNLINK); - ll_inode2fid(&rec->ul_fid1, inode); - rec->ul_namelen = HTON__u32(namelen + 1); /* for terminating \0 */ - LOGL0(name, namelen, tmp); + ll_inode2fid(&rec->ul_fid1, inode); + ll_inode2fid(&rec->ul_fid2, child); + rec->ul_namelen = HTON__u32(namelen + 1); /* for terminating \0 */ + LOGL0(name, namelen, tmp); } void mds_link_pack(struct mds_rec_link *rec, - struct inode *inode, struct inode *dir, - const char *name, int namelen) + struct inode *inode, struct inode *dir, + const char *name, int namelen) { - char *tmp = (char *)rec + sizeof(*rec); - rec->lk_reclen = HTON__u32(sizeof(*rec)) + size_round0(namelen); - rec->lk_opcode = HTON__u32(REINT_LINK); - - ll_inode2fid(&rec->lk_fid1, inode); - ll_inode2fid(&rec->lk_fid2, dir); - rec->lk_namelen = HTON__u32(namelen + 1); /* for terminating \0 */ - LOGL0(name, namelen, tmp); + char *tmp = (char *)rec + sizeof(*rec); + rec->lk_reclen = HTON__u32(sizeof(*rec)) + size_round0(namelen); + rec->lk_opcode = HTON__u32(REINT_LINK); + + ll_inode2fid(&rec->lk_fid1, inode); + ll_inode2fid(&rec->lk_fid2, dir); + rec->lk_namelen = HTON__u32(namelen + 1); /* for terminating \0 */ + LOGL0(name, namelen, tmp); } void mds_rename_pack(struct mds_rec_rename *rec, struct inode *srcdir, struct inode *tgtdir, const char *name, int namelen, const char *tgt, int tgtlen) { - char *tmp = (char *)rec + sizeof(*rec); - /* XXX do something about time, uid, gid */ - rec->rn_reclen = - HTON__u32(sizeof(*rec) + size_round0(namelen) + - size_round0(tgtlen)); - rec->rn_opcode = HTON__u32(REINT_RENAME); - - ll_inode2fid(&rec->rn_fid1, srcdir); - ll_inode2fid(&rec->rn_fid2, tgtdir); - rec->rn_namelen = HTON__u32(namelen + 1); /* for terminating \0 */ - LOGL0(name, namelen, tmp); - if (tgt) { - rec->rn_tgtlen = HTON__u32(tgtlen + 1); - LOGL0(tgt, tgtlen, tmp); - } + char *tmp = (char *)rec + sizeof(*rec); + /* XXX do something about time, uid, gid */ + rec->rn_reclen = + HTON__u32(sizeof(*rec) + size_round0(namelen) + + size_round0(tgtlen)); + rec->rn_opcode = HTON__u32(REINT_RENAME); + + ll_inode2fid(&rec->rn_fid1, srcdir); + ll_inode2fid(&rec->rn_fid2, tgtdir); + rec->rn_namelen = HTON__u32(namelen + 1); /* for terminating \0 */ + LOGL0(name, namelen, tmp); + if (tgt) { + rec->rn_tgtlen = HTON__u32(tgtlen + 1); + LOGL0(tgt, tgtlen, tmp); + } } /* unpacking */ @@ -126,137 +130,137 @@ void mds_rename_pack(struct mds_rec_rename *rec, struct inode *srcdir, struct in 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) { - CERROR("invalid buffer length\n"); - return -EFAULT; - } - r->ur_opcode = NTOH__u32(hdr->ur_opcode); - return 0; + 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) { + CERROR("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)) { - CERROR("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); - attr->ia_gid = NTOH__u32(rec->sa_gid); - attr->ia_size = NTOH__u64(rec->sa_size); - attr->ia_atime = NTOH__u64(rec->sa_atime); - 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; + struct iattr *attr = &r->ur_iattr; + struct mds_rec_setattr *rec = (struct mds_rec_setattr *)buf; + + if (len < sizeof(*rec)) { + CERROR("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); + attr->ia_gid = NTOH__u32(rec->sa_gid); + attr->ia_size = NTOH__u64(rec->sa_size); + attr->ia_atime = NTOH__u64(rec->sa_atime); + 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)) { - CERROR("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__u32(rec->cr_namelen); - r->ur_tgtlen = NTOH__u32(rec->cr_tgtlen); - - UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); - UNLOGL0(r->ur_tgt, char, r->ur_tgtlen, ptr, end); - return 0; + struct mds_rec_create *rec = (struct mds_rec_create *)buf; + char *ptr, *end; + + if (len < sizeof(*rec)) { + CERROR("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__u32(rec->cr_namelen); + r->ur_tgtlen = NTOH__u32(rec->cr_tgtlen); + + UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); + UNLOGL0(r->ur_tgt, char, r->ur_tgtlen, ptr, end); + return 0; } static int mds_link_unpack(char *buf, int len, struct mds_update_record *r) { - struct mds_rec_link *rec = (struct mds_rec_link *)buf; - char *ptr, *end; - - if (len < sizeof(*rec)) { - CERROR("invalid buffer length\n"); - return -EFAULT; - } - - ptr = (char *)rec + sizeof(*rec); - end = ptr + len - sizeof(*rec); - - r->ur_fid1 = &rec->lk_fid1; - r->ur_fid2 = &rec->lk_fid2; - r->ur_namelen = NTOH__u32(rec->lk_namelen); - UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); - return 0; + struct mds_rec_link *rec = (struct mds_rec_link *)buf; + char *ptr, *end; + + if (len < sizeof(*rec)) { + CERROR("invalid buffer length\n"); + return -EFAULT; + } + + ptr = (char *)rec + sizeof(*rec); + end = ptr + len - sizeof(*rec); + + r->ur_fid1 = &rec->lk_fid1; + r->ur_fid2 = &rec->lk_fid2; + r->ur_namelen = NTOH__u32(rec->lk_namelen); + UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); + return 0; } - static int mds_unlink_unpack(char *buf, int len, struct mds_update_record *r) { - struct mds_rec_unlink *rec = (struct mds_rec_unlink *)buf; - char *ptr, *end; - ENTRY; - - if (len < sizeof(*rec)) { - CERROR("invalid buffer length\n"); - return -EFAULT; - } - - ptr = (char *)rec + sizeof(*rec); - end = ptr + len - sizeof(*rec); - - r->ur_fid1 = &rec->ul_fid1; - r->ur_namelen = NTOH__u32(rec->ul_namelen); - UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); - EXIT; - return 0; + struct mds_rec_unlink *rec = (struct mds_rec_unlink *)buf; + char *ptr, *end; + ENTRY; + + if (len < sizeof(*rec)) { + CERROR("invalid buffer length\n"); + return -EFAULT; + } + + ptr = (char *)rec + sizeof(*rec); + end = ptr + len - sizeof(*rec); + + r->ur_fid1 = &rec->ul_fid1; + r->ur_fid2 = &rec->ul_fid2; + r->ur_namelen = NTOH__u32(rec->ul_namelen); + UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); + EXIT; + return 0; } static int mds_rename_unpack(char *buf, int len, struct mds_update_record *r) { - struct mds_rec_rename *rec = (struct mds_rec_rename *)buf; - char *ptr, *end; - - if (len < sizeof(*rec)) { - CERROR("invalid buffer length\n"); - return -EFAULT; - } - - ptr = (char *)rec + sizeof(*rec); - end = ptr + len - sizeof(*rec); - - r->ur_fid1 = &rec->rn_fid1; - r->ur_fid2 = &rec->rn_fid2; - r->ur_namelen = NTOH__u32(rec->rn_namelen); - r->ur_tgtlen = NTOH__u32(rec->rn_tgtlen); - - UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); - UNLOGL0(r->ur_tgt, char, r->ur_tgtlen, ptr, end); - return 0; + struct mds_rec_rename *rec = (struct mds_rec_rename *)buf; + char *ptr, *end; + + if (len < sizeof(*rec)) { + CERROR("invalid buffer length\n"); + return -EFAULT; + } + + ptr = (char *)rec + sizeof(*rec); + end = ptr + len - sizeof(*rec); + + r->ur_fid1 = &rec->rn_fid1; + r->ur_fid2 = &rec->rn_fid2; + r->ur_namelen = NTOH__u32(rec->rn_namelen); + r->ur_tgtlen = NTOH__u32(rec->rn_tgtlen); + + UNLOGL0(r->ur_name, char, r->ur_namelen, ptr, end); + UNLOGL0(r->ur_tgt, char, r->ur_tgtlen, 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_SETATTR] mds_setattr_unpack, [REINT_CREATE] mds_create_unpack, [REINT_LINK] mds_link_unpack, [REINT_UNLINK] mds_unlink_unpack, @@ -265,22 +269,22 @@ static update_unpacker mds_unpackers[REINT_MAX + 1] = { 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; + 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/llite/namei.c b/lustre/llite/namei.c index 461fb67..f7b9462 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -183,7 +183,8 @@ static struct inode *ll_create_node(struct inode *dir, const char *name, return inode; } /* ll_new_inode */ -int ll_mdc_unlink(struct inode *dir, const char *name, int len) +int ll_mdc_unlink(struct inode *dir, struct inode *child, + const char *name, int len) { struct ptlrpc_request *request; int err; @@ -191,7 +192,7 @@ int ll_mdc_unlink(struct inode *dir, const char *name, int len) ENTRY; - err = mdc_unlink(&sbi->ll_mds_client, dir, name, len, &request); + err = mdc_unlink(&sbi->ll_mds_client, dir, child, name, len, &request); ptlrpc_free_req(request); EXIT; @@ -406,7 +407,8 @@ static int ll_unlink(struct inode * dir, struct dentry *dentry) if (!de) goto out; - err = ll_mdc_unlink(dir, dentry->d_name.name, dentry->d_name.len); + err = ll_mdc_unlink(dir, dentry->d_inode, + dentry->d_name.name, dentry->d_name.len); if (err) goto out; diff --git a/lustre/mdc/mdc_reint.c b/lustre/mdc/mdc_reint.c index 181b8fa..2bfdbb8 100644 --- a/lustre/mdc/mdc_reint.c +++ b/lustre/mdc/mdc_reint.c @@ -33,151 +33,151 @@ static int mdc_reint(struct ptlrpc_client *cl, struct ptlrpc_request *request) { - int rc; + int rc; - rc = ptlrpc_queue_wait(cl, request); + rc = ptlrpc_queue_wait(cl, request); if (rc) - CERROR("error in handling %d\n", rc); + CERROR("error in handling %d\n", rc); - return rc; + return rc; } int mdc_setattr(struct ptlrpc_client *peer, - struct inode *inode, struct iattr *iattr, - struct ptlrpc_request **request) + struct inode *inode, struct iattr *iattr, + struct ptlrpc_request **request) { - int rc; - struct mds_rec_setattr *rec; + int rc; + struct mds_rec_setattr *rec; ENTRY; *request = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, sizeof(*rec), NULL); - if (!(*request)) { - CERROR("cannot pack\n"); + if (!(*request)) { + CERROR("cannot pack\n"); EXIT; - return -ENOMEM; - } + return -ENOMEM; + } - rec = mds_req_tgt((*request)->rq_req.mds); - mds_setattr_pack(rec, inode, iattr); - (*request)->rq_req.mds->opcode = HTON__u32(REINT_SETATTR); - (*request)->rq_replen = - sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); + rec = mds_req_tgt((*request)->rq_req.mds); + mds_setattr_pack(rec, inode, iattr); + (*request)->rq_req.mds->opcode = HTON__u32(REINT_SETATTR); + (*request)->rq_replen = + sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); - rc = mdc_reint(peer, *request); + rc = mdc_reint(peer, *request); EXIT; return rc; } int mdc_create(struct ptlrpc_client *peer, - struct inode *dir, const char *name, int namelen, - const char *tgt, int tgtlen, - int mode, __u64 id, __u32 uid, __u32 gid, __u64 time, + struct inode *dir, const char *name, int namelen, + const char *tgt, int tgtlen, + int mode, __u64 id, __u32 uid, __u32 gid, __u64 time, struct ptlrpc_request **request) { - int rc; - struct mds_rec_create *rec; + int rc; + struct mds_rec_create *rec; ENTRY; - (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, - sizeof(*rec) + size_round0(namelen) + - size_round0(tgtlen), NULL); - if (!(*request)) { - CERROR("cannot pack\n"); - return -ENOMEM; - } + (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, + sizeof(*rec) + size_round0(namelen) + + size_round0(tgtlen), NULL); + if (!(*request)) { + CERROR("cannot pack\n"); + return -ENOMEM; + } - (*request)->rq_replen = - sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); + (*request)->rq_replen = + sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); - rec = mds_req_tgt((*request)->rq_req.mds); - mds_create_pack(rec, dir, name, namelen, mode, id, uid, gid, time, - tgt, tgtlen); + rec = mds_req_tgt((*request)->rq_req.mds); + mds_create_pack(rec, dir, name, namelen, mode, id, uid, gid, time, + tgt, tgtlen); - rc = mdc_reint(peer, (*request)); + rc = mdc_reint(peer, (*request)); EXIT; - return rc; + return rc; } -int mdc_unlink(struct ptlrpc_client *peer, - struct inode *dir, const char *name, int namelen, +int mdc_unlink(struct ptlrpc_client *peer, struct inode *dir, + struct inode *child, const char *name, int namelen, struct ptlrpc_request **request) { - int rc; - struct mds_rec_unlink *rec; + int rc; + struct mds_rec_unlink *rec; - (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, - sizeof(*rec) + size_round0(namelen), NULL); - if (!(*request)) { - CERROR("cannot pack\n"); - return -ENOMEM; - } + (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, + sizeof(*rec) + size_round0(namelen), NULL); + if (!(*request)) { + CERROR("cannot pack\n"); + return -ENOMEM; + } - (*request)->rq_replen = - sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); + (*request)->rq_replen = + sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); - rec = mds_req_tgt((*request)->rq_req.mds); - mds_unlink_pack(rec, dir, name, namelen); + rec = mds_req_tgt((*request)->rq_req.mds); + mds_unlink_pack(rec, dir, child, name, namelen); - rc = mdc_reint(peer, (*request)); + rc = mdc_reint(peer, (*request)); EXIT; - return rc; + return rc; } int mdc_link(struct ptlrpc_client *peer, struct dentry *src, - struct inode *dir, const char *name, int namelen, + struct inode *dir, const char *name, int namelen, struct ptlrpc_request **request) { - int rc; - struct mds_rec_link *rec; + int rc; + struct mds_rec_link *rec; ENTRY; - (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, - sizeof(*rec) + size_round0(namelen), NULL); - if (!(*request)) { - CERROR("cannot pack\n"); - return -ENOMEM; - } + (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, + sizeof(*rec) + size_round0(namelen), NULL); + if (!(*request)) { + CERROR("cannot pack\n"); + return -ENOMEM; + } - (*request)->rq_replen = - sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); + (*request)->rq_replen = + sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); - rec = mds_req_tgt((*request)->rq_req.mds); - mds_link_pack(rec, src->d_inode, dir, name, namelen); + rec = mds_req_tgt((*request)->rq_req.mds); + mds_link_pack(rec, src->d_inode, dir, name, namelen); - rc = mdc_reint(peer, (*request)); + rc = mdc_reint(peer, (*request)); EXIT; - return rc; + return rc; } int mdc_rename(struct ptlrpc_client *peer, struct inode *src, - struct inode *tgt, const char *old, int oldlen, - const char *new, int newlen, + struct inode *tgt, const char *old, int oldlen, + const char *new, int newlen, struct ptlrpc_request **request) { - int rc; - struct mds_rec_rename *rec; + int rc; + struct mds_rec_rename *rec; ENTRY; - (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, - sizeof(*rec) + size_round0(oldlen) - + size_round0(newlen), NULL); - if (!(*request)) { - CERROR("cannot pack\n"); - return -ENOMEM; - } + (*request) = ptlrpc_prep_req(peer, MDS_REINT, 0, NULL, + sizeof(*rec) + size_round0(oldlen) + + size_round0(newlen), NULL); + if (!(*request)) { + CERROR("cannot pack\n"); + return -ENOMEM; + } - (*request)->rq_replen = - sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); + (*request)->rq_replen = + sizeof(struct ptlrep_hdr) + sizeof(struct mds_rep); - rec = mds_req_tgt((*request)->rq_req.mds); - mds_rename_pack(rec, src, tgt, old, oldlen, new, newlen); + rec = mds_req_tgt((*request)->rq_req.mds); + mds_rename_pack(rec, src, tgt, old, oldlen, new, newlen); - rc = mdc_reint(peer, (*request)); + rc = mdc_reint(peer, (*request)); EXIT; - return rc; + return rc; } diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 87c48b9..1fa95aa 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -153,8 +153,7 @@ struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid, /* stolen from NFS */ struct super_block *sb = mds->mds_sb; unsigned long ino = fid->id; - //__u32 generation = fid->generation; - __u32 generation = 0; + __u32 generation = fid->generation; struct inode *inode; struct list_head *lp; struct dentry *result; @@ -243,6 +242,7 @@ int mds_getattr(struct ptlrpc_request *req) inode = de->d_inode; rep->ino = inode->i_ino; + rep->generation = inode->i_generation; rep->atime = inode->i_atime; rep->ctime = inode->i_ctime; rep->mtime = inode->i_mtime; diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 2aa4c39..fad45cd 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -209,6 +209,11 @@ static int mds_reint_unlink(struct mds_update_record *rec, GOTO(out_unlink, (rc = -ESTALE)); } + if (dchild->d_inode->i_ino != rec->ur_fid2->id) + LBUG(); + if (dchild->d_inode->i_generation != rec->ur_fid2->generation) + LBUG(); + OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_UNLINK_WRITE); switch (dchild->d_inode->i_mode & S_IFMT) {