X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzfs_vnops.c;h=db5d3856a6aced6c51b0b5f2886c56d6fb7dfd6b;hb=8170d281263e52ff33d7fba93ab625196844df36;hp=3b671b4acd42b58fa5cc7df54ccf0c9cbbd1ad2a;hpb=c99c90015ece64746e20b74245caca41d1dbefe1;p=zfs.git diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 3b671b4..db5d385 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -240,6 +240,68 @@ zfs_close(struct inode *ip, int flag, cred_t *cr) } EXPORT_SYMBOL(zfs_close); +#if defined(SEEK_HOLE) && defined(SEEK_DATA) +/* + * Lseek support for finding holes (cmd == SEEK_HOLE) and + * data (cmd == SEEK_DATA). "off" is an in/out parameter. + */ +static int +zfs_holey_common(struct inode *ip, int cmd, loff_t *off) +{ + znode_t *zp = ITOZ(ip); + uint64_t noff = (uint64_t)*off; /* new offset */ + uint64_t file_sz; + int error; + boolean_t hole; + + file_sz = zp->z_size; + if (noff >= file_sz) { + return (ENXIO); + } + + if (cmd == SEEK_HOLE) + hole = B_TRUE; + else + hole = B_FALSE; + + error = dmu_offset_next(ZTOZSB(zp)->z_os, zp->z_id, hole, &noff); + + /* end of file? */ + if ((error == ESRCH) || (noff > file_sz)) { + /* + * Handle the virtual hole at the end of file. + */ + if (hole) { + *off = file_sz; + return (0); + } + return (ENXIO); + } + + if (noff < *off) + return (error); + *off = noff; + return (error); +} + +int +zfs_holey(struct inode *ip, int cmd, loff_t *off) +{ + znode_t *zp = ITOZ(ip); + zfs_sb_t *zsb = ITOZSB(ip); + int error; + + ZFS_ENTER(zsb); + ZFS_VERIFY_ZP(zp); + + error = zfs_holey_common(ip, cmd, off); + + ZFS_EXIT(zsb); + return (error); +} +EXPORT_SYMBOL(zfs_holey); +#endif /* SEEK_HOLE && SEEK_DATA */ + #if defined(_KERNEL) /* * When a file is memory mapped, we must keep the IO data synchronized @@ -2037,7 +2099,7 @@ zfs_readdir(struct inode *ip, void *dirent, filldir_t filldir, objnum = ZFS_DIRENT_OBJ(zap.za_first_integer); } done = filldir(dirent, zap.za_name, strlen(zap.za_name), - zap_cursor_serialize(&zc), objnum, 0); + *pos, objnum, ZFS_DIRENT_TYPE(zap.za_first_integer)); if (done) { break; }