Browse Source

UFS - add Buf, Uio, ufs_readdir

Uio uses Block under the hood.
Removed code for cookies and EOF flag from ufs_readdir, as that's only for NFS support in FreeBSD.
Still need to handle Block-related errors, since they would occur deep in the UFS code.

Signed-off-by: Graham MacDonald <grahamamacdonald@gmail.com>
Graham MacDonald 6 years ago
parent
commit
6dc18de837

+ 3 - 0
sys/include/ufs/freebsd_util.h

@@ -98,10 +98,13 @@ typedef int64_t intmax_t;	/* FIXME: This should probably be moved to <u.h> or re
  */
 #define	EPERM		1		/* Operation not permitted */
 #define	ENOENT		2		/* No such file or directory */
+#define	EIO		5		/* Input/output error */
 #define	EINVAL		22		/* Invalid argument */
 #define	EFBIG		27		/* File too large */
 #define	ENOSPC		28		/* No space left on device */
 
+#define	EJUSTRETURN	(-2)		/* don't modify regs, just return */
+
 #define S_IFMT 0170000		/* type of file */
 
 /*

+ 1 - 1
sys/include/ufs/ufsmount.h

@@ -79,7 +79,7 @@ typedef struct ufsmount {
 	//uint	um_trim_inflight;
 	//struct taskqueue *um_trim_tq;
 	int	(*um_balloc)(vnode *, off_t, int, Ucred *, int, Buf **);
-	int	(*um_blkatoff)(vnode *, off_t, char **, void **);
+	int	(*um_blkatoff)(vnode *, off_t, char **, Buf **);
 	int	(*um_truncate)(vnode *, off_t, int, Ucred *);
 	int	(*um_update)(vnode *, int);
 	int	(*um_valloc)(vnode *, int, Ucred *, vnode **);

+ 1 - 1
sys/src/9/ufs/ffs_extern.h

@@ -50,7 +50,7 @@ typedef struct workhead workhead;
 //	    struct ucred *, ufs2_daddr_t *);
 int	ffs_balloc_ufs2(vnode *a_vp, off_t a_startoffset, int a_size,
             Ucred *a_cred, int a_flags, Buf **a_bpp);
-int	ffs_blkatoff(vnode *, off_t, char **, void **);
+int	ffs_blkatoff(vnode *, off_t, char **, Buf **);
 /*void	ffs_blkfree(struct ufsmount *, struct fs *, struct vnode *,
 	    ufs2_daddr_t, long, ino_t, enum vtype, struct workhead *);
 ufs2_daddr_t ffs_blkpref_ufs1(struct inode *, ufs_lbn_t, int, ufs1_daddr_t *);

+ 1 - 1
sys/src/9/ufs/ffs_subr.c

@@ -66,7 +66,7 @@ ffs_blkatoff(vnode *vp, off_t offset, char **res, Buf **bpp)
 	bsize = blksize(fs, ip, lbn);
 
 	*bpp = nil;
-	error = bread(vp->mount, lbn, bsize, /*NOCRED,*/ &bp); 
+	error = bread(vp, lbn, bsize, /*NOCRED,*/ &bp); 
 	if (error) {
 		releasebuf(bp);
 		return (error);

+ 4 - 4
sys/src/9/ufs/ffs_vfsops.c

@@ -720,7 +720,7 @@ static int sblock_try[] = SBLOCKSEARCH;
  * Common code for mount and mountroot
  */
 static int 
-ffs_mountfs (vnode *devvp, MountPoint *mp, thread *td)
+ffs_mountfs(vnode *devvp, MountPoint *mp, thread *td)
 {
 	// TODO HARVEY - Don't need devvp, and maybe don't need td?
 	Fs *fs;
@@ -780,7 +780,7 @@ ffs_mountfs (vnode *devvp, MountPoint *mp, thread *td)
 			goto out;
 		}*/
 
-		if (bread(mp, btodb(sblock_try[i]), SBLOCKSIZE, &buf) != 0) {
+		if (breadmp(mp, btodb(sblock_try[i]), SBLOCKSIZE, &buf) != 0) {
 			releasebuf(buf);
 			print("not found at %p\n", sblock_try[i]);
 			error = -1;
@@ -887,7 +887,7 @@ ffs_mountfs (vnode *devvp, MountPoint *mp, thread *td)
 		if (i + fs->fs_frag > blks)
 			size = (blks - i) * fs->fs_fsize;
 
-		error = bread(mp, fsbtodb(fs, fs->fs_csaddr + i), size, &buf);
+		error = breadmp(mp, fsbtodb(fs, fs->fs_csaddr + i), size, &buf);
 		if (error != 0) {
 			free(fs->fs_csp);
 			goto out;
@@ -1582,7 +1582,7 @@ ffs_vgetf(MountPoint *mp, ino_t ino, int flags, vnode **vpp, int ffs_flags)
 	//	return (error);
 
 	/* Read in the disk contents for the inode, copy into the inode. */
-	error = bread(mp, fsbtodb(fs, ino_to_fsba(fs, ino)),
+	error = breadmp(mp, fsbtodb(fs, ino_to_fsba(fs, ino)),
 		(int)fs->fs_bsize, &buf);
 	if (error) {
 		/*

+ 22 - 24
sys/src/9/ufs/ufs_bmap.c

@@ -107,10 +107,10 @@ ufs_bmaparray(
 	int *runp,
 	int *runb)
 {
-	//struct buf *bp;
+	Buf *bp;
 	Indir a[UFS_NIADDR+1], *ap;
 	ufs2_daddr_t daddr;
-	//ufs_lbn_t metalbn;
+	ufs_lbn_t metalbn;
 	int error, num, maxrun = 0;
 	int *nump;
 
@@ -186,8 +186,6 @@ ufs_bmaparray(
 	/* Get disk address out of indirect block array */
 	daddr = ip->din2->di_ib[ap->in_off];
 
-#if 0
-
 	for (bp = nil, ++ap; --num; ++ap) {
 		/*
 		 * Exit the loop if there is no disk address assigned yet and
@@ -196,17 +194,25 @@ ufs_bmaparray(
 		 */
 
 		metalbn = ap->in_lbn;
-		if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn)
+
+		// TODO HARVEY Going to have to revisit this when we implement
+		// writing, so we can read writes before they've been flushed
+		// to disk.
+		//if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn)
+		//	break;
+		if (daddr == 0 || metalbn == bn)
 			break;
+
 		/*
 		 * If we get here, we've either got the block in the cache
 		 * or we have a disk address for it, go fetch it.
 		 */
 		if (bp)
-			bqrelse(bp);
+			releasebuf(bp);
 
-		bp = getblk(vp, metalbn, mp->mnt_stat.f_iosize, 0, 0, 0);
-		if ((bp->b_flags & B_CACHE) == 0) {
+		bp = getblk(vp, metalbn, mp->mnt_stat.f_iosize, 0);
+		// TODO HARVEY Revisit when we manage a cache of Bufs
+		/*if ((bp->b_flags & B_CACHE) == 0) {
 #ifdef INVARIANTS
 			if (!daddr)
 				panic("ufs_bmaparray: indirect block not in cache");
@@ -217,43 +223,35 @@ ufs_bmaparray(
 			bp->b_ioflags &= ~BIO_ERROR;
 			vfs_busy_pages(bp, 0);
 			bp->b_iooffset = dbtob(bp->b_blkno);
-			bstrategy(bp);
-#ifdef RACCT
-			if (racct_enable) {
-				PROC_LOCK(curproc);
-				racct_add_buf(curproc, bp, 0);
-				PROC_UNLOCK(curproc);
-			}
-#endif /* RACCT */
+			ffs_geom_strategy(bp);
 			curthread->td_ru.ru_inblock++;
 			error = bufwait(bp);
 			if (error) {
 				brelse(bp);
 				return (error);
 			}
-		}
+		}*/
 
-		daddr = ((ufs2_daddr_t *)bp->b_data)[ap->in_off];
+		daddr = ((ufs2_daddr_t *)bp->data)[ap->in_off];
 		if (num == 1 && daddr && runp) {
 			for (bn = ap->in_off + 1;
-			    bn < MNINDIR(ump) && *runp < maxrun &&
+			    bn < ump->um_nindir && *runp < maxrun &&
 			    is_sequential(ump,
-			    ((ufs2_daddr_t *)bp->b_data)[bn - 1],
-			    ((ufs2_daddr_t *)bp->b_data)[bn]);
+			    ((ufs2_daddr_t *)bp->data)[bn - 1],
+			    ((ufs2_daddr_t *)bp->data)[bn]);
 			    ++bn, ++*runp);
 			bn = ap->in_off;
 			if (runb && bn) {
 				for (--bn; bn >= 0 && *runb < maxrun &&
 				    is_sequential(ump,
-				    ((ufs2_daddr_t *)bp->b_data)[bn],
-				    ((ufs2_daddr_t *)bp->b_data)[bn + 1]);
+				    ((ufs2_daddr_t *)bp->data)[bn],
+				    ((ufs2_daddr_t *)bp->data)[bn + 1]);
 				    --bn, ++*runb);
 			}
 		}
 	}
 	if (bp)
 		releasebuf(bp);
-#endif //0
 
 	/*
 	 * Since this is FFS independent code, we are out of scope for the

+ 2 - 2
sys/src/9/ufs/ufs_extern.h

@@ -32,7 +32,7 @@
 
 //struct componentname;
 //struct direct;
-//struct indir;
+typedef struct Indir Indir;
 typedef struct inode inode;
 //struct mount;
 //struct thread;
@@ -72,7 +72,7 @@ int	 ufs_init();
 //void	 ufs_itimes(struct vnode *vp);
 //int	 ufs_lookup(vop_cachedlookup_args *);
 //void	 ufs_prepare_reclaim(struct vnode *vp);
-//int	 ufs_readdir(struct vop_readdir_args *);
+int	 ufs_readdir(vnode *, Uio *);
 //int	 ufs_reclaim(struct vop_reclaim_args *);
 void	ffs_snapgone(struct inode *);
 int	ufs_root(MountPoint *mp, int flags, vnode **vpp);

+ 31 - 5
sys/src/9/ufs/ufs_harvey_external.c

@@ -23,6 +23,7 @@
 #include "ufs/quota.h"
 #include "ufs/dinode.h"
 #include "ufs/inode.h"
+#include "ufs/dir.h"
 #include "ufs_extern.h"
 #include "ffs_extern.h"
 
@@ -228,13 +229,38 @@ writeinodedata(char *buf, int buflen, vnode *vn)
 	int i = 0;
 
 	if (vn->type == VREG) {
-		i += snprint(buf + i, buflen - i, "regular file\n");
-	} else if (vn->type == VDIR) {
-		i += snprint(buf + i, buflen - i, "directory\n");
-	} else {
-		i += snprint(buf + i, buflen - i, "unsupported inode type (%d)\n", vn->type);
+		i += snprint(buf + i, buflen - i, "file\n");
+		return i;
 	}
 
+	if (vn->type == VDIR) {
+		Uio* uio = newuio(DIRBLKSIZ);
+		uio->resid = vn->data->i_size;
+
+		int rcode = ufs_readdir(vn, uio);
+		if (rcode) {
+			i += snprint(buf + i, buflen - i, "error reading directory\n");
+			releaseuio(uio);
+			return i;
+		}
+
+		packuio(uio);
+
+		// Iterate over all files
+		int64_t diroffset = 0;
+		int64_t endoffset = uio->offset - uio->resid;
+		while (uio->offset >= 0 && diroffset < endoffset) {
+			Dirent* dir = (Dirent*)(uio->dest->rp + diroffset);
+
+			i += snprint(buf + i, buflen - i, "%s\t%llu\n", dir->name, (uint64_t)dir->fileno);
+			diroffset += dir->reclen;
+		}
+
+		releaseuio(uio);
+		return i;
+	}
+
+	i += snprint(buf + i, buflen - i, "unsupported inode type (%d)\n", vn->type);
 	return i;
 }
 

+ 89 - 6
sys/src/9/ufs/ufs_harvey_internal.c

@@ -17,6 +17,7 @@
 
 #include "ufsdat.h"
 #include "ufs/libufsdat.h"
+#include "ufs_extern.h"
 
 
 // TODO HARVEY Pool of buffers?  Aiming for as simple as possible for now.
@@ -24,7 +25,10 @@ Buf*
 newbuf(size_t size)
 {
 	Buf *b = smalloc(sizeof(Buf));
+	b->vnode = nil;
 	b->data = smalloc(size);
+	b->offset = 0;
+	b->bcount = size;
 	return b;
 }
 
@@ -33,22 +37,102 @@ releasebuf(Buf *b)
 {
 	if (b->data) {
 		free(b->data);
-		b->data = nil;
 	}
 	free(b);
 }
 
+Uio*
+newuio(int blocksize)
+{
+	// TODO HARVEY error handling
+	Uio *uio = smalloc(sizeof(Uio));
+	return uio;
+}
+
+void
+releaseuio(Uio *uio)
+{
+	// TODO HARVEY error handling
+	if (uio->dest) {
+		freeblist(uio->dest);
+	}
+	free(uio);
+}
+
+void
+packuio(Uio *uio)
+{
+	if (uio->dest) {
+		uio->dest = concatblock(uio->dest);
+	}
+}
+
+int
+uiomove(void *src, int64_t srclen, Uio *uio)
+{
+	// TODO HARVEY error handling
+	Block *block = mem2bl(src, srclen);
+
+	if (!uio->dest) {
+		uio->dest = block;
+	} else {
+		// Append block - seems like this should be a standard function
+		Block *b = uio->dest;
+		while (b->next) {
+			b = b->next;
+		}
+		b->next = block;
+	}
+
+	uio->resid -= srclen;
+	uio->offset += srclen;
+	return 0;
+}
+
+/*
+ * Wrapper to enable Harvey's channel read function to be used like FreeBSD's
+ * block read function.
+ * Use when reading Fs or anything else not relative to a vnode.
+ */
+int32_t
+breadmp(MountPoint *mp, daddr_t blkno, size_t size, Buf **buf)
+{
+	Buf *b = newbuf(size);
+
+	Chan *c = mp->chan;
+	int64_t offset = dbtob(blkno);
+	int32_t bytesRead = c->dev->read(c, b->data, size, offset);
+	if (bytesRead != size) {
+		releasebuf(b);
+		print("bread returned wrong size\n");
+		return 1;
+	}
+
+	*buf = b;
+	return 0;
+}
+
 /*
  * Wrapper to enable Harvey's channel read function to be used like FreeBSD's
  * block read function.
+ * Use when reading relative to a vnode.
  */
 int32_t
-bread(MountPoint *mp, daddr_t blockno, size_t size, Buf **buf)
+bread(vnode *vn, daddr_t lblkno, size_t size, Buf **buf)
 {
+	daddr_t pblkno;
+	int rcode = ufs_bmaparray(vn, lblkno, &pblkno, nil, nil, nil);
+	if (rcode) {
+		print("bread failed to transform logical block to physical\n");
+		return 1;
+	}
+
 	Buf *b = newbuf(size);
+	b->vnode = vn;
 
+	MountPoint *mp = vn->mount;
 	Chan *c = mp->chan;
-	int64_t offset = dbtob(blockno);
+	int64_t offset = dbtob(pblkno);
 	int32_t bytesRead = c->dev->read(c, b->data, size, offset);
 	if (bytesRead != size) {
 		releasebuf(b);
@@ -61,11 +145,10 @@ bread(MountPoint *mp, daddr_t blockno, size_t size, Buf **buf)
 }
 
 Buf *
-getblk(vnode *vp, daddr_t blkno, size_t size, int flags)
+getblk(vnode *vn, daddr_t lblkno, size_t size, int flags)
 {
 	Buf *b;
-	MountPoint *mp = vp->mount;
-	int32_t rcode = bread(mp, blkno, size, &b);
+	int32_t rcode = bread(vn, lblkno, size, &b);
 	if (rcode) {
 		print("getblk - bread failed\n");
 		return nil;

+ 61 - 79
sys/src/9/ufs/ufs_vnops.c

@@ -48,12 +48,11 @@
 #include "ufs/quota.h"
 #include "ufs/inode.h"
 #include "ufs/dinode.h"
+#include "ufs/dir.h"
+#include "ffs_extern.h"
 
 /*#include <ufs/ufs/acl.h>
 #include <ufs/ufs/extattr.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-#include <ufs/ufs/dir.h>
 #include <ufs/ufs/ufsmount.h>
 #include <ufs/ufs/ufs_extern.h>
 #ifdef UFS_DIRHASH
@@ -69,10 +68,21 @@ FEATURE(ufs_quota64, "64bit UFS disk quotas support");
 FEATURE(suiddir,
     "Give all new files in directory the same ownership as the directory");
 #endif
+*/
 
 
-#include <ufs/ffs/ffs_extern.h>
-*/
+/*
+ * The _GENERIC_DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry.  This returns the amount of space in struct direct
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ *
+ * XXX although this macro is in the implementation namespace, it requires
+ * a manifest constant that is not.
+ */
+#define	GENERIC_DIRSIZ(dp) \
+    ((sizeof (Dirent) - (UFS_MAXNAMLEN+1)) + (((dp)->namlen+1 + 3) &~ 3))
+
 
 #if 0
 static vop_accessx_t	ufs_accessx;
@@ -2019,126 +2029,98 @@ ufs_symlink (struct vop_symlink_args *ap)
 		vput(vp);
 	return (error);
 }
+#endif // 0
 
 /*
  * Vnode op for reading directories.
  */
 int 
-ufs_readdir (struct vop_readdir_args *ap)
+ufs_readdir(vnode * vp, Uio *uio)
 {
-	struct vnode *vp = ap->a_vp;
-	struct uio *uio = ap->a_uio;
-	struct buf *bp;
-	struct inode *ip;
-	struct direct *dp, *edp;
-	uint64_t *cookies;
-	struct dirent dstdp;
+	Buf *bp;
+	inode *ip;
+	Direct *dp, *edp;
+	Dirent dstdp;
 	off_t offset, startoffset;
 	size_t readcnt, skipcnt;
-	ssize_t startresid;
-	int ncookies;
+	int64_t startresid;
 	int error;
 
-	if (uio->uio_offset < 0)
+	if (uio->offset < 0)
 		return (EINVAL);
 	ip = VTOI(vp);
 	if (ip->i_effnlink == 0)
 		return (0);
-	if (ap->a_ncookies != nil) {
-		ncookies = uio->uio_resid;
-		if (uio->uio_offset >= ip->i_size)
-			ncookies = 0;
-		else if (ip->i_size - uio->uio_offset < ncookies)
-			ncookies = ip->i_size - uio->uio_offset;
-		ncookies = ncookies / (offsetof(struct direct, d_name) + 4) + 1;
-		cookies = malloc(ncookies * sizeof(*cookies), M_TEMP, M_WAITOK);
-		*ap->a_ncookies = ncookies;
-		*ap->a_cookies = cookies;
-	} else {
-		ncookies = 0;
-		cookies = nil;
-	}
-	offset = startoffset = uio->uio_offset;
-	startresid = uio->uio_resid;
+
+	offset = startoffset = uio->offset;
+	startresid = uio->resid;
 	error = 0;
-	while (error == 0 && uio->uio_resid > 0 &&
-	    uio->uio_offset < ip->i_size) {
-		error = ffs_blkatoff(vp, uio->uio_offset, nil, &bp);
+	while (error == 0 && uio->resid > 0 && uio->offset < ip->i_size) {
+		error = ffs_blkatoff(vp, uio->offset, nil, &bp);
 		if (error)
 			break;
-		if (bp->b_offset + bp->b_bcount > ip->i_size)
-			readcnt = ip->i_size - bp->b_offset;
+		
+		if (bp->offset + bp->bcount > ip->i_size)
+			readcnt = ip->i_size - bp->offset;
 		else
-			readcnt = bp->b_bcount;
-		skipcnt = (size_t)(uio->uio_offset - bp->b_offset) &
-		    ~(size_t)(DIRBLKSIZ - 1);
-		offset = bp->b_offset + skipcnt;
-		dp = (struct direct *)&bp->b_data[skipcnt];
-		edp = (struct direct *)&bp->b_data[readcnt];
-		while (error == 0 && uio->uio_resid > 0 && dp < edp) {
-			if (dp->d_reclen <= offsetof(struct direct, d_name) ||
+			readcnt = bp->bcount;
+
+		skipcnt = (size_t)(uio->offset - bp->offset) & ~(size_t)(DIRBLKSIZ - 1);
+		offset = bp->offset + skipcnt;
+		dp = (Direct *)&bp->data[skipcnt];
+		edp = (Direct *)&bp->data[readcnt];
+		while (error == 0 && uio->resid > 0 && dp < edp) {
+			if (dp->d_reclen <= offsetof(Direct, d_name) ||
 			    (caddr_t)dp + dp->d_reclen > (caddr_t)edp) {
 				error = EIO;
 				break;
 			}
 
-			dstdp.d_namlen = dp->d_namlen;
-			dstdp.d_type = dp->d_type;
+			dstdp.namlen = dp->d_namlen;
+			dstdp.type = dp->d_type;
 
-			if (offsetof(struct direct, d_name) + dstdp.d_namlen >
-			    dp->d_reclen) {
+			if (offsetof(Direct, d_name) + dstdp.namlen > dp->d_reclen) {
 				error = EIO;
 				break;
 			}
 			if (offset < startoffset || dp->d_ino == 0)
 				goto nextentry;
-			dstdp.d_fileno = dp->d_ino;
-			dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
-			bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen);
-			dstdp.d_name[dstdp.d_namlen] = '\0';
-			if (dstdp.d_reclen > uio->uio_resid) {
-				if (uio->uio_resid == startresid)
+
+			dstdp.fileno = dp->d_ino;
+			dstdp.reclen = GENERIC_DIRSIZ(&dstdp);
+			memmove(dstdp.name, dp->d_name, dstdp.namlen);
+			dstdp.name[dstdp.namlen] = '\0';
+
+			if (dstdp.reclen > uio->resid) {
+				if (uio->resid == startresid)
 					error = EINVAL;
 				else
 					error = EJUSTRETURN;
 				break;
 			}
+			
 			/* Advance dp. */
-			error = uiomove((caddr_t)&dstdp, dstdp.d_reclen, uio);
+			error = uiomove(&dstdp, dstdp.reclen, uio);
 			if (error)
 				break;
-			if (cookies != nil) {
-				KASSERT(ncookies > 0,
-				    ("ufs_readdir: cookies buffer too small"));
-				*cookies = offset + dp->d_reclen;
-				cookies++;
-				ncookies--;
-			}
+
 nextentry:
 			offset += dp->d_reclen;
-			dp = (struct direct *)((caddr_t)dp + dp->d_reclen);
+			dp = (Direct *)((caddr_t)dp + dp->d_reclen);
 		}
-		bqrelse(bp);
-		uio->uio_offset = offset;
+		releasebuf(bp);
+		uio->offset = offset;
 	}
+
 	/* We need to correct uio_offset. */
-	uio->uio_offset = offset;
+	uio->offset = offset;
 	if (error == EJUSTRETURN)
 		error = 0;
-	if (ap->a_ncookies != nil) {
-		if (error == 0) {
-			ap->a_ncookies -= ncookies;
-		} else {
-			free(*ap->a_cookies, M_TEMP);
-			*ap->a_ncookies = 0;
-			*ap->a_cookies = nil;
-		}
-	}
-	if (error == 0 && ap->a_eofflag)
-		*ap->a_eofflag = ip->i_size <= uio->uio_offset;
-	return (error);
+	return error;
 }
 
+#if 0
+
 /*
  * Return target name of a symbolic link
  */

+ 26 - 1
sys/src/9/ufs/ufsdat.h

@@ -31,10 +31,23 @@ typedef struct thread {
 typedef struct Ucred {
 } Ucred;
 
+
 typedef struct Buf {
-	void *data;
+	vnode*	vnode;
+	void*	data;
+	size_t	bcount;		/* Requested size of buffer */
+	int64_t	offset;		/* Offset into file. */
 } Buf;
 
+
+typedef struct Uio {
+	int64_t	offset;		/* offset in target object */
+	int64_t	resid;		/* remaining bytes to process */
+
+	Block*	dest;
+} Uio;
+
+
 /*
  * filesystem statistics
  */
@@ -105,6 +118,18 @@ typedef struct vnode {
 } vnode;
 
 
+#define	MAXUFSNAMLEN	255
+
+
+typedef struct Dirent {
+	uint32_t	fileno;			// file number of entry
+	uint16_t	reclen;			// length of this record
+	uint8_t		type; 			// file type, see below
+	uint8_t		namlen;			// length of string in name
+	char		name[MAXUFSNAMLEN + 1];	// name must be no longer than this
+} Dirent;
+
+
 /*
  * Vnode flags.
  *	VI flags are protected by interlock and live in v_iflag

+ 7 - 2
sys/src/9/ufs/ufsfns.h

@@ -39,9 +39,14 @@ int		ffs_unmount(MountPoint *mp, int mntflags);
 // Internal functions - maybe they should be somewhere else?
 void		assert_vop_locked(vnode *vp, const char *str);
 void		assert_vop_elocked(vnode *vp, const char *str);
-int32_t		bread(MountPoint *mp, daddr_t blockno, size_t size, Buf **buf);
+int32_t		bread(vnode *vn, daddr_t blockno, size_t size, Buf **buf);
+int32_t		breadmp(MountPoint *mp, daddr_t blockno, size_t size, Buf **buf);
 void		check_vnodes_locked(MountPoint *mp);
-Buf*		getblk(vnode *vp, daddr_t blkno, size_t size, int flags);
+Buf*		getblk(vnode *vn, daddr_t blkno, size_t size, int flags);
 Vtype		ifmt_to_vtype(uint16_t imode);
 Buf*		newbuf(size_t size);
+Uio*		newuio(int blocksize);
+void		packuio(Uio *uio);
 void		releasebuf(Buf *b);
+void		releaseuio(Uio *uio);
+int		uiomove(void *src, int64_t srclen, Uio *uio);