Whamcloud - gitweb
b=15134
authorpravins <pravins>
Sun, 8 Feb 2009 16:56:20 +0000 (16:56 +0000)
committerpravins <pravins>
Sun, 8 Feb 2009 16:56:20 +0000 (16:56 +0000)
i=adilger
i=yury.umanets
add file-type attribute to lu_dirent.

libcfs/include/libcfs/linux/linux-fs.h
libcfs/include/libcfs/posix/libcfs.h
lustre/include/lclient.h
lustre/include/lu_object.h
lustre/include/lustre/lustre_idl.h
lustre/lclient/lcommon_cl.c
lustre/liblustre/dir.c
lustre/llite/dir.c
lustre/mdc/mdc_lib.c
lustre/mdd/mdd_object.c
lustre/mdt/mdt_handler.c

index 4933a1b..903001e 100644 (file)
@@ -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
index 909deef..9d5970a 100644 (file)
@@ -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
index 2c88beb..974a03f 100644 (file)
@@ -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 {                                                                  \
index 54ef3df..73fe7af 100644 (file)
@@ -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 {
index 76327b2..9f5190a 100644 (file)
@@ -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);
 }
index d68ba37..c06573a 100644 (file)
@@ -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;
+}
index 8999ae6..7b0832e 100644 (file)
@@ -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);
index 8506022..f94d458 100644 (file)
@@ -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);
 
index dc5aa09..7094b5a 100644 (file)
@@ -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);
 }
 
index 9d0dbc1..9846cb4 100644 (file)
@@ -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);
index b46baaf..f95d6b4 100644 (file)
@@ -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]);