diff options
author | dfr <dfr@FreeBSD.org> | 1997-04-05 12:23:44 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1997-04-05 12:23:44 +0000 |
commit | f5e07dc7a9122ab09ec825245491e1391f8c51ba (patch) | |
tree | cf3b0ae1d2fc814e88c42dfff736721954bf2826 /sys | |
parent | b8a7416e6941f3652915e34a329f7d580290e79b (diff) | |
download | FreeBSD-src-f5e07dc7a9122ab09ec825245491e1391f8c51ba.zip FreeBSD-src-f5e07dc7a9122ab09ec825245491e1391f8c51ba.tar.gz |
Support NFS cookies in VOP_READDIR, allowing ext2fs filesystems to be
exported via NFS.
2.2 candidate.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/gnu/ext2fs/ext2_lookup.c | 26 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_lookup.c | 26 |
2 files changed, 52 insertions, 0 deletions
diff --git a/sys/gnu/ext2fs/ext2_lookup.c b/sys/gnu/ext2fs/ext2_lookup.c index 566d99c..23fc1e4 100644 --- a/sys/gnu/ext2fs/ext2_lookup.c +++ b/sys/gnu/ext2fs/ext2_lookup.c @@ -156,6 +156,7 @@ ext2_readdir(ap) int count, error; struct ext2_dir_entry *edp, *dp; + int ncookies; struct dirent dstdp; struct uio auio; struct iovec aiov; @@ -183,6 +184,7 @@ printf("ext2_readdir called uio->uio_offset %d uio->uio_resid %d count %d \n", if (error == 0) { readcnt = count - auio.uio_resid; edp = (struct ext2_dir_entry *)&dirbuf[readcnt]; + ncookies = 0; for (dp = (struct ext2_dir_entry *)dirbuf; !error && uio->uio_resid > 0 && dp < edp; ) { ext2_dirconv2ffs(dp, &dstdp); @@ -194,6 +196,8 @@ printf("ext2_readdir called uio->uio_offset %d uio->uio_resid %d count %d \n", error = uiomove((caddr_t)&dstdp, dstdp.d_reclen, uio); + if (!error) + ncookies++; } else break; } else { @@ -203,8 +207,30 @@ printf("ext2_readdir called uio->uio_offset %d uio->uio_resid %d count %d \n", } /* we need to correct uio_offset */ uio->uio_offset = startoffset + (caddr_t)dp - dirbuf; + + if (!error && ap->a_ncookies != NULL) { + u_long *cookies; + u_long *cookiep; + off_t off; + + if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) + panic("ext2fs_readdir: unexpected uio from NFS server"); + MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, + M_WAITOK); + off = startoffset; + for (dp = (struct ext2_dir_entry *)dirbuf, cookiep = cookies; + dp < edp; + dp = (struct ext2_dir_entry *)((caddr_t) dp + dp->rec_len)) { + off += dp->rec_len; + *cookiep++ = (u_long) off; + } + *ap->a_ncookies = ncookies; + *ap->a_cookies = cookies; + } } FREE(dirbuf, M_TEMP); + if (ap->a_eofflag) + *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; return (error); } diff --git a/sys/gnu/fs/ext2fs/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c index 566d99c..23fc1e4 100644 --- a/sys/gnu/fs/ext2fs/ext2_lookup.c +++ b/sys/gnu/fs/ext2fs/ext2_lookup.c @@ -156,6 +156,7 @@ ext2_readdir(ap) int count, error; struct ext2_dir_entry *edp, *dp; + int ncookies; struct dirent dstdp; struct uio auio; struct iovec aiov; @@ -183,6 +184,7 @@ printf("ext2_readdir called uio->uio_offset %d uio->uio_resid %d count %d \n", if (error == 0) { readcnt = count - auio.uio_resid; edp = (struct ext2_dir_entry *)&dirbuf[readcnt]; + ncookies = 0; for (dp = (struct ext2_dir_entry *)dirbuf; !error && uio->uio_resid > 0 && dp < edp; ) { ext2_dirconv2ffs(dp, &dstdp); @@ -194,6 +196,8 @@ printf("ext2_readdir called uio->uio_offset %d uio->uio_resid %d count %d \n", error = uiomove((caddr_t)&dstdp, dstdp.d_reclen, uio); + if (!error) + ncookies++; } else break; } else { @@ -203,8 +207,30 @@ printf("ext2_readdir called uio->uio_offset %d uio->uio_resid %d count %d \n", } /* we need to correct uio_offset */ uio->uio_offset = startoffset + (caddr_t)dp - dirbuf; + + if (!error && ap->a_ncookies != NULL) { + u_long *cookies; + u_long *cookiep; + off_t off; + + if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) + panic("ext2fs_readdir: unexpected uio from NFS server"); + MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, + M_WAITOK); + off = startoffset; + for (dp = (struct ext2_dir_entry *)dirbuf, cookiep = cookies; + dp < edp; + dp = (struct ext2_dir_entry *)((caddr_t) dp + dp->rec_len)) { + off += dp->rec_len; + *cookiep++ = (u_long) off; + } + *ap->a_ncookies = ncookies; + *ap->a_cookies = cookies; + } } FREE(dirbuf, M_TEMP); + if (ap->a_eofflag) + *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; return (error); } |