Hello List,

I am trying to fetch the data/hole info of a sparse file through the 
lseek(SEEK_HOLE/SEEK_DATA)
stuff, the result of fpathconf(..., _PC_MIN_HOLE_SIZE) is ok, so I think this 
interface is supported
on my testing ZFS, but SEEK_HOLE always return the sparse file total size 
instead of the desired
first hole start offset.

The whole process was shown as following, Could anyone give any hints?

Create a sparse file("sparse2") as below, SEEK_HOLE should returns *ZERO* and 
SEEK_DATA should
returns 40960 IMHO:
bash-3.00@ python -c "f=open('sparse2', 'w'); f.seek(40960); f.write('BYE'); 
f.close()"

A tiny program to examine the hole start offset of file "sparse2".
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

int
main(int argc, char *argv[])
{
        int ret = 0, fd;
        off_t data_pos, hole_pos;
        const char *filename = NULL;

        if (argc != 2) {
                fprintf(stderr, "Usage: %s file\n", argv[0]);
                return 1;
        }

        filename = strdup(argv[1]);
        if (!filename) {
                perror("strdup");
                return -1;
        }

        fd = open(filename, O_RDONLY);
        if (fd < 0) {
                perror("open");
                ret = -1;
                goto out;
        }

        if (fpathconf(fd, _PC_MIN_HOLE_SIZE) < 0) {
                fprintf(stderr, "The underlying filesystem does not support 
SEEK_HOLE.\n");
                goto out;
        }

        hole_pos = lseek(fd, (off_t)0, SEEK_HOLE);
        if (hole_pos < 0) {
                if (errno == EINVAL || errno == ENOTSUP) {
                        fprintf(stderr, "SEEK_HOLE does not support on OS or 
filesystem.\n");
                        goto out;
                }

                perror("lseek");
                ret = -1;
                goto out;
        }

        if (hole_pos == 0)
                fprintf(stderr, "Oh, no!! hole start at offset 0?\n");

        if (hole_pos > 0)
                fprintf(stderr, "detected a real hole at: %d.\n", hole_pos);

out:
        free(filename);
        lseek(fd, (off_t)0, SEEK_SET);
                        
        return 0;       
}

My test env:
============
bash-3.00# uname -a
SunOS unknown 5.10 Generic_142910-17 i86pc i386 i86pc

man zfs(1):
SunOS 5.10          Last change: 11 Jun 2010

bash-3.00# zfs list
NAME                        USED  AVAIL  REFER  MOUNTPOINT
...
...
rpool/export/home           120K   139G   120K  /export/home
...

"sparse2" located at "/export/home":
bash-3.00# zdb -dddddd rpool/export/home
Object  lvl   iblk   dblk  dsize  lsize   %full  type
104    1    16K  40.5K  40.5K  40.5K  100.00  ZFS plain file
264   bonus  ZFS znode
dnode flags: USED_BYTES USERUSED_ACCOUNTED
dnode maxblkid: 0
path    /sparse2
uid     0
gid     0
atime   Mon Apr 18 14:50:46 2011
mtime   Mon Apr 18 14:50:46 2011
ctime   Mon Apr 18 14:50:46 2011
crtime  Mon Apr 18 14:50:46 2011
gen     497
mode    100600
size    40963
parent  3
links   1
xattr   0
rdev    0x0000000000000000
Indirect blocks:
0 L0 0:1960ce000:a200 a200L/a200P F=1 B=497/497

segment [0000000000000000, 000000000000a200) size 40.5K

bash-3.00# zdb -R rpool/export/home 0:1960ce000:a200
.....
009ff0:  0000000000000000  0000000000000000  ................
00a000:  0000000000455942  0000000000000000  BYE.............
00a010:  0000000000000000  0000000000000000  ................
....
...

Any comments are appreciated!

Thanks,
-Jeff
_______________________________________________
zfs-discuss mailing list
zfs-discuss@opensolaris.org
http://mail.opensolaris.org/mailman/listinfo/zfs-discuss

Reply via email to