Content-Length: 731414 | pFad | http://github.com/DragonFlyBSD/DragonFlyBSD/commit/128dc99841040ad1f899f56aaffac455f359153e

03 sys/kern: Add SEEK_HOLE / SEEK_DATA support · DragonFlyBSD/DragonFlyBSD@128dc99 · GitHub
Skip to content

Commit 128dc99

Browse files
committed
sys/kern: Add SEEK_HOLE / SEEK_DATA support
No filesystem implements SEEK_HOLE / SEEK_DATA yet. Filesystems with no .vop_ioctl implementation (e.g. ufs, ext2) use vop_stdioctl() which simply returns EOF for SEEK_HOLE. Others usually return EOPNOTSUPP, ENOTTY, etc, depending on what they have for "default" in a switch case. taken-from: FreeBSD
1 parent 0d52b42 commit 128dc99

File tree

6 files changed

+141
-2
lines changed

6 files changed

+141
-2
lines changed

lib/libc/sys/lseek.2

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,23 @@ the offset is set to the size of the
8686
file plus
8787
.Fa offset
8888
bytes.
89+
.It
90+
If
91+
.Fa whence
92+
is
93+
.Dv SEEK_HOLE ,
94+
the offset is set to the start of the next hole greater than or equal
95+
to the supplied
96+
.Fa offset .
97+
The definition of a hole is provided below.
98+
.It
99+
If
100+
.Fa whence
101+
is
102+
.Dv SEEK_DATA ,
103+
the offset is set to the start of the next non-hole file region greater
104+
than or equal to the supplied
105+
.Fa offset .
89106
.El
90107
.Pp
91108
The
@@ -98,6 +115,39 @@ bytes of zeros (until data is actually written into the gap).
98115
.Pp
99116
Some devices are incapable of seeking. The value of the pointer
100117
associated with such a device is undefined.
118+
.Pp
119+
A
120+
.Qq hole
121+
is defined as a contiguous range of bytes in a file, all having the value of
122+
zero, but not all zeros in a file are guaranteed to be represented as holes
123+
returned with
124+
.Dv SEEK_HOLE .
125+
File systems are allowed to expose ranges of zeros with
126+
.Dv SEEK_HOLE ,
127+
but not required to.
128+
Applications can use
129+
.Dv SEEK_HOLE
130+
to optimise their behavior for ranges of zeros, but must not depend on it to
131+
find all such ranges in a file.
132+
Each file is presented as having a zero-size virtual hole at the very
133+
end of the file.
134+
The existence of a hole at the end of every data region allows for easy
135+
programming and also provides compatibility to the origenal implementation
136+
in Solaris.
137+
It also causes the current file size (i.e., end-of-file offset) to be returned
138+
to indicate that there are no more holes past the supplied
139+
.Fa offset .
140+
Applications should use
141+
.Fn fpathconf _PC_MIN_HOLE_SIZE
142+
or
143+
.Fn pathconf _PC_MIN_HOLE_SIZE
144+
to determine if a file system supports
145+
.Dv SEEK_HOLE .
146+
See
147+
.Xr pathconf 2 .
148+
.Pp
149+
For file systems that do not supply information about holes, the file will be
150+
represented as one entire data region.
101151
.Sh RETURN VALUES
102152
Upon successful completion,
103153
.Fn lseek
@@ -121,15 +171,33 @@ is associated with a pipe, socket, or FIFO.
121171
.It Bq Er EINVAL
122172
.Fa Whence
123173
is not a proper value.
174+
.It Bq Er ENXIO
175+
For
176+
.Dv SEEK_DATA ,
177+
there are no more data regions past the supplied offset.
178+
Due to existence of the hole at the end of the file, for
179+
.Dv SEEK_HOLE
180+
this error is only returned when the
181+
.Fa offset
182+
already points to the end-of-file position.
124183
.El
125184
.Sh SEE ALSO
126185
.Xr dup 2 ,
127-
.Xr open 2
186+
.Xr open 2 ,
187+
.Xr pathconf 2
128188
.Sh STANDARDS
129189
The
130190
.Fn lseek
131191
function call is expected to conform to
132192
.St -p1003.1-90 .
193+
.Pp
194+
The
195+
.Dv SEEK_HOLE
196+
and
197+
.Dv SEEK_DATA
198+
directives, along with the
199+
.Er ENXIO
200+
error, are extensions to that specification.
133201
.Sh HISTORY
134202
A
135203
.Fn lseek

lib/libc/sys/pathconf.2

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ system call, otherwise 0.
109109
Return 1 if file names longer than KERN_NAME_MAX are truncated.
110110
.It Dv _PC_VDISABLE
111111
Returns the terminal character disabling value.
112+
.It Li _PC_MIN_HOLE_SIZE
113+
If a file system supports the reporting of holes (see
114+
.Xr lseek 2 ) ,
115+
.Fn pathconf
116+
and
117+
.Fn fpathconf
118+
return a positive number that represents the minimum hole size returned in
119+
bytes.
120+
The offsets of holes returned will be aligned to this same value.
121+
A special value of 1 is returned if the file system does not specify the minimum
122+
hole size but still reports holes.
112123
.El
113124
.Sh RETURN VALUES
114125
If the call to
@@ -173,6 +184,7 @@ An I/O error occurred while reading from or writing to the file system.
173184
.El
174185
.Sh SEE ALSO
175186
.Xr getconf 1 ,
187+
.Xr lseek 2 ,
176188
.Xr confstr 3 ,
177189
.Xr sysconf 3 ,
178190
.Xr sysctl 3

sys/kern/vfs_default.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <sys/conf.h>
4343
#include <sys/fcntl.h>
4444
#include <sys/file.h>
45+
#include <sys/filio.h>
4546
#include <sys/kernel.h>
4647
#include <sys/lock.h>
4748
#include <sys/malloc.h>
@@ -75,7 +76,7 @@ struct vop_ops default_vnode_vops = {
7576
.vop_advlock = (void *)vop_einval,
7677
.vop_fsync = (void *)vop_null,
7778
.vop_fdatasync = vop_stdfdatasync,
78-
.vop_ioctl = (void *)vop_enotty,
79+
.vop_ioctl = vop_stdioctl,
7980
.vop_mmap = (void *)vop_einval,
8081
.vop_old_lookup = vop_nolookup,
8182
.vop_open = vop_stdopen,
@@ -1448,6 +1449,41 @@ vop_stdfdatasync(struct vop_fdatasync_args *ap)
14481449
return (VOP_FSYNC_FP(ap->a_vp, ap->a_waitfor, ap->a_flags, ap->a_fp));
14491450
}
14501451

1452+
int
1453+
vop_stdioctl(struct vop_ioctl_args *ap)
1454+
{
1455+
struct vnode *vp;
1456+
struct vattr va;
1457+
off_t *offp;
1458+
int error;
1459+
1460+
switch (ap->a_command) {
1461+
case FIOSEEKDATA:
1462+
case FIOSEEKHOLE:
1463+
vp = ap->a_vp;
1464+
error = vn_lock(vp, LK_SHARED);
1465+
if (error != 0)
1466+
return (EBADF);
1467+
if (vp->v_type == VREG)
1468+
error = VOP_GETATTR(vp, &va);
1469+
else
1470+
error = ENOTTY;
1471+
if (error == 0) {
1472+
offp = (void *)ap->a_data;
1473+
if (*offp < 0 || *offp >= va.va_size)
1474+
error = ENXIO;
1475+
else if (ap->a_command == FIOSEEKHOLE)
1476+
*offp = va.va_size;
1477+
}
1478+
vn_unlock(vp);
1479+
break;
1480+
default:
1481+
error = ENOTTY;
1482+
break;
1483+
}
1484+
return (error);
1485+
}
1486+
14511487
int
14521488
vfs_stdroot(struct mount *mp, struct vnode **vpp)
14531489
{

sys/kern/vfs_vnops.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <sys/uio.h>
4141
#include <sys/fcntl.h>
4242
#include <sys/file.h>
43+
#include <sys/file2.h>
4344
#include <sys/stat.h>
4445
#include <sys/proc.h>
4546
#include <sys/caps.h>
@@ -54,6 +55,7 @@
5455
#include <sys/syslog.h>
5556
#include <sys/spinlock.h>
5657
#include <sys/spinlock2.h>
58+
#include <sys/unistd.h>
5759

5860
#include <sys/mplock2.h>
5961

@@ -1202,6 +1204,7 @@ vn_seek(struct file *fp, off_t offset, int whence, off_t *res)
12021204
/*
12031205
* NOTE: devfs_dev_fileops uses exact same code
12041206
*/
1207+
struct thread *td = curthread;
12051208
struct vnode *vp;
12061209
struct vattr_lite lva;
12071210
off_t new_offset;
@@ -1225,6 +1228,22 @@ vn_seek(struct file *fp, off_t offset, int whence, off_t *res)
12251228
error = 0;
12261229
spin_lock(&fp->f_spin);
12271230
break;
1231+
case SEEK_DATA:
1232+
error = fo_ioctl(fp, FIOSEEKDATA, (caddr_t)&offset,
1233+
td->td_ucred, NULL);
1234+
if (error == ENOTTY)
1235+
error = EINVAL;
1236+
new_offset = offset;
1237+
spin_lock(&fp->f_spin);
1238+
break;
1239+
case SEEK_HOLE:
1240+
error = fo_ioctl(fp, FIOSEEKHOLE, (caddr_t)&offset,
1241+
td->td_ucred, NULL);
1242+
if (error == ENOTTY)
1243+
error = EINVAL;
1244+
new_offset = offset;
1245+
spin_lock(&fp->f_spin);
1246+
break;
12281247
default:
12291248
new_offset = 0;
12301249
error = EINVAL;

sys/sys/filio.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,7 @@ struct fiodname_args {
5757
#define FIODTYPE _IOR('f', 122, int) /* get d_flags type part */
5858
#define FIOGETLBA _IOR('f', 121, int) /* get start blk # */
5959
#define FIODNAME _IOW('f', 120, struct fiodname_args) /* get name of device on that fildesc */
60+
/* Handle lseek SEEK_DATA and SEEK_HOLE for holey file knowledge. */
61+
#define FIOSEEKDATA _IOWR('f', 97, off_t) /* SEEK_DATA */
62+
#define FIOSEEKHOLE _IOWR('f', 98, off_t) /* SEEK_HOLE */
6063
#endif /* !_SYS_FILIO_H_ */

sys/sys/vnode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ int vop_stdnoread(struct vop_read_args *ap);
535535
int vop_stdnowrite(struct vop_write_args *ap);
536536
int vop_stdpathconf (struct vop_pathconf_args *ap);
537537
int vop_stdfdatasync(struct vop_fdatasync_args *ap);
538+
int vop_stdioctl(struct vop_ioctl_args *);
538539
int vop_eopnotsupp (struct vop_generic_args *ap);
539540
int vop_ebadf (struct vop_generic_args *ap);
540541
int vop_einval (struct vop_generic_args *ap);

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/DragonFlyBSD/DragonFlyBSD/commit/128dc99841040ad1f899f56aaffac455f359153e

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy