Commit 46a1c2c7 authored by Jie Liu's avatar Jie Liu Committed by Al Viro

vfs: export lseek_execute() to modules

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: default avatarJie 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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 2142914e
...@@ -2425,20 +2425,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence) ...@@ -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 = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
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;
}
out: out:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
return offset; return offset;
......
...@@ -866,16 +866,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence) ...@@ -866,16 +866,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
break; break;
} }
if (offset < 0 || offset > inode->i_sb->s_maxbytes) { offset = vfs_setpos(file, 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;
}
out: out:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
......
...@@ -494,17 +494,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) ...@@ -494,17 +494,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
if (dataoff > isize) if (dataoff > isize)
return -ENXIO; return -ENXIO;
if (dataoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) return vfs_setpos(file, dataoff, maxsize);
return -EINVAL;
if (dataoff > maxsize)
return -EINVAL;
if (dataoff != file->f_pos) {
file->f_pos = dataoff;
file->f_version = 0;
}
return dataoff;
} }
/* /*
...@@ -580,17 +570,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) ...@@ -580,17 +570,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
if (holeoff > isize) if (holeoff > isize)
holeoff = isize; holeoff = isize;
if (holeoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) return vfs_setpos(file, holeoff, maxsize);
return -EINVAL;
if (holeoff > maxsize)
return -EINVAL;
if (holeoff != file->f_pos) {
file->f_pos = holeoff;
file->f_version = 0;
}
return holeoff;
} }
/* /*
......
...@@ -2646,17 +2646,7 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence) ...@@ -2646,17 +2646,7 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence)
goto out; goto out;
} }
if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
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;
}
out: out:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
......
...@@ -41,7 +41,19 @@ static inline int unsigned_offsets(struct file *file) ...@@ -41,7 +41,19 @@ static inline int unsigned_offsets(struct file *file)
return file->f_mode & FMODE_UNSIGNED_OFFSET; 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)) if (offset < 0 && !unsigned_offsets(file))
return -EINVAL; return -EINVAL;
...@@ -54,6 +66,7 @@ static loff_t lseek_execute(struct file *file, loff_t offset, loff_t maxsize) ...@@ -54,6 +66,7 @@ static loff_t lseek_execute(struct file *file, loff_t offset, loff_t maxsize)
} }
return offset; return offset;
} }
EXPORT_SYMBOL(vfs_setpos);
/** /**
* generic_file_llseek_size - generic llseek implementation for regular files * 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, ...@@ -94,7 +107,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
* like SEEK_SET. * like SEEK_SET.
*/ */
spin_lock(&file->f_lock); 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); spin_unlock(&file->f_lock);
return offset; return offset;
case SEEK_DATA: case SEEK_DATA:
...@@ -116,7 +129,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence, ...@@ -116,7 +129,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
break; break;
} }
return lseek_execute(file, offset, maxsize); return vfs_setpos(file, offset, maxsize);
} }
EXPORT_SYMBOL(generic_file_llseek_size); EXPORT_SYMBOL(generic_file_llseek_size);
......
...@@ -1268,8 +1268,7 @@ xfs_seek_data( ...@@ -1268,8 +1268,7 @@ xfs_seek_data(
} }
out: out:
if (offset != file->f_pos) offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
file->f_pos = offset;
out_unlock: out_unlock:
xfs_iunlock_map_shared(ip, lock); xfs_iunlock_map_shared(ip, lock);
...@@ -1377,8 +1376,7 @@ xfs_seek_hole( ...@@ -1377,8 +1376,7 @@ xfs_seek_hole(
* situation in particular. * situation in particular.
*/ */
offset = min_t(loff_t, offset, isize); offset = min_t(loff_t, offset, isize);
if (offset != file->f_pos) offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
file->f_pos = offset;
out_unlock: out_unlock:
xfs_iunlock_map_shared(ip, lock); xfs_iunlock_map_shared(ip, lock);
......
...@@ -2426,6 +2426,7 @@ extern void ...@@ -2426,6 +2426,7 @@ extern void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); 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 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 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(struct file *file, loff_t offset, int whence);
extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
int whence, loff_t maxsize, loff_t eof); int whence, loff_t maxsize, loff_t eof);
......
...@@ -1798,10 +1798,7 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence) ...@@ -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) { offset = vfs_setpos(file, offset, MAX_LFS_FILESIZE);
file->f_pos = offset;
file->f_version = 0;
}
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
return offset; return offset;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment