summaryrefslogtreecommitdiffstats
path: root/sys/fs/tmpfs
diff options
context:
space:
mode:
authorbdrewery <bdrewery@FreeBSD.org>2014-03-30 18:22:10 +0000
committerbdrewery <bdrewery@FreeBSD.org>2014-03-30 18:22:10 +0000
commit1416559ea41fb635f5aa0e2562a084996db8249e (patch)
tree12114cc2a6ed3a5c4d443df681126d7844baf02f /sys/fs/tmpfs
parent6dfd032c5729a991eebc2481cc29578b9588f23b (diff)
downloadFreeBSD-src-1416559ea41fb635f5aa0e2562a084996db8249e.zip
FreeBSD-src-1416559ea41fb635f5aa0e2562a084996db8249e.tar.gz
MFC r263131,r263174,r263175:
Tmpfs readdir() redundant logic and code readability cleanup. r263131: Cleanup redundant logic and add some comments to help explain how it works in lieu of potentially less clear code. r263174: Rename cnt to maxcookies and change its use as the condition for when to lookup cookies to be less obscure. r263175: Add missing FALLTHROUGH comment in tmpfs_dir_getdents for looking up '.' and '..'.
Diffstat (limited to 'sys/fs/tmpfs')
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c47
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c18
2 files changed, 38 insertions, 27 deletions
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index ec96936..f4508c6 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -348,6 +348,9 @@ tmpfs_dirent_hash(const char *name, u_int len)
static __inline off_t
tmpfs_dirent_cookie(struct tmpfs_dirent *de)
{
+ if (de == NULL)
+ return (TMPFS_DIRCOOKIE_EOF);
+
MPASS(de->td_cookie >= TMPFS_DIRCOOKIE_MIN);
return (de->td_cookie);
@@ -1144,7 +1147,7 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
* error code if another error happens.
*/
int
-tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt,
+tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int maxcookies,
u_long *cookies, int *ncookies)
{
struct tmpfs_dir_cursor dc;
@@ -1155,25 +1158,33 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt,
TMPFS_VALIDATE_DIR(node);
off = 0;
+
+ /*
+ * Lookup the node from the current offset. The starting offset of
+ * 0 will lookup both '.' and '..', and then the first real entry,
+ * or EOF if there are none. Then find all entries for the dir that
+ * fit into the buffer. Once no more entries are found (de == NULL),
+ * the offset is set to TMPFS_DIRCOOKIE_EOF, which will cause the next
+ * call to return 0.
+ */
switch (uio->uio_offset) {
case TMPFS_DIRCOOKIE_DOT:
error = tmpfs_dir_getdotdent(node, uio);
if (error != 0)
return (error);
uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
- if (cnt != 0)
+ if (cookies != NULL)
cookies[(*ncookies)++] = off = uio->uio_offset;
+ /* FALLTHROUGH */
case TMPFS_DIRCOOKIE_DOTDOT:
error = tmpfs_dir_getdotdotdent(node, uio);
if (error != 0)
return (error);
de = tmpfs_dir_first(node, &dc);
- if (de == NULL)
- uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
- else
- uio->uio_offset = tmpfs_dirent_cookie(de);
- if (cnt != 0)
+ uio->uio_offset = tmpfs_dirent_cookie(de);
+ if (cookies != NULL)
cookies[(*ncookies)++] = off = uio->uio_offset;
+ /* EOF. */
if (de == NULL)
return (0);
break;
@@ -1183,7 +1194,7 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt,
de = tmpfs_dir_lookup_cookie(node, uio->uio_offset, &dc);
if (de == NULL)
return (EINVAL);
- if (cnt != 0)
+ if (cookies != NULL)
off = tmpfs_dirent_cookie(de);
}
@@ -1251,25 +1262,19 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt,
error = uiomove(&d, d.d_reclen, uio);
if (error == 0) {
de = tmpfs_dir_next(node, &dc);
- if (cnt != 0) {
- if (de == NULL)
- off = TMPFS_DIRCOOKIE_EOF;
- else
- off = tmpfs_dirent_cookie(de);
- MPASS(*ncookies < cnt);
+ if (cookies != NULL) {
+ off = tmpfs_dirent_cookie(de);
+ MPASS(*ncookies < maxcookies);
cookies[(*ncookies)++] = off;
}
}
} while (error == 0 && uio->uio_resid > 0 && de != NULL);
- /* Update the offset and cache. */
- if (cnt == 0) {
- if (de == NULL)
- off = TMPFS_DIRCOOKIE_EOF;
- else
- off = tmpfs_dirent_cookie(de);
- }
+ /* Skip setting off when using cookies as it is already done above. */
+ if (cookies == NULL)
+ off = tmpfs_dirent_cookie(de);
+ /* Update the offset and cache. */
uio->uio_offset = off;
node->tn_dir.tn_readdir_lastn = off;
node->tn_dir.tn_readdir_lastp = de;
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 073a9fe..7f74f20 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -1199,32 +1199,38 @@ tmpfs_readdir(struct vop_readdir_args *v)
int error;
ssize_t startresid;
- int cnt = 0;
+ int maxcookies;
struct tmpfs_node *node;
/* This operation only makes sense on directory nodes. */
if (vp->v_type != VDIR)
return ENOTDIR;
+ maxcookies = 0;
node = VP_TO_TMPFS_DIR(vp);
startresid = uio->uio_resid;
+ /* Allocate cookies for NFS and compat modules. */
if (cookies != NULL && ncookies != NULL) {
- cnt = howmany(node->tn_size, sizeof(struct tmpfs_dirent)) + 2;
- *cookies = malloc(cnt * sizeof(**cookies), M_TEMP, M_WAITOK);
+ maxcookies = howmany(node->tn_size,
+ sizeof(struct tmpfs_dirent)) + 2;
+ *cookies = malloc(maxcookies * sizeof(**cookies), M_TEMP,
+ M_WAITOK);
*ncookies = 0;
}
- if (cnt == 0)
+ if (cookies == NULL)
error = tmpfs_dir_getdents(node, uio, 0, NULL, NULL);
else
- error = tmpfs_dir_getdents(node, uio, cnt, *cookies, ncookies);
+ error = tmpfs_dir_getdents(node, uio, maxcookies, *cookies,
+ ncookies);
+ /* Buffer was filled without hitting EOF. */
if (error == EJUSTRETURN)
error = (uio->uio_resid != startresid) ? 0 : EINVAL;
- if (error != 0 && cnt != 0)
+ if (error != 0 && cookies != NULL)
free(*cookies, M_TEMP);
if (eofflag != NULL)
OpenPOWER on IntegriCloud