vfs: export lseek_execute() to modules
authorJie Liu <jeff.liu@oracle.com>
Tue, 25 Jun 2013 04:02:13 +0000 (12:02 +0800)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 3 Jul 2013 12:23:27 +0000 (16:23 +0400)
For those file systems(btrfs/ext4/ocfs2/tmpfs) that support
SEEK_DATA/SEEK_HOLE functions, we end up handling the similar
matter in lseek_execute() to update the current file offset
to the desired offset if it is valid, ceph also does the
simliar things at ceph_llseek().

To reduce the duplications, this patch make lseek_execute()
public accessible so that we can call it directly from the
underlying file systems.

Thanks Dave Chinner for this suggestion.

[AV: call it vfs_setpos(), don't bring the removed 'inode' argument back]

v2->v1:
- Add kernel-doc comments for lseek_execute()
- Call lseek_execute() in ceph->llseek()

Signed-off-by: Jie Liu <jeff.liu@oracle.com>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Chris Mason <chris.mason@fusionio.com>
Cc: Josef Bacik <jbacik@fusionio.com>
Cc: Ben Myers <bpm@sgi.com>
Cc: Ted Tso <tytso@mit.edu>
Cc: Hugh Dickins <hughd@google.com>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Sage Weil <sage@inktank.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/btrfs/file.c
fs/ceph/file.c
fs/ext4/file.c
fs/ocfs2/file.c
fs/read_write.c
fs/xfs/xfs_file.c
include/linux/fs.h
mm/shmem.c

index 4205ba752d40ccbadfb0fa0b1f053b1022c553c0..89da56a58b635c9bf80197c0cf32e2dc3f698442 100644 (file)
@@ -2425,20 +2425,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence)
                }
        }
 
-       if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) {
-               offset = -EINVAL;
-               goto out;
-       }
-       if (offset > inode->i_sb->s_maxbytes) {
-               offset = -EINVAL;
-               goto out;
-       }
-
-       /* Special lock needed here? */
-       if (offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
+       offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
 out:
        mutex_unlock(&inode->i_mutex);
        return offset;
index 656e169074305f12d34859ca07ee710c4c1a954d..16c989d3e23c762e52904419a81beae943332ea0 100644 (file)
@@ -866,16 +866,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
                break;
        }
 
-       if (offset < 0 || offset > inode->i_sb->s_maxbytes) {
-               offset = -EINVAL;
-               goto out;
-       }
-
-       /* Special lock needed here? */
-       if (offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
+       offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
 
 out:
        mutex_unlock(&inode->i_mutex);
index b1b4d51b5d86b4e54c179ddce5f5b574238b3629..469361dbe619b4e1eae9b2ed4596753fb0f4ff00 100644 (file)
@@ -494,17 +494,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
        if (dataoff > isize)
                return -ENXIO;
 
-       if (dataoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
-               return -EINVAL;
-       if (dataoff > maxsize)
-               return -EINVAL;
-
-       if (dataoff != file->f_pos) {
-               file->f_pos = dataoff;
-               file->f_version = 0;
-       }
-
-       return dataoff;
+       return vfs_setpos(file, dataoff, maxsize);
 }
 
 /*
@@ -580,17 +570,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
        if (holeoff > isize)
                holeoff = isize;
 
-       if (holeoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
-               return -EINVAL;
-       if (holeoff > maxsize)
-               return -EINVAL;
-
-       if (holeoff != file->f_pos) {
-               file->f_pos = holeoff;
-               file->f_version = 0;
-       }
-
-       return holeoff;
+       return vfs_setpos(file, holeoff, maxsize);
 }
 
 /*
index 8a38714f1d92ec98b197e28e1a06adcce6e6b582..41000f223ca42bb855a57f1cc27f08a28ecccba9 100644 (file)
@@ -2646,17 +2646,7 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence)
                goto out;
        }
 
-       if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
-               ret = -EINVAL;
-       if (!ret && offset > inode->i_sb->s_maxbytes)
-               ret = -EINVAL;
-       if (ret)
-               goto out;
-
-       if (offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
+       offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
 
 out:
        mutex_unlock(&inode->i_mutex);
index 37d16e82b575b9dc9a200f4bbfcb6e89b9e2eabc..122a3846d9e14270a26952e92b25971257ebd82b 100644 (file)
@@ -41,7 +41,19 @@ static inline int unsigned_offsets(struct file *file)
        return file->f_mode & FMODE_UNSIGNED_OFFSET;
 }
 
-static loff_t lseek_execute(struct file *file, loff_t offset, loff_t maxsize)
+/**
+ * vfs_setpos - update the file offset for lseek
+ * @file:      file structure in question
+ * @offset:    file offset to seek to
+ * @maxsize:   maximum file size
+ *
+ * This is a low-level filesystem helper for updating the file offset to
+ * the value specified by @offset if the given offset is valid and it is
+ * not equal to the current file offset.
+ *
+ * Return the specified offset on success and -EINVAL on invalid offset.
+ */
+loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
 {
        if (offset < 0 && !unsigned_offsets(file))
                return -EINVAL;
@@ -54,6 +66,7 @@ static loff_t lseek_execute(struct file *file, loff_t offset, loff_t maxsize)
        }
        return offset;
 }
+EXPORT_SYMBOL(vfs_setpos);
 
 /**
  * generic_file_llseek_size - generic llseek implementation for regular files
@@ -94,7 +107,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
                 * like SEEK_SET.
                 */
                spin_lock(&file->f_lock);
-               offset = lseek_execute(file, file->f_pos + offset, maxsize);
+               offset = vfs_setpos(file, file->f_pos + offset, maxsize);
                spin_unlock(&file->f_lock);
                return offset;
        case SEEK_DATA:
@@ -116,7 +129,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
                break;
        }
 
-       return lseek_execute(file, offset, maxsize);
+       return vfs_setpos(file, offset, maxsize);
 }
 EXPORT_SYMBOL(generic_file_llseek_size);
 
index 0ad2b95fca12fbd215b9eb63f84b2bd7c21b6609..de3dc98f4e8f76067c1e7d0ee4631a8638d87988 100644 (file)
@@ -1268,8 +1268,7 @@ xfs_seek_data(
        }
 
 out:
-       if (offset != file->f_pos)
-               file->f_pos = offset;
+       offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
 
 out_unlock:
        xfs_iunlock_map_shared(ip, lock);
@@ -1377,8 +1376,7 @@ out:
         * situation in particular.
         */
        offset = min_t(loff_t, offset, isize);
-       if (offset != file->f_pos)
-               file->f_pos = offset;
+       offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
 
 out_unlock:
        xfs_iunlock_map_shared(ip, lock);
index a137a73fc1fe1aa826c6602df09daf886ef529e6..bccb1924ec93eda2ae891c7cd1f6ab970ffd6a9d 100644 (file)
@@ -2426,6 +2426,7 @@ extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
 extern loff_t noop_llseek(struct file *file, loff_t offset, int whence);
 extern loff_t no_llseek(struct file *file, loff_t offset, int whence);
+extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence);
 extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
                int whence, loff_t maxsize, loff_t eof);
index f887358dabc557e69618d360a61c8dbb51738b8d..118dfa4952f4dc565fd284c0df6b0d2bd19f4452 100644 (file)
@@ -1798,10 +1798,7 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence)
                }
        }
 
-       if (offset >= 0 && offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
+       offset = vfs_setpos(file, offset, MAX_LFS_FILESIZE);
        mutex_unlock(&inode->i_mutex);
        return offset;
 }