mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-26 18:43:33 -05:00
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: 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>
This commit is contained in:
parent
2142914e3e
commit
46a1c2c7ae
8 changed files with 25 additions and 68 deletions
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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,
|
||||||
* 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,
|
||||||
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(
|
||||||
}
|
}
|
||||||
|
|
||||||
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 @@ out:
|
||||||
* 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
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue