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