Add SEEK_DATA/SEEK_HOLE to lseek()/llseek()
[zfs.git] / module / zfs / zpl_file.c
index c6d97db..ebae6bf 100644 (file)
@@ -235,6 +235,28 @@ zpl_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
        return (wrote);
 }
 
+static loff_t
+zpl_llseek(struct file *filp, loff_t offset, int whence)
+{
+#if defined(SEEK_HOLE) && defined(SEEK_DATA)
+       if (whence == SEEK_DATA || whence == SEEK_HOLE) {
+               struct inode *ip = filp->f_mapping->host;
+               loff_t maxbytes = ip->i_sb->s_maxbytes;
+               loff_t error;
+
+               spl_inode_lock(ip);
+               error = -zfs_holey(ip, whence, &offset);
+               if (error == 0)
+                       error = lseek_execute(filp, ip, offset, maxbytes);
+               spl_inode_unlock(ip);
+
+               return (error);
+       }
+#endif /* SEEK_HOLE && SEEK_DATA */
+
+       return generic_file_llseek(filp, offset, whence);
+}
+
 /*
  * It's worth taking a moment to describe how mmap is implemented
  * for zfs because it differs considerably from other Linux filesystems.
@@ -464,7 +486,7 @@ const struct address_space_operations zpl_address_space_operations = {
 const struct file_operations zpl_file_operations = {
        .open           = zpl_open,
        .release        = zpl_release,
-       .llseek         = generic_file_llseek,
+       .llseek         = zpl_llseek,
        .read           = zpl_read,
        .write          = zpl_write,
        .mmap           = zpl_mmap,