From 80ea65839c878f18b1471d89f4db0b6ba0450813 Mon Sep 17 00:00:00 2001 From: pravins Date: Sun, 8 Feb 2009 16:56:20 +0000 Subject: [PATCH] b=15134 i=adilger i=yury.umanets add file-type attribute to lu_dirent. --- libcfs/include/libcfs/linux/linux-fs.h | 2 + libcfs/include/libcfs/posix/libcfs.h | 1 + lustre/include/lclient.h | 2 + lustre/include/lu_object.h | 16 +++- lustre/include/lustre/lustre_idl.h | 71 ++++++++++++++- lustre/lclient/lcommon_cl.c | 22 +++++ lustre/liblustre/dir.c | 7 +- lustre/llite/dir.c | 7 +- lustre/mdc/mdc_lib.c | 2 + lustre/mdd/mdd_object.c | 161 ++++++++++++++++++++++++--------- lustre/mdt/mdt_handler.c | 2 + 11 files changed, 237 insertions(+), 56 deletions(-) diff --git a/libcfs/include/libcfs/linux/linux-fs.h b/libcfs/include/libcfs/linux/linux-fs.h index 4933a1b..903001e 100644 --- a/libcfs/include/libcfs/linux/linux-fs.h +++ b/libcfs/include/libcfs/linux/linux-fs.h @@ -85,4 +85,6 @@ typedef struct file_lock cfs_flock_t; ssize_t cfs_user_write (cfs_file_t *filp, const char *buf, size_t count, loff_t *offset); +#define CFS_IFTODT(type) (((type) & 0170000) >> 12) + #endif diff --git a/libcfs/include/libcfs/posix/libcfs.h b/libcfs/include/libcfs/posix/libcfs.h index 909deef..9d5970a 100644 --- a/libcfs/include/libcfs/posix/libcfs.h +++ b/libcfs/include/libcfs/posix/libcfs.h @@ -411,4 +411,5 @@ static inline void radix_tree_preload_end(void) typedef ssize_t (*read_actor_t)(); +#define CFS_IFTODT(type) (((type) & 0170000) >> 12) #endif diff --git a/lustre/include/lclient.h b/lustre/include/lclient.h index 2c88beb..974a03f 100644 --- a/lustre/include/lclient.h +++ b/lustre/include/lclient.h @@ -358,6 +358,8 @@ int cl_inode_init(struct inode *inode, struct lustre_md *md); void cl_inode_fini(struct inode *inode); int cl_local_size(struct inode *inode); +__u16 ll_dirent_type_get(struct lu_dirent *ent); + #ifdef INVARIANT_CHECK # define CLOBINVRNT(env, clob, expr) \ do { \ diff --git a/lustre/include/lu_object.h b/lustre/include/lu_object.h index 54ef3df..73fe7af 100644 --- a/lustre/include/lu_object.h +++ b/lustre/include/lu_object.h @@ -905,12 +905,18 @@ static inline void lu_object_ref_del_at(struct lu_object *o, lu_ref_del_at(&o->lo_header->loh_reference, link, scope, source); } +/** input params, should be filled out by mdt */ struct lu_rdpg { - /* input params, should be filled out by mdt */ - __u64 rp_hash; /* hash */ - int rp_count; /* count in bytes */ - int rp_npages; /* number of pages */ - struct page **rp_pages; /* pointers to pages */ + /** hash */ + __u64 rp_hash; + /** count in bytes */ + unsigned int rp_count; + /** number of pages */ + unsigned int rp_npages; + /** requested attr */ + __u32 rp_attrs; + /** pointers to pages */ + struct page **rp_pages; }; enum lu_xattr_flags { diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index 76327b2..9f5190a 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -490,18 +490,69 @@ static inline int lu_fid_cmp(const struct lu_fid *f0, /** \defgroup lu_dir lu_dir * @{ */ + +/** + * Enumeration of possible directory entry attributes. + * + * Attributes follow directory entry header in the order they appear in this + * enumeration. + */ +enum lu_dirent_attrs { + LUDA_FID = 0x0001, + LUDA_TYPE = 0x0002, +}; + /** * Layout of readdir pages, as transmitted on wire. */ struct lu_dirent { + /** valid if LUDA_FID is set. */ struct lu_fid lde_fid; + /** a unique entry identifier: a hash or an offset. */ __u64 lde_hash; + /** total record length, including all attributes. */ __u16 lde_reclen; + /** name length */ __u16 lde_namelen; - __u32 lde_pad0; + /** optional variable size attributes following this entry. + * taken from enum lu_dirent_attrs. + */ + __u32 lde_attrs; + /** name is followed by the attributes indicated in ->ldp_attrs, in + * their natural order. After the last attribute, padding bytes are + * added to make ->lde_reclen a multiple of 8. + */ char lde_name[0]; }; +/* + * Definitions of optional directory entry attributes formats. + * + * Individual attributes do not have their length encoded in a generic way. It + * is assumed that consumer of an attribute knows its format. This means that + * it is impossible to skip over an unknown attribute, except by skipping over all + * remaining attributes (by using ->lde_reclen), which is not too + * constraining, because new server versions will append new attributes at + * the end of an entry. + */ + +/** + * Fid directory attribute: a fid of an object referenced by the entry. This + * will be almost always requested by the client and supplied by the server. + * + * Aligned to 8 bytes. + */ +/* To have compatibility with 1.8, lets have fid in lu_dirent struct. */ + +/** + * File type. + * + * Aligned to 2 bytes. + */ +struct luda_type { + __u16 lt_type; +}; + struct lu_dirpage { __u64 ldp_hash_start; __u64 ldp_hash_end; @@ -534,11 +585,25 @@ static inline struct lu_dirent *lu_dirent_next(struct lu_dirent *ent) return next; } +static inline int lu_dirent_calc_size(int namelen, __u16 attr) +{ + int size; + + if (attr & LUDA_TYPE) { + const unsigned align = sizeof(struct luda_type) - 1; + size = (sizeof(struct lu_dirent) + namelen + align) & ~align; + size += sizeof(struct luda_type); + } else + size = sizeof(struct lu_dirent) + namelen; + + return (size + 7) & ~7; +} + static inline int lu_dirent_size(struct lu_dirent *ent) { if (le16_to_cpu(ent->lde_reclen) == 0) { - return (sizeof(*ent) + - le16_to_cpu(ent->lde_namelen) + 7) & ~7; + return lu_dirent_calc_size(le16_to_cpu(ent->lde_namelen), + le32_to_cpu(ent->lde_attrs)); } return le16_to_cpu(ent->lde_reclen); } diff --git a/lustre/lclient/lcommon_cl.c b/lustre/lclient/lcommon_cl.c index d68ba37..c06573a 100644 --- a/lustre/lclient/lcommon_cl.c +++ b/lustre/lclient/lcommon_cl.c @@ -1186,3 +1186,25 @@ void cl_inode_fini(struct inode *inode) cl_env_reexit(cookie); } } + +/** + * return IF_* type for given lu_dirent entry. + * IF_* flag shld be converted to particular OS file type in + * platform llite module. + */ +__u16 ll_dirent_type_get(struct lu_dirent *ent) +{ + __u16 type = 0; + struct luda_type *lt; + int len = 0; + + if (le32_to_cpu(ent->lde_attrs) & LUDA_TYPE) { + const unsigned align = sizeof(struct luda_type) - 1; + + len = le16_to_cpu(ent->lde_namelen); + len = (len + align) & ~align; + lt = (void *) ent->lde_name + len; + type = CFS_IFTODT(le16_to_cpu(lt->lt_type)); + } + return type; +} diff --git a/lustre/liblustre/dir.c b/lustre/liblustre/dir.c index 8999ae6..7b0832e 100644 --- a/lustre/liblustre/dir.c +++ b/lustre/liblustre/dir.c @@ -211,6 +211,7 @@ ssize_t llu_iop_filldirentries(struct inode *dir, _SYSIO_OFF_T *basep, int rc; int done; int shift; + __u16 type; ENTRY; liblustre_wait_event(0); @@ -272,9 +273,9 @@ ssize_t llu_iop_filldirentries(struct inode *dir, _SYSIO_OFF_T *basep, name = ent->lde_name; fid_le_to_cpu(&fid, &fid); ino = llu_fid_build_ino(llu_i2sbi(dir), &fid); - + type = ll_dirent_type_get(ent); done = filldir(buf, nbytes, name, namelen, - (loff_t)hash, ino, DT_UNKNOWN, + (loff_t)hash, ino, type, &filled); } next = le64_to_cpu(dp->ldp_hash_end); @@ -309,7 +310,7 @@ ssize_t llu_iop_filldirentries(struct inode *dir, _SYSIO_OFF_T *basep, PFID(&lli->lli_fid), (unsigned long)pos, rc); } } - lli->lli_dir_pos = (loff_t)(__s32)pos; + lli->lli_dir_pos = (loff_t)pos; *basep = lli->lli_dir_pos; out: ll_dir_chain_fini(&chain); diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 8506022..f94d458 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -394,6 +394,7 @@ int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) int rc; int done; int shift; + __u16 type; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %lu/%llu\n", @@ -457,9 +458,9 @@ int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) name = ent->lde_name; fid_le_to_cpu(&fid, &fid); ino = ll_fid_build_ino(sbi, &fid); - + type = ll_dirent_type_get(ent); done = filldir(cookie, name, namelen, - (loff_t)hash, ino, DT_UNKNOWN); + (loff_t)hash, ino, type); } next = le64_to_cpu(dp->ldp_hash_end); ll_put_page(page); @@ -491,7 +492,7 @@ int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) } } - filp->f_pos = (loff_t)(__s32)pos; + filp->f_pos = (loff_t)pos; filp->f_version = inode->i_version; touch_atime(filp->f_vfsmnt, filp->f_dentry); diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index dc5aa09..7094b5a 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -122,6 +122,8 @@ void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, b->size = pgoff; /* !! */ b->nlink = size; /* !! */ __mdc_pack_body(b, -1); + b->mode = LUDA_FID | LUDA_TYPE; + mdc_pack_capa(req, &RMF_CAPA1, oc); } diff --git a/lustre/mdd/mdd_object.c b/lustre/mdd/mdd_object.c index 9d0dbc1..9846cb4 100644 --- a/lustre/mdd/mdd_object.c +++ b/lustre/mdd/mdd_object.c @@ -1919,16 +1919,80 @@ static int mdd_readpage_sanity_check(const struct lu_env *env, RETURN(rc); } -static int mdd_dir_page_build(const struct lu_env *env, int first, - void *area, int nob, const struct dt_it_ops *iops, - struct dt_it *it, __u64 *start, __u64 *end, - struct lu_dirent **last) +static int mdd_append_attrs(const struct lu_env *env, + struct mdd_device *mdd, + __u32 attr, + const struct dt_it_ops *iops, + struct dt_it *it, + struct lu_dirent*ent) +{ + struct mdd_thread_info *info = mdd_env_info(env); + struct lu_fid *fid = &info->mti_fid2; + int len = cpu_to_le16(ent->lde_namelen); + const unsigned align = sizeof(struct luda_type) - 1; + struct lu_fid_pack *pack; + struct mdd_object *obj; + struct luda_type *lt; + int rc = 0; + + if (attr & LUDA_FID) { + pack = (struct lu_fid_pack *)iops->rec(env, it); + if (IS_ERR(pack)) { + rc = PTR_ERR(pack); + ent->lde_attrs = 0; + goto out; + } + rc = fid_unpack(pack, fid); + if (rc != 0) { + ent->lde_attrs = 0; + goto out; + } + + fid_cpu_to_le(&ent->lde_fid, fid); + ent->lde_attrs = LUDA_FID; + } + + /* check if file type is required */ + if (attr & LUDA_TYPE) { + if (!(attr & LUDA_FID)) { + CERROR("wrong attr : [%x]\n",attr); + rc = -EINVAL; + goto out; + } + + obj = mdd_object_find(env, mdd, fid); + if (obj == NULL) /* remote object */ + goto out; + + if (IS_ERR(obj)) { + rc = PTR_ERR(obj); + goto out; + } + + if (mdd_object_exists(obj) == +1) { + len = (len + align) & ~align; + + lt = (void *) ent->lde_name + len; + lt->lt_type = cpu_to_le16(mdd_object_type(obj)); + + ent->lde_attrs |= LUDA_TYPE; + } + mdd_object_put(env, obj); + } +out: + ent->lde_attrs = cpu_to_le32(ent->lde_attrs); + return rc; +} + +static int mdd_dir_page_build(const struct lu_env *env, struct mdd_device *mdd, + int first, void *area, int nob, + const struct dt_it_ops *iops, struct dt_it *it, + __u64 *start, __u64 *end, + struct lu_dirent **last, __u32 attr) { - struct lu_fid *fid = &mdd_env_info(env)->mti_fid2; - struct mdd_thread_info *info = mdd_env_info(env); - struct lu_fid_pack *pack = &info->mti_pack; int result; struct lu_dirent *ent; + __u64 hash = 0; if (first) { memset(area, 0, sizeof (struct lu_dirpage)); @@ -1936,56 +2000,64 @@ static int mdd_dir_page_build(const struct lu_env *env, int first, nob -= sizeof (struct lu_dirpage); } - LASSERT(nob > sizeof *ent); - ent = area; - result = 0; do { char *name; int len; int recsize; - __u64 hash; - name = (char *)iops->key(env, it); len = iops->key_size(env, it); - pack = (struct lu_fid_pack *)iops->rec(env, it); - result = fid_unpack(pack, fid); - if (result != 0) - break; + /* IAM iterator can return record with zero len. */ + if (len == 0) + goto next; - recsize = (sizeof(*ent) + len + 7) & ~7; + name = (char *)iops->key(env, it); hash = iops->store(env, it); - *end = hash; - CDEBUG(D_INFO, "%p %p %d "DFID": "LPU64" (%d) \"%*.*s\"\n", - name, ent, nob, PFID(fid), hash, len, len, len, name); + if (unlikely(first)) { + first = 0; + *start = hash; + } + + recsize = lu_dirent_calc_size(len, attr); + + CDEBUG(D_INFO, "%p %p %d "LPU64" (%d) \"%*.*s\"\n", + name, ent, nob, hash, len, len, len, name); if (nob >= recsize) { - ent->lde_fid = *fid; - fid_cpu_to_le(&ent->lde_fid, &ent->lde_fid); - ent->lde_hash = hash; + ent->lde_hash = cpu_to_le64(hash); ent->lde_namelen = cpu_to_le16(len); ent->lde_reclen = cpu_to_le16(recsize); memcpy(ent->lde_name, name, len); - if (first && ent == area) - *start = hash; - *last = ent; - ent = (void *)ent + recsize; - nob -= recsize; - result = iops->next(env, it); + + result = mdd_append_attrs(env, mdd, attr, iops, it, ent); + if (result != 0) + goto out; } else { /* * record doesn't fit into page, enlarge previous one. */ - LASSERT(*last != NULL); - (*last)->lde_reclen = - cpu_to_le16(le16_to_cpu((*last)->lde_reclen) + - nob); - break; + if (*last) { + (*last)->lde_reclen = + cpu_to_le16(le16_to_cpu((*last)->lde_reclen) + + nob); + result = 0; + } else + result = -EINVAL; + + goto out; } + *last = ent; + ent = (void *)ent + recsize; + nob -= recsize; + +next: + result = iops->next(env, it); } while (result == 0); +out: + *end = hash; return result; } @@ -1997,6 +2069,7 @@ static int __mdd_readpage(const struct lu_env *env, struct mdd_object *obj, const struct dt_it_ops *iops; struct page *pg; struct lu_dirent *last = NULL; + struct mdd_device *mdd = mdo2mdd(&obj->mod_obj); int i; int rc; int nob; @@ -2046,11 +2119,14 @@ static int __mdd_readpage(const struct lu_env *env, struct mdd_object *obj, i++, nob -= CFS_PAGE_SIZE) { LASSERT(i < rdpg->rp_npages); pg = rdpg->rp_pages[i]; - rc = mdd_dir_page_build(env, !i, cfs_kmap(pg), + rc = mdd_dir_page_build(env, mdd, !i, cfs_kmap(pg), min_t(int, nob, CFS_PAGE_SIZE), iops, - it, &hash_start, &hash_end, &last); - if (rc != 0 || i == rdpg->rp_npages - 1) - last->lde_reclen = 0; + it, &hash_start, &hash_end, &last, + rdpg->rp_attrs); + if (rc != 0 || i == rdpg->rp_npages - 1) { + if (last) + last->lde_reclen = 0; + } cfs_kunmap(pg); } if (rc > 0) { @@ -2064,13 +2140,14 @@ static int __mdd_readpage(const struct lu_env *env, struct mdd_object *obj, struct lu_dirpage *dp; dp = cfs_kmap(rdpg->rp_pages[0]); - dp->ldp_hash_start = rdpg->rp_hash; - dp->ldp_hash_end = hash_end; + dp->ldp_hash_start = cpu_to_le64(rdpg->rp_hash); + dp->ldp_hash_end = cpu_to_le64(hash_end); if (i == 0) /* * No pages were processed, mark this. */ dp->ldp_flags |= LDF_EMPTY; + dp->ldp_flags = cpu_to_le32(dp->ldp_flags); cfs_kunmap(rdpg->rp_pages[0]); } @@ -2112,8 +2189,8 @@ static int mdd_readpage(const struct lu_env *env, struct md_object *obj, pg = rdpg->rp_pages[0]; dp = (struct lu_dirpage*)cfs_kmap(pg); memset(dp, 0 , sizeof(struct lu_dirpage)); - dp->ldp_hash_start = rdpg->rp_hash; - dp->ldp_hash_end = DIR_END_OFF; + dp->ldp_hash_start = cpu_to_le64(rdpg->rp_hash); + dp->ldp_hash_end = cpu_to_le64(DIR_END_OFF); dp->ldp_flags |= LDF_EMPTY; dp->ldp_flags = cpu_to_le32(dp->ldp_flags); cfs_kunmap(pg); diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index b46baaf..f95d6b4 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -1414,6 +1414,8 @@ static int mdt_readpage(struct mdt_thread_info *info) rdpg->rp_hash, reqbody->size); RETURN(-EFAULT); } + + rdpg->rp_attrs = reqbody->mode; rdpg->rp_count = reqbody->nlink; rdpg->rp_npages = (rdpg->rp_count + CFS_PAGE_SIZE - 1)>>CFS_PAGE_SHIFT; OBD_ALLOC(rdpg->rp_pages, rdpg->rp_npages * sizeof rdpg->rp_pages[0]); -- 1.8.3.1