Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/fs/tmpfs change the way to handle directory "offsets" so...



details:   https://anonhg.NetBSD.org/src/rev/38c26d1430fe
branches:  trunk
changeset: 584400:38c26d1430fe
user:      yamt <yamt%NetBSD.org@localhost>
date:      Thu Sep 15 12:34:35 2005 +0000

description:
change the way to handle directory "offsets" so that
they won't be changed when removing entries in the directory.
some applications like cvs rely on this.

diffstat:

 sys/fs/tmpfs/tmpfs.h       |   16 +++++-
 sys/fs/tmpfs/tmpfs_subr.c  |  102 +++++++++++++++++++++++++-------------------
 sys/fs/tmpfs/tmpfs_vnops.c |   83 ++++++++++++++++++------------------
 3 files changed, 111 insertions(+), 90 deletions(-)

diffs (truncated from 395 to 300 lines):

diff -r 5eb3705de1d6 -r 38c26d1430fe sys/fs/tmpfs/tmpfs.h
--- a/sys/fs/tmpfs/tmpfs.h      Thu Sep 15 09:30:21 2005 +0000
+++ b/sys/fs/tmpfs/tmpfs.h      Thu Sep 15 12:34:35 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmpfs.h,v 1.3 2005/09/13 14:29:18 yamt Exp $   */
+/*     $NetBSD: tmpfs.h,v 1.4 2005/09/15 12:34:35 yamt Exp $   */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -68,6 +68,11 @@
 };
 TAILQ_HEAD(tmpfs_dir, tmpfs_dirent);
 
+#define        TMPFS_DIRCOOKIE(dirent) ((off_t)(uintptr_t)(dirent))
+#define        TMPFS_DIRCOOKIE_DOT     0
+#define        TMPFS_DIRCOOKIE_DOTDOT  1
+#define        TMPFS_DIRCOOKIE_EOF     2
+
 /* --------------------------------------------------------------------- */
 
 /*
@@ -116,7 +121,7 @@
                        struct tmpfs_dir        tn_dir;
 
                        /* Used by tmpfs_readdir to speed up lookups. */
-                       long                    tn_readdir_lastn;
+                       off_t                   tn_readdir_lastn;
                        struct tmpfs_dirent *   tn_readdir_lastp;
                };
 
@@ -193,7 +198,8 @@
                            struct componentname *cnp);
 int    tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *);
 int    tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *);
-int    tmpfs_dir_getdents(struct tmpfs_node *, struct uio *);
+struct tmpfs_dirent *  tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t);
+int    tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *);
 int    tmpfs_reg_resize(struct vnode *, off_t);
 size_t tmpfs_mem_info(boolean_t);
 int    tmpfs_chflags(struct vnode *, int, struct ucred *, struct proc *);
@@ -230,7 +236,9 @@
  */
 #define TMPFS_VALIDATE_DIR(node) \
     KASSERT((node)->tn_type == VDIR); \
-    KASSERT((node)->tn_size % sizeof(struct tmpfs_dirent) == 0);
+    KASSERT((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
+    KASSERT((node)->tn_readdir_lastp == NULL || \
+       TMPFS_DIRCOOKIE((node)->tn_readdir_lastp) == (node)->tn_readdir_lastn);
 
 /* --------------------------------------------------------------------- */
 
diff -r 5eb3705de1d6 -r 38c26d1430fe sys/fs/tmpfs/tmpfs_subr.c
--- a/sys/fs/tmpfs/tmpfs_subr.c Thu Sep 15 09:30:21 2005 +0000
+++ b/sys/fs/tmpfs/tmpfs_subr.c Thu Sep 15 12:34:35 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmpfs_subr.c,v 1.4 2005/09/13 14:29:18 yamt Exp $      */
+/*     $NetBSD: tmpfs_subr.c,v 1.5 2005/09/15 12:34:35 yamt Exp $      */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.4 2005/09/13 14:29:18 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.5 2005/09/15 12:34:35 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -483,8 +483,15 @@
 {
        struct tmpfs_node *dnode;
 
+       KASSERT(VOP_ISLOCKED(vp));
+
        dnode = VP_TO_TMPFS_DIR(vp);
 
+       if (dnode->tn_readdir_lastp == de) {
+               dnode->tn_readdir_lastn = 0;
+               dnode->tn_readdir_lastp = NULL;
+       }
+
        TAILQ_REMOVE(&dnode->tn_dir, de, td_entries);
        dnode->tn_size -= sizeof(struct tmpfs_dirent);
        dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
@@ -534,7 +541,7 @@
        struct dirent dent;
 
        TMPFS_VALIDATE_DIR(node);
-       KASSERT(uio->uio_offset == 0);
+       KASSERT(uio->uio_offset == TMPFS_DIRCOOKIE_DOT);
 
        dent.d_fileno = node->tn_id;
        dent.d_type = DT_DIR;
@@ -548,8 +555,7 @@
        else {
                error = uiomove(&dent, dent.d_reclen, uio);
                if (error == 0)
-                       uio->uio_offset += sizeof(struct tmpfs_dirent) - \
-                           dent.d_reclen;
+                       uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
        }
 
        node->tn_status |= TMPFS_NODE_ACCESSED;
@@ -571,7 +577,7 @@
        struct dirent dent;
 
        TMPFS_VALIDATE_DIR(node);
-       KASSERT(uio->uio_offset == sizeof(struct tmpfs_dirent));
+       KASSERT(uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT);
 
        dent.d_fileno = node->tn_id;
        dent.d_type = DT_DIR;
@@ -585,9 +591,15 @@
                error = -1;
        else {
                error = uiomove(&dent, dent.d_reclen, uio);
-               if (error == 0)
-                       uio->uio_offset += sizeof(struct tmpfs_dirent) - \
-                           dent.d_reclen;
+               if (error == 0) {
+                       struct tmpfs_dirent *de;
+
+                       de = TAILQ_FIRST(&node->tn_dir);
+                       if (de == NULL)
+                               uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
+                       else
+                               uio->uio_offset = TMPFS_DIRCOOKIE(de);
+               }
        }
 
        node->tn_status |= TMPFS_NODE_ACCESSED;
@@ -597,49 +609,56 @@
 
 /* --------------------------------------------------------------------- */
 
+/* lookup a directory entry by cookie */
+struct tmpfs_dirent *
+tmpfs_dir_lookupbycookie(struct tmpfs_node *node, off_t cookie)
+{
+       struct tmpfs_dirent *de;
+
+       if (cookie == node->tn_readdir_lastn &&
+           node->tn_readdir_lastp != NULL) {
+               return node->tn_readdir_lastp;
+       }
+
+       TAILQ_FOREACH(de, &node->tn_dir, td_entries) {
+               if (TMPFS_DIRCOOKIE(de) == cookie) {
+                       break;
+               }
+       }
+
+       return de;
+}
+
+/* --------------------------------------------------------------------- */
+
 /* Helper function for tmpfs_readdir.  Returns as much directory entries
  * as can fit in the uio space.  The read starts at uio->uio_offset.
  * The function returns 0 on success, -1 if there was not enough space
  * in the uio structure to hold the directory entry or an appropriate
  * error code if another error happens. */
 int
-tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio)
+tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp)
 {
        int error;
-       long cnt, startcnt;
+       off_t startcookie;
        struct tmpfs_dirent *de;
 
        TMPFS_VALIDATE_DIR(node);
-       KASSERT(uio->uio_offset % sizeof(struct tmpfs_dirent) == 0);
-       KASSERT(uio->uio_offset >= sizeof(struct tmpfs_dirent) * 2);
-       KASSERT(uio->uio_offset < node->tn_size +
-           sizeof(struct tmpfs_dirent) * 2);
 
        /* Locate the first directory entry we have to return.  We have cached
         * the last readdir in the node, so use those values if appropriate.
         * Otherwise do a linear scan to find the requested entry. */
-       de = NULL;
-       startcnt = uio->uio_offset / sizeof(struct tmpfs_dirent) - 2;
-       if (startcnt == node->tn_readdir_lastn && \
-           node->tn_readdir_lastp != NULL) {
-               cnt = node->tn_readdir_lastn;
-               de = node->tn_readdir_lastp;
+       startcookie = uio->uio_offset;
+       KASSERT(startcookie != TMPFS_DIRCOOKIE_DOT);
+       KASSERT(startcookie != TMPFS_DIRCOOKIE_DOTDOT);
+       if (startcookie == TMPFS_DIRCOOKIE_EOF) {
+               return 0;
        } else {
-               cnt = 0;
-               de = TAILQ_FIRST(&node->tn_dir);
-               while (cnt < startcnt) {
-                       cnt++;
-                       de = TAILQ_NEXT(de, td_entries);
-
-                       /* Ensure that if we have not found the desired item,
-                        * there are more entries in the directory to continue
-                        * the search. */
-                       KASSERT(IMPLIES(de == TAILQ_LAST(&node->tn_dir,
-                           tmpfs_dir), cnt == startcnt));
-               }
+               de = tmpfs_dir_lookupbycookie(node, startcookie);
        }
-       KASSERT(cnt == startcnt);
-       KASSERT(de != NULL);
+       if (de == NULL) {
+               return EINVAL;
+       }
 
        /* Read as much entries as possible; i.e., until we reach the end of
         * the directory or we exhaust uio space. */
@@ -698,22 +717,17 @@
                 * advance pointers. */
                error = uiomove(&d, d.d_reclen, uio);
 
-               cnt++;
+               (*cntp)++;
                de = TAILQ_NEXT(de, td_entries);
        } while (error == 0 && uio->uio_resid > 0 && de != NULL);
 
-       /* Update the offset in the uio structure to be correctly aligned
-        * with tmpfs_dirent structures.  Otherwise, the offset is the
-        * size of the returned dirent structures, which is useless for us. */
-       uio->uio_offset = (cnt + 2) * sizeof(struct tmpfs_dirent);
-
-       /* Cache the current status. */
+       /* Update the offset and cache. */
        if (de == NULL) {
-               KASSERT(cnt == node->tn_size / sizeof(struct tmpfs_dirent));
+               uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
                node->tn_readdir_lastn = 0;
                node->tn_readdir_lastp = NULL;
        } else {
-               node->tn_readdir_lastn = cnt;
+               node->tn_readdir_lastn = uio->uio_offset = TMPFS_DIRCOOKIE(de);
                node->tn_readdir_lastp = de;
        }
 
diff -r 5eb3705de1d6 -r 38c26d1430fe sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c        Thu Sep 15 09:30:21 2005 +0000
+++ b/sys/fs/tmpfs/tmpfs_vnops.c        Thu Sep 15 12:34:35 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmpfs_vnops.c,v 1.9 2005/09/14 20:27:26 yamt Exp $     */
+/*     $NetBSD: tmpfs_vnops.c,v 1.10 2005/09/15 12:34:35 yamt Exp $    */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.9 2005/09/14 20:27:26 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.10 2005/09/15 12:34:35 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -1040,11 +1040,6 @@
         * interested parties and clean it from the cache). */
        vput(vp);
 
-       /* As the directory has been modified, invalidate readdir cached
-        * values. */
-       dnode->tn_readdir_lastn = 0;
-       dnode->tn_readdir_lastp = NULL;
-
        error = 0;
 
 out:
@@ -1084,7 +1079,8 @@
        int *ncookies = ((struct vop_readdir_args *)v)->a_ncookies;
 
        int error;
-       off_t realsize, startoff;
+       off_t startoff;
+       off_t cnt;
        struct tmpfs_node *node;
 
        KASSERT(VOP_ISLOCKED(vp));
@@ -1096,75 +1092,78 @@
        }
 
        node = VP_TO_TMPFS_DIR(vp);
-       realsize = node->tn_size + sizeof(struct tmpfs_dirent) * 2;
-
-       /* The offset cannot extend past the end of the directory. */
-       if (uio->uio_offset >= realsize) {
-               error = EINVAL;
-               goto out;
-       }
-
-       /* The offset must be correctly aligned at the begining of
-        * tmpfs_dirent structures. */
-       if (uio->uio_offset % sizeof(struct tmpfs_dirent) > 0) {
-               error = EINVAL;
-               goto out;
-       }



Home | Main Index | Thread Index | Old Index