fs: handle SEEK_HOLE/SEEK_DATA properly in all fs's that define their own llseek
[deliverable/linux.git] / fs / ceph / file.c
index 0a292459c895aaa2f44cf137dbab787c82809906..0d0eae05598fbab77ed5d390435cb82e49dce6d2 100644 (file)
@@ -768,13 +768,16 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
 
        mutex_lock(&inode->i_mutex);
        __ceph_do_pending_vmtruncate(inode);
-       switch (origin) {
-       case SEEK_END:
+       if (origin != SEEK_CUR || origin != SEEK_SET) {
                ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE);
                if (ret < 0) {
                        offset = ret;
                        goto out;
                }
+       }
+
+       switch (origin) {
+       case SEEK_END:
                offset += inode->i_size;
                break;
        case SEEK_CUR:
@@ -790,6 +793,19 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
                }
                offset += file->f_pos;
                break;
+       case SEEK_DATA:
+               if (offset >= inode->i_size) {
+                       ret = -ENXIO;
+                       goto out;
+               }
+               break;
+       case SEEK_HOLE:
+               if (offset >= inode->i_size) {
+                       ret = -ENXIO;
+                       goto out;
+               }
+               offset = inode->i_size;
+               break;
        }
 
        if (offset < 0 || offset > inode->i_sb->s_maxbytes) {
This page took 0.023826 seconds and 5 git commands to generate.