Skip to contentSkip to conversation

vfs: export lseek_execute() to modules

PATCH In review Jeff Liu 2 participants 3 messages Jun 25, 2013

Subsystems (8)
lore
Share & tools
lore

Jeff Liu

author
#0 lore raw

PATCH v2 1/1 vfs: export lseek_execute() to modules

From: Jie Liu <[email protected]>

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.

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

Cc Dave Chinner <[email protected]>
Cc Al Viro <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Christoph Hellwig <[email protected]>
Cc Chris Mason <[email protected]>
Cc Josef Bacik <[email protected]>
Cc Ben Myers <[email protected]>
Cc Ted Tso <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Mark Fasheh <[email protected]>
Cc Joel Becker <[email protected]>
Cc Sage Weil <[email protected]>
---
 fs/btrfs/file.c    |   15 +--------------
 fs/ceph/file.c     |   11 +----------
 fs/ext4/file.c     |   24 ++----------------------
 fs/ocfs2/file.c    |   12 +-----------
 fs/read_write.c    |   18 ++++++++++++++++--
 fs/xfs/xfs_file.c  |    6 ++----
 include/linux/fs.h |    2 ++
 mm/shmem.c         |    5 +----
 8 files changed, 26 insertions(+), 67 deletions(-)
fs/btrfs/file.c +1 -14
index 4205ba7..a56eced 100644
@@ -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 = lseek_execute(file, inode, offset, inode->i_sb->s_maxbytes);
 out:
 	mutex_unlock(&inode->i_mutex);
 	return offset;
fs/ceph/file.c +1 -10
index 656e169..7cfc94d 100644
@@ -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 = lseek_execute(file, inode, offset, inode->i_sb->s_maxbytes);
 
 out:
 	mutex_unlock(&inode->i_mutex);
fs/ext4/file.c +2 -22
index b1b4d51..f4b6971 100644
@@ -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 lseek_execute(file, inode, 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 lseek_execute(file, inode, holeoff, maxsize);
 }
 
 /*
fs/ocfs2/file.c +1 -11
index ff54014..13af684 100644
@@ -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 = lseek_execute(file, inode, offset, inode->i_sb->s_maxbytes);
 
 out:
 	mutex_unlock(&inode->i_mutex);
fs/read_write.c +16 -2
index 2cefa41..2bf0de9 100644
@@ -41,8 +41,21 @@ static inline int unsigned_offsets(struct file *file)
 	return file->f_mode & FMODE_UNSIGNED_OFFSET;
 }
 
-static loff_t lseek_execute(struct file *file, struct inode *inode,
-		loff_t offset, loff_t maxsize)
+/**
+ * lseek_execute - update the file offset for lseek
+ * @file:	file structure in question
+ * @inode:	inode of the file
+ * @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 lseek_execute(struct file *file, struct inode *inode,
+		     loff_t offset, loff_t maxsize)
 {
 	if (offset < 0 && !unsigned_offsets(file))
 		return -EINVAL;
@@ -55,6 +68,7 @@ static loff_t lseek_execute(struct file *file, struct inode *inode,
 	}
 	return offset;
 }
+EXPORT_SYMBOL(lseek_execute);
 
 /**
  * generic_file_llseek_size - generic llseek implementation for regular files
fs/xfs/xfs_file.c +2 -4
index a5f2042..d052e88 100644
@@ -1270,8 +1270,7 @@ xfs_seek_data(
 	}
 
 out:
-	if (offset != file->f_pos)
-		file->f_pos = offset;
+	offset = lseek_execute(file, inode, offset, inode->i_sb->s_maxbytes);
 
 out_unlock:
 	xfs_iunlock_map_shared(ip, lock);
@@ -1379,8 +1378,7 @@ out:
 	 * situation in particular.
 	 */
 	offset = min_t(loff_t, offset, isize);
-	if (offset != file->f_pos)
-		file->f_pos = offset;
+	offset = lseek_execute(file, inode, offset, inode->i_sb->s_maxbytes);
 
 out_unlock:
 	xfs_iunlock_map_shared(ip, lock);
include/linux/fs.h +2 -0
index 65c2be2..00becde 100644
@@ -2419,6 +2419,8 @@ 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 lseek_execute(struct file *file, struct inode *inode,
+			    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);
mm/shmem.c +1 -4
index 5e6a842..47ffb4a 100644
@@ -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 = lseek_execute(file, inode, offset, MAX_LFS_FILESIZE);
 	mutex_unlock(&inode->i_mutex);
 	return offset;
 }
Signature · 7 lines
1.7.9.5

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#1 lore raw
Quoted 11 lines · Jeff Liu

From: Jie Liu <[email protected]>

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.

Umm... I like it, but it needs changes:
* inode argument of lseek_execute() is pointless (and killed
off in vfs.git, actually)
* I'm really not happy about the name of that function. For
a static it's kinda-sort tolerable, but for something global, let alone exported...

I've put a modified variant into #for-next; could you check if you are still OK with it?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#2 lore raw
Quoted 20 lines · Al Viro
Quoted 11 lines · Jeff Liu

From: Jie Liu <[email protected]>

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.

Umm... I like it, but it needs changes:
* inode argument of lseek_execute() is pointless (and killed
off in vfs.git, actually)
* I'm really not happy about the name of that function. For
a static it's kinda-sort tolerable, but for something global, let alone exported...

Quoted 2 lines

I've put a modified variant into #for-next; could you check if you are still OK with it?

Yep, I'm ok with vfs_setpos().

Thanks,
-Jeff

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>