Subject: RFC: lseek() extension for sparse files version 3 + UFS implementation
To: None <tech-kern@NetBSD.org>
From: Reinoud Zandijk <reinoud@netbsd.org>
List: tech-kern
Date: 09/26/2006 21:36:04
--f2QGlHpHGjS2mn6Y
Content-Type: multipart/mixed; boundary="pWyiEgJYm5f9v55/"
Content-Disposition: inline
--pWyiEgJYm5f9v55/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Dear folks,
thanks for the feedback on the former two patches. I've created a hopefully
final patch for RFC to implement the Solaris lseek() extension to handle
sparse files.
I've also included an UFS implementation at request that is thus
implemented for ffs, lfs and ext2fs. The patch only works on the inode
datastructure and is FFS agnostic and thus should work for all UFS since
neither lfs nor ext2fs uses a special routine.
If there are no objections i'd like to submit it. So please try it out! :)
Attached is also a test-program that uses the new lseek() primitives to
copy a sparse file.
With regards,
Reinoud
--pWyiEgJYm5f9v55/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=DIFFS-sparse-20060926b
Index: include/stdio.h
===================================================================
RCS file: /cvsroot/src/include/stdio.h,v
retrieving revision 1.64
diff -u -p -r1.64 stdio.h
--- include/stdio.h 10 May 2006 21:09:45 -0000 1.64
+++ include/stdio.h 26 Sep 2006 16:59:02 -0000
@@ -203,6 +203,12 @@ __END_DECLS
#ifndef SEEK_END
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
+#ifndef SEEK_DATA
+#define SEEK_DATA 3 /* Set file pointer to next data past offset */
+#endif
+#ifndef SEEK_HOLE
+#define SEEK_HOLE 4 /* Set file pointer to next hole past offset */
+#endif
#define stdin (&__sF[0])
#define stdout (&__sF[1])
Index: lib/libc/sys/lseek.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/lseek.2,v
retrieving revision 1.22
diff -u -p -r1.22 lseek.2
--- lib/libc/sys/lseek.2 13 May 2004 10:20:58 -0000 1.22
+++ lib/libc/sys/lseek.2 26 Sep 2006 16:59:06 -0000
@@ -29,7 +29,7 @@
.\"
.\" @(#)lseek.2 8.3 (Berkeley) 4/19/94
.\"
-.Dd April 19, 1994
+.Dd September 21, 2006
.Dt LSEEK 2
.Os
.Sh NAME
@@ -86,6 +86,29 @@ the offset is set to the size of the
file plus
.Fa offset
bytes.
+.It
+If
+.Fa whence
+is
+.Dv SEEK_DATA ,
+the offset is set to the next non-hole region which file offset is
+greater or equal to the provided
+.Fa offset
+in bytes. If specifying an
+.Fa offset
+of 0 bytes, there is guaranteed to be a data region for easy programming.
+.It
+If
+.Fa whence
+is
+.Dv SEEK_HOLE ,
+the offset is set to the next hole region which file offset is
+greater or equal to the provided
+.Fa offset
+in bytes. If specifying an
+.Fa offset
+within the boundaries of the file, there is a guaranteed virtual hole at the
+end of the file for easy programming.
.El
.Pp
The
@@ -121,6 +144,9 @@ is associated with a pipe, socket, or FI
.It Bq Er EINVAL
.Fa whence
is not a proper value, or the resulting file offset would be invalid.
+.It Bq Er ENXIO
+No more data regions or hole regions are present past the supplied
+.Fa offset
.El
.Sh SEE ALSO
.Xr dup 2 ,
@@ -129,8 +155,18 @@ is not a proper value, or the resulting
The
.Fn lseek
function conforms to
-.St -p1003.1-90 .
+.St -p1003.1-90 . The
+.Dv SEEK_DATA
+and
+.Dv SEEK_HOLE
+conform to the Solaris 10 implemention.
.Sh BUGS
This document's use of
.Fa whence
is incorrect English, but is maintained for historical reasons.
+.Sh HISTORY
+The
+.Dv SEEK_DATA
+and
+.Dv SEEK_HOLE
+functionality was added in NetBSD 5.0
Index: share/man/man9/vnodeops.9
===================================================================
RCS file: /cvsroot/src/share/man/man9/vnodeops.9,v
retrieving revision 1.51
diff -u -p -r1.51 vnodeops.9
--- share/man/man9/vnodeops.9 16 Sep 2006 08:54:22 -0000 1.51
+++ share/man/man9/vnodeops.9 26 Sep 2006 16:59:14 -0000
@@ -146,8 +146,8 @@
.Fn VOP_FSYNC "struct vnode *vp" "struct ucred *cred" "int flags" \
"off_t offlo" "off_t offhi" "struct lwp *l"
.Ft int
-.Fn VOP_SEEK "struct vnode *vp" "off_t oldoff" "off_t newoff" \
-"struct ucred *cred"
+.Fn VOP_SEEK "struct vnode *vp" "off_t oldoffset" "int whence" \
+"off_t givenoffset" "off_t *newoffset" "struct ucred *cred"
.Ft int
.Fn VOP_REMOVE "struct vnode *vp" "struct vnode *vp" \
"struct componentname *cnp"
@@ -828,18 +828,32 @@ This function implements the
and
.Xr fsync 2
system calls.
-.It Fn VOP_SEEK "vp" "oldoff" "newoff" "cred"
-Test if the file is seekable for the specified offset
-.Fa newoff .
+.It Fn VOP_SEEK "vp" "oldoffset" "whence" "givenoffset" "*newoffset" "cred"
+Implements the
+.Xr lseek 1
+function on a node. It tests if the file is seekable for the specified offset
+.Fa givenoffset
+with the method
+.Fa whence .
The argument
.Fa vp
is the locked vnode of the file to test.
-For most filesystems this function simply tests if
-.Fa newoff
-is valid.
-If the specified
-.Fa newoff
-is less than zero, the function returns error code EINVAL.
+Filesystems should return the new offset in
+.Fa *newoffset
+and return EINVAL if the resulting offset is invalid. If
+.Fa *newoffset
+is
+.Dv NULL
+no value needs to be returned. If
+.Fa *vattr
+is
+.Dv NULL
+, only
+.Dv SEEK_SET
+and
+.Dv SEEK_CUR
+are valid operations for
+.Fa whence .
.It Fn VOP_REMOVE "dvp" "vp" "cnp"
Remove a file.
The argument
@@ -1462,6 +1476,9 @@ input
.It Bq Er EIO
a read error occurred while reading the directory or reading the
contents of a symbolic link
+.It Bq Er ENXIO
+a seek for a data segment or hole segment in a file indicated no more segments
+from the given offset are defined.
.It Bq Er EROFS
the filesystem is read-only
.El
Index: sys/fs/ptyfs/ptyfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/ptyfs/ptyfs_vnops.c,v
retrieving revision 1.16
diff -u -p -r1.16 ptyfs_vnops.c
--- sys/fs/ptyfs/ptyfs_vnops.c 23 Jul 2006 22:06:10 -0000 1.16
+++ sys/fs/ptyfs/ptyfs_vnops.c 26 Sep 2006 16:59:32 -0000
@@ -128,7 +128,7 @@ int ptyfs_kqfilter (void *);
#define ptyfs_revoke genfs_revoke
#define ptyfs_mmap genfs_eopnotsupp
#define ptyfs_fsync genfs_nullop
-#define ptyfs_seek genfs_nullop
+#define ptyfs_seek genfs_seek
#define ptyfs_remove genfs_eopnotsupp
#define ptyfs_link genfs_abortop
#define ptyfs_rename genfs_eopnotsupp
Index: sys/fs/union/union_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/union/union_vnops.c,v
retrieving revision 1.16
diff -u -p -r1.16 union_vnops.c
--- sys/fs/union/union_vnops.c 14 May 2006 21:31:52 -0000 1.16
+++ sys/fs/union/union_vnops.c 26 Sep 2006 16:59:33 -0000
@@ -1207,8 +1207,10 @@ union_seek(v)
{
struct vop_seek_args /* {
struct vnode *a_vp;
- off_t a_oldoff;
- off_t a_newoff;
+ off_t a_oldoffset;
+ int a_whence;
+ off_t a_givenoffset;
+ off_t *a_newoffset;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *ovp = OTHERVP(ap->a_vp);
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.270
diff -u -p -r1.270 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c 13 Sep 2006 10:07:42 -0000 1.270
+++ sys/kern/vfs_syscalls.c 26 Sep 2006 16:59:33 -0000
@@ -2117,8 +2117,7 @@ sys_lseek(struct lwp *l, void *v, regist
struct filedesc *fdp = p->p_fd;
struct file *fp;
struct vnode *vp;
- struct vattr vattr;
- off_t newoff;
+ off_t newoffset;
int error;
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
@@ -2129,31 +2128,14 @@ sys_lseek(struct lwp *l, void *v, regist
vp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
error = ESPIPE;
- goto out;
+ } else {
+ error = VOP_SEEK(vp, fp->f_offset, SCARG(uap, whence),
+ SCARG(uap, offset), &newoffset, cred);
}
- switch (SCARG(uap, whence)) {
- case SEEK_CUR:
- newoff = fp->f_offset + SCARG(uap, offset);
- break;
- case SEEK_END:
- error = VOP_GETATTR(vp, &vattr, cred, l);
- if (error)
- goto out;
- newoff = SCARG(uap, offset) + vattr.va_size;
- break;
- case SEEK_SET:
- newoff = SCARG(uap, offset);
- break;
- default:
- error = EINVAL;
- goto out;
- }
- if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0)
- goto out;
+ if (error == 0)
+ *(off_t *)retval = fp->f_offset = newoffset;
- *(off_t *)retval = fp->f_offset = newoff;
- out:
FILE_UNUSE(fp, l);
return (error);
}
@@ -2170,6 +2152,7 @@ sys_pread(struct lwp *l, void *v, regist
syscallarg(size_t) nbyte;
syscallarg(off_t) offset;
} */ *uap = v;
+ kauth_cred_t cred = l->l_cred;
struct proc *p = l->l_proc;
struct filedesc *fdp = p->p_fd;
struct file *fp;
@@ -2199,7 +2182,8 @@ sys_pread(struct lwp *l, void *v, regist
* XXX This works because no file systems actually
* XXX take any action on the seek operation.
*/
- if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
+ error = VOP_SEEK(vp, fp->f_offset, SEEK_SET, offset, NULL, cred);
+ if (error != 0)
goto out;
/* dofileread() will unuse the descriptor for us */
@@ -2223,6 +2207,7 @@ sys_preadv(struct lwp *l, void *v, regis
syscallarg(int) iovcnt;
syscallarg(off_t) offset;
} */ *uap = v;
+ kauth_cred_t cred = l->l_cred;
struct proc *p = l->l_proc;
struct filedesc *fdp = p->p_fd;
struct file *fp;
@@ -2252,7 +2237,8 @@ sys_preadv(struct lwp *l, void *v, regis
* XXX This works because no file systems actually
* XXX take any action on the seek operation.
*/
- if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
+ error = VOP_SEEK(vp, fp->f_offset, SEEK_SET, offset, NULL, cred);
+ if (error != 0)
goto out;
/* dofilereadv() will unuse the descriptor for us */
@@ -2276,6 +2262,7 @@ sys_pwrite(struct lwp *l, void *v, regis
syscallarg(size_t) nbyte;
syscallarg(off_t) offset;
} */ *uap = v;
+ kauth_cred_t cred = l->l_cred;
struct proc *p = l->l_proc;
struct filedesc *fdp = p->p_fd;
struct file *fp;
@@ -2305,7 +2292,8 @@ sys_pwrite(struct lwp *l, void *v, regis
* XXX This works because no file systems actually
* XXX take any action on the seek operation.
*/
- if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
+ error = VOP_SEEK(vp, fp->f_offset, SEEK_SET, offset, NULL, cred);
+ if (error != 0)
goto out;
/* dofilewrite() will unuse the descriptor for us */
@@ -2329,6 +2317,7 @@ sys_pwritev(struct lwp *l, void *v, regi
syscallarg(int) iovcnt;
syscallarg(off_t) offset;
} */ *uap = v;
+ kauth_cred_t cred = l->l_cred;
struct proc *p = l->l_proc;
struct filedesc *fdp = p->p_fd;
struct file *fp;
@@ -2358,7 +2347,8 @@ sys_pwritev(struct lwp *l, void *v, regi
* XXX This works because no file systems actually
* XXX take any action on the seek operation.
*/
- if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
+ error = VOP_SEEK(vp, fp->f_offset, SEEK_SET, offset, NULL, cred);
+ if (error != 0)
goto out;
/* dofilewritev() will unuse the descriptor for us */
Index: sys/kern/vnode_if.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vnode_if.c,v
retrieving revision 1.66
diff -u -p -r1.66 vnode_if.c
--- sys/kern/vnode_if.c 13 Jul 2006 12:00:25 -0000 1.66
+++ sys/kern/vnode_if.c 26 Sep 2006 16:59:33 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vnode_if.c,v 1.66 2006/07/13 12:00:25 martin Exp $ */
+/* $NetBSD$ */
/*
* Warning: DO NOT EDIT! This file is automatically generated!
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.66 2006/07/13 12:00:25 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD$");
/*
@@ -741,8 +741,10 @@ const struct vnodeop_desc vop_seek_desc
};
int
VOP_SEEK(struct vnode *vp,
- off_t oldoff,
- off_t newoff,
+ off_t oldoffset,
+ int whence,
+ off_t givenoffset,
+ off_t *newoffset,
kauth_cred_t cred)
{
struct vop_seek_args a;
@@ -750,8 +752,10 @@ VOP_SEEK(struct vnode *vp,
#endif
a.a_desc = VDESC(vop_seek);
a.a_vp = vp;
- a.a_oldoff = oldoff;
- a.a_newoff = newoff;
+ a.a_oldoffset = oldoffset;
+ a.a_whence = whence;
+ a.a_givenoffset = givenoffset;
+ a.a_newoffset = newoffset;
a.a_cred = cred;
return (VCALL(vp, VOFFSET(vop_seek), &a));
}
Index: sys/kern/vnode_if.src
===================================================================
RCS file: /cvsroot/src/sys/kern/vnode_if.src,v
retrieving revision 1.50
diff -u -p -r1.50 vnode_if.src
--- sys/kern/vnode_if.src 14 May 2006 21:15:12 -0000 1.50
+++ sys/kern/vnode_if.src 26 Sep 2006 16:59:34 -0000
@@ -266,13 +266,14 @@ vop_fsync {
};
#
-# Needs work: Is newoff right? What's it mean?
# XXX Locking protocol?
#
vop_seek {
IN struct vnode *vp;
- IN off_t oldoff;
- IN off_t newoff;
+ IN off_t oldoffset;
+ IN int whence;
+ IN off_t givenoffset;
+ OUT off_t *newoffset;
IN kauth_cred_t cred;
};
Index: sys/miscfs/deadfs/dead_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/deadfs/dead_vnops.c,v
retrieving revision 1.39
diff -u -p -r1.39 dead_vnops.c
--- sys/miscfs/deadfs/dead_vnops.c 14 May 2006 21:31:52 -0000 1.39
+++ sys/miscfs/deadfs/dead_vnops.c 26 Sep 2006 16:59:34 -0000
@@ -64,7 +64,7 @@ int dead_ioctl(void *);
int dead_poll(void *);
#define dead_mmap genfs_badop
#define dead_fsync genfs_nullop
-#define dead_seek genfs_nullop
+#define dead_seek genfs_nullop /* no size -> genfs_nullop allowed */
#define dead_remove genfs_badop
#define dead_link genfs_badop
#define dead_rename genfs_badop
Index: sys/miscfs/genfs/genfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/genfs/genfs_vnops.c,v
retrieving revision 1.129
diff -u -p -r1.129 genfs_vnops.c
--- sys/miscfs/genfs/genfs_vnops.c 15 Sep 2006 15:51:12 -0000 1.129
+++ sys/miscfs/genfs/genfs_vnops.c 26 Sep 2006 16:59:34 -0000
@@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: genfs_vnops.
#include <sys/mman.h>
#include <sys/file.h>
#include <sys/kauth.h>
+#include <sys/unistd.h>
#include <miscfs/genfs/genfs.h>
#include <miscfs/genfs/genfs_node.h>
@@ -90,15 +91,55 @@ genfs_seek(void *v)
{
struct vop_seek_args /* {
struct vnode *a_vp;
- off_t a_oldoff;
- off_t a_newoff;
- kauth_cred_t cred;
- } */ *ap = v;
+ off_t a_oldoffset;
+ int a_whence;
+ off_t a_givenoffset;
+ off_t *a_newoffset;
+ kauth_cred_t a_cred;
+ }; */ *ap = v;
+ off_t newoffset;
+ struct vattr vattr;
+ int error;
+
+ error = VOP_GETATTR(ap->a_vp, &vattr, ap->a_cred, curlwp);
+ if (error)
+ return error;
+
+ /* initialise return value with old offset */
+ newoffset = ap->a_oldoffset;
+ switch (ap->a_whence) {
+ case SEEK_CUR:
+ newoffset = ap->a_oldoffset + ap->a_givenoffset;
+ break;
+ case SEEK_END:
+ newoffset = ap->a_givenoffset + vattr.va_size;
+ break;
+ case SEEK_SET:
+ newoffset = ap->a_givenoffset;
+ break;
+ case SEEK_DATA:
+ /* if in the file space, there is one data block */
+ if (ap->a_givenoffset >= vattr.va_size)
+ return ENXIO;
+ newoffset = ap->a_givenoffset;
+ break;
+ case SEEK_HOLE:
+ /* there exists one virtual hole at the end of the file */
+ if (ap->a_givenoffset > vattr.va_size)
+ return ENXIO;
+ newoffset = vattr.va_size;
+ break;
+ default:
+ return EINVAL;
+ }
- if (ap->a_newoff < 0)
- return (EINVAL);
+ if (newoffset < 0)
+ return EINVAL;
- return (0);
+ if (ap->a_newoffset)
+ *(ap->a_newoffset) = newoffset;
+
+ return 0;
}
int
Index: sys/miscfs/kernfs/kernfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/kernfs/kernfs_vnops.c,v
retrieving revision 1.125
diff -u -p -r1.125 kernfs_vnops.c
--- sys/miscfs/kernfs/kernfs_vnops.c 23 Jun 2006 20:54:21 -0000 1.125
+++ sys/miscfs/kernfs/kernfs_vnops.c 26 Sep 2006 16:59:34 -0000
@@ -190,7 +190,7 @@ int kernfs_ioctl(void *);
#define kernfs_poll genfs_poll
#define kernfs_revoke genfs_revoke
#define kernfs_fsync genfs_nullop
-#define kernfs_seek genfs_nullop
+#define kernfs_seek genfs_seek
#define kernfs_remove genfs_eopnotsupp
int kernfs_link(void *);
#define kernfs_rename genfs_eopnotsupp
Index: sys/miscfs/procfs/procfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_vnops.c,v
retrieving revision 1.134
diff -u -p -r1.134 procfs_vnops.c
--- sys/miscfs/procfs/procfs_vnops.c 20 Sep 2006 08:09:05 -0000 1.134
+++ sys/miscfs/procfs/procfs_vnops.c 26 Sep 2006 16:59:35 -0000
@@ -184,7 +184,7 @@ int procfs_setattr(void *);
#define procfs_poll genfs_poll
#define procfs_revoke genfs_revoke
#define procfs_fsync genfs_nullop
-#define procfs_seek genfs_nullop
+#define procfs_seek genfs_seek
#define procfs_remove genfs_eopnotsupp
int procfs_link(void *);
#define procfs_rename genfs_eopnotsupp
Index: sys/miscfs/specfs/specdev.h
===================================================================
RCS file: /cvsroot/src/sys/miscfs/specfs/specdev.h,v
retrieving revision 1.30
diff -u -p -r1.30 specdev.h
--- sys/miscfs/specfs/specdev.h 14 May 2006 21:32:21 -0000 1.30
+++ sys/miscfs/specfs/specdev.h 26 Sep 2006 16:59:35 -0000
@@ -120,7 +120,7 @@ int spec_kqfilter(void *);
#define spec_revoke genfs_revoke
#define spec_mmap genfs_mmap
int spec_fsync(void *);
-#define spec_seek genfs_nullop /* XXX should query device */
+#define spec_seek genfs_seek /* XXX should query device */
#define spec_remove genfs_badop
#define spec_link genfs_badop
#define spec_rename genfs_badop
Index: sys/sys/fcntl.h
===================================================================
RCS file: /cvsroot/src/sys/sys/fcntl.h,v
retrieving revision 1.33
diff -u -p -r1.33 fcntl.h
--- sys/sys/fcntl.h 29 Nov 2005 22:52:02 -0000 1.33
+++ sys/sys/fcntl.h 26 Sep 2006 16:59:35 -0000
@@ -247,15 +247,21 @@ struct flock {
#endif
/* Always ensure that these are consistent with <stdio.h> and <unistd.h>! */
-#ifndef SEEK_SET
+#ifndef SEEK_SET
#define SEEK_SET 0 /* set file offset to offset */
#endif
-#ifndef SEEK_CUR
+#ifndef SEEK_CUR
#define SEEK_CUR 1 /* set file offset to current plus offset */
#endif
-#ifndef SEEK_END
+#ifndef SEEK_END
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
+#ifndef SEEK_DATA
+#define SEEK_DATA 3 /* Set file pointer to next data past offset */
+#endif
+#ifndef SEEK_HOLE
+#define SEEK_HOLE 4 /* Set file pointer to next hole past offset */
+#endif
/*
* posix_advise advisories.
Index: sys/sys/unistd.h
===================================================================
RCS file: /cvsroot/src/sys/sys/unistd.h,v
retrieving revision 1.35
diff -u -p -r1.35 unistd.h
--- sys/sys/unistd.h 14 Aug 2006 18:17:48 -0000 1.35
+++ sys/sys/unistd.h 26 Sep 2006 16:59:35 -0000
@@ -108,6 +108,8 @@
#define SEEK_SET 0 /* set file offset to offset */
#define SEEK_CUR 1 /* set file offset to current plus offset */
#define SEEK_END 2 /* set file offset to EOF plus offset */
+#define SEEK_DATA 3 /* Set file pointer to next data past offset */
+#define SEEK_HOLE 4 /* Set file pointer to next hole past offset */
#if defined(_NETBSD_SOURCE)
/* whence values for lseek(2); renamed by POSIX 1003.1 */
Index: sys/sys/vnode_if.h
===================================================================
RCS file: /cvsroot/src/sys/sys/vnode_if.h,v
retrieving revision 1.62
diff -u -p -r1.62 vnode_if.h
--- sys/sys/vnode_if.h 13 Jul 2006 12:00:26 -0000 1.62
+++ sys/sys/vnode_if.h 26 Sep 2006 16:59:35 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vnode_if.h,v 1.62 2006/07/13 12:00:26 martin Exp $ */
+/* $NetBSD$ */
/*
* Warning: DO NOT EDIT! This file is automatically generated!
@@ -224,12 +224,14 @@ int VOP_FSYNC(struct vnode *, kauth_cred
struct vop_seek_args {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
- off_t a_oldoff;
- off_t a_newoff;
+ off_t a_oldoffset;
+ int a_whence;
+ off_t a_givenoffset;
+ off_t *a_newoffset;
kauth_cred_t a_cred;
};
extern const struct vnodeop_desc vop_seek_desc;
-int VOP_SEEK(struct vnode *, off_t, off_t, kauth_cred_t);
+int VOP_SEEK(struct vnode *, off_t, int, off_t, off_t *, kauth_cred_t);
struct vop_remove_args {
const struct vnodeop_desc *a_desc;
Index: sys/ufs/files.ufs
===================================================================
RCS file: /cvsroot/src/sys/ufs/files.ufs,v
retrieving revision 1.15
diff -u -p -r1.15 files.ufs
--- sys/ufs/files.ufs 20 Jul 2006 23:49:07 -0000 1.15
+++ sys/ufs/files.ufs 26 Sep 2006 16:59:36 -0000
@@ -60,3 +60,5 @@ file ufs/ufs/ufs_lookup.c ffs | lfs | m
file ufs/ufs/ufs_quota.c quota & (ffs | lfs | mfs)
file ufs/ufs/ufs_vfsops.c ffs | lfs | mfs | ext2fs
file ufs/ufs/ufs_vnops.c ffs | lfs | mfs | ext2fs
+file ufs/ufs/ufs_seek.c ffs | lfs | mfs | ext2fs
+
Index: sys/ufs/ufs/ufs_extern.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_extern.h,v
retrieving revision 1.49
diff -u -p -r1.49 ufs_extern.h
--- sys/ufs/ufs/ufs_extern.h 14 May 2006 21:33:39 -0000 1.49
+++ sys/ufs/ufs/ufs_extern.h 26 Sep 2006 16:59:36 -0000
@@ -83,7 +83,7 @@ int ufs_readlink(void *);
int ufs_remove(void *);
int ufs_rename(void *);
int ufs_rmdir(void *);
-#define ufs_seek genfs_seek
+int ufs_seek(void *);
#define ufs_poll genfs_poll
int ufs_setattr(void *);
int ufs_strategy(void *);
--pWyiEgJYm5f9v55/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sparsecopy.c"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
#define BLOB_SIZE 32*1024
char *blob[BLOB_SIZE];
int fdi, fdo;
#define MIN(a,b) ((a) < (b) ? (a) : (b))
void filedatacopy(off_t start, off_t len)
{
off_t cplen;
printf("copy from %"PRIu64" to %"PRIu64"\n", start, start+len);
cplen = MIN(BLOB_SIZE, len);
while (len) {
pread(fdi, blob, cplen, start);
pwrite(fdo, blob, cplen, start);
start += cplen;
len -= cplen;
cplen = MIN(BLOB_SIZE, len);
}
}
int main(int argc, char **argv)
{
off_t extent, data, hole, pos;
struct stat stat;
int error;
char *filen;
if (argc != 2) {
printf("Use %s fname\n", argv[0]);
return EXIT_FAILURE;
}
filen = argv[1];
if ((fdi = open(filen, O_RDONLY, 0)) == -1) {
printf("Can't open my input file\n");
return EXIT_FAILURE;
}
if (fstat(fdi, &stat)) {
printf("can't stat file\n");
return EXIT_FAILURE;
}
if ((fdo = open("file-out", O_WRONLY | O_TRUNC | O_CREAT, 0666)) == -1) {
printf("Can't open output file\n");
return EXIT_FAILURE;
}
/* sparse copy routine */
extent = stat.st_size;
error= 0;
pos = 0;
while (pos < extent) {
data = lseek(fdi, pos, SEEK_DATA);
hole = lseek(fdi, data, SEEK_HOLE);
printf("DATA = %"PRIi64"\n", data);
printf("HOLE = %"PRIi64"\n", hole);
if (data == -1) {
error = errno;
break;
}
filedatacopy(data, hole-data);
pos = hole;
}
if (error && (error != ENXIO)) {
printf("error occured in transfer\n");
return EXIT_FAILURE;
}
close(fdi);
close(fdo);
return EXIT_SUCCESS;
}
--pWyiEgJYm5f9v55/--
--f2QGlHpHGjS2mn6Y
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (NetBSD)
iQEVAwUBRRmBHIKcNwBDyKpoAQJb5ggAxOSw24+MqaWyr216mxA/1L4IYTauBl2a
Ldq7Azp55Ta5VdkDwjGbjdqeSJjrX2fYS9RcbHDoCQ2GJG5PXVKp9C7TiECd3Buk
tlDhv4H/2trwUHgM66u00+jftk1RslfysDVEonzdhmpuqOM1mc1AW431dc9MHZHU
3Z8cROEKwHt4NihiNsZ/NGJ1LGOJScexuDYm5jxhLNF2cbzqSPTotEb2LPvX3qj3
8OgK0wz5G2qVhTVbKBa9ADfdWmbPIj5peFeZh0Uxtslg578H5VO+sYlXJas7MJTX
RKwKnukORXa7oXA1O/JwXbylQTZA238YcQvfpLxBwxC0NvlKgJD/3A==
=ymjk
-----END PGP SIGNATURE-----
--f2QGlHpHGjS2mn6Y--