aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/file.c15
-rw-r--r--fs/ceph/file.c11
-rw-r--r--fs/ext4/file.c24
-rw-r--r--fs/ocfs2/file.c12
-rw-r--r--fs/read_write.c19
-rw-r--r--fs/xfs/xfs_file.c6
-rw-r--r--include/linux/fs.h1
-rw-r--r--mm/shmem.c5
8 files changed, 25 insertions, 68 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 4205ba752d40..89da56a58b63 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2425,20 +2425,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence)
2425 } 2425 }
2426 } 2426 }
2427 2427
2428 if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { 2428 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
2429 offset = -EINVAL;
2430 goto out;
2431 }
2432 if (offset > inode->i_sb->s_maxbytes) {
2433 offset = -EINVAL;
2434 goto out;
2435 }
2436
2437 /* Special lock needed here? */
2438 if (offset != file->f_pos) {
2439 file->f_pos = offset;
2440 file->f_version = 0;
2441 }
2442out: 2429out:
2443 mutex_unlock(&inode->i_mutex); 2430 mutex_unlock(&inode->i_mutex);
2444 return offset; 2431 return offset;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 656e16907430..16c989d3e23c 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -866,16 +866,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
866 break; 866 break;
867 } 867 }
868 868
869 if (offset < 0 || offset > inode->i_sb->s_maxbytes) { 869 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
870 offset = -EINVAL;
871 goto out;
872 }
873
874 /* Special lock needed here? */
875 if (offset != file->f_pos) {
876 file->f_pos = offset;
877 file->f_version = 0;
878 }
879 870
880out: 871out:
881 mutex_unlock(&inode->i_mutex); 872 mutex_unlock(&inode->i_mutex);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index b1b4d51b5d86..469361dbe619 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -494,17 +494,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
494 if (dataoff > isize) 494 if (dataoff > isize)
495 return -ENXIO; 495 return -ENXIO;
496 496
497 if (dataoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) 497 return vfs_setpos(file, dataoff, maxsize);
498 return -EINVAL;
499 if (dataoff > maxsize)
500 return -EINVAL;
501
502 if (dataoff != file->f_pos) {
503 file->f_pos = dataoff;
504 file->f_version = 0;
505 }
506
507 return dataoff;
508} 498}
509 499
510/* 500/*
@@ -580,17 +570,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
580 if (holeoff > isize) 570 if (holeoff > isize)
581 holeoff = isize; 571 holeoff = isize;
582 572
583 if (holeoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) 573 return vfs_setpos(file, holeoff, maxsize);
584 return -EINVAL;
585 if (holeoff > maxsize)
586 return -EINVAL;
587
588 if (holeoff != file->f_pos) {
589 file->f_pos = holeoff;
590 file->f_version = 0;
591 }
592
593 return holeoff;
594} 574}
595 575
596/* 576/*
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 8a38714f1d92..41000f223ca4 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2646,17 +2646,7 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence)
2646 goto out; 2646 goto out;
2647 } 2647 }
2648 2648
2649 if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) 2649 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
2650 ret = -EINVAL;
2651 if (!ret && offset > inode->i_sb->s_maxbytes)
2652 ret = -EINVAL;
2653 if (ret)
2654 goto out;
2655
2656 if (offset != file->f_pos) {
2657 file->f_pos = offset;
2658 file->f_version = 0;
2659 }
2660 2650
2661out: 2651out:
2662 mutex_unlock(&inode->i_mutex); 2652 mutex_unlock(&inode->i_mutex);
diff --git a/fs/read_write.c b/fs/read_write.c
index 37d16e82b575..122a3846d9e1 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -41,7 +41,19 @@ static inline int unsigned_offsets(struct file *file)
41 return file->f_mode & FMODE_UNSIGNED_OFFSET; 41 return file->f_mode & FMODE_UNSIGNED_OFFSET;
42} 42}
43 43
44static loff_t lseek_execute(struct file *file, loff_t offset, loff_t maxsize) 44/**
45 * vfs_setpos - update the file offset for lseek
46 * @file: file structure in question
47 * @offset: file offset to seek to
48 * @maxsize: maximum file size
49 *
50 * This is a low-level filesystem helper for updating the file offset to
51 * the value specified by @offset if the given offset is valid and it is
52 * not equal to the current file offset.
53 *
54 * Return the specified offset on success and -EINVAL on invalid offset.
55 */
56loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
45{ 57{
46 if (offset < 0 && !unsigned_offsets(file)) 58 if (offset < 0 && !unsigned_offsets(file))
47 return -EINVAL; 59 return -EINVAL;
@@ -54,6 +66,7 @@ static loff_t lseek_execute(struct file *file, loff_t offset, loff_t maxsize)
54 } 66 }
55 return offset; 67 return offset;
56} 68}
69EXPORT_SYMBOL(vfs_setpos);
57 70
58/** 71/**
59 * generic_file_llseek_size - generic llseek implementation for regular files 72 * 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 * like SEEK_SET. 107 * like SEEK_SET.
95 */ 108 */
96 spin_lock(&file->f_lock); 109 spin_lock(&file->f_lock);
97 offset = lseek_execute(file, file->f_pos + offset, maxsize); 110 offset = vfs_setpos(file, file->f_pos + offset, maxsize);
98 spin_unlock(&file->f_lock); 111 spin_unlock(&file->f_lock);
99 return offset; 112 return offset;
100 case SEEK_DATA: 113 case SEEK_DATA:
@@ -116,7 +129,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
116 break; 129 break;
117 } 130 }
118 131
119 return lseek_execute(file, offset, maxsize); 132 return vfs_setpos(file, offset, maxsize);
120} 133}
121EXPORT_SYMBOL(generic_file_llseek_size); 134EXPORT_SYMBOL(generic_file_llseek_size);
122 135
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 0ad2b95fca12..de3dc98f4e8f 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1268,8 +1268,7 @@ xfs_seek_data(
1268 } 1268 }
1269 1269
1270out: 1270out:
1271 if (offset != file->f_pos) 1271 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
1272 file->f_pos = offset;
1273 1272
1274out_unlock: 1273out_unlock:
1275 xfs_iunlock_map_shared(ip, lock); 1274 xfs_iunlock_map_shared(ip, lock);
@@ -1377,8 +1376,7 @@ out:
1377 * situation in particular. 1376 * situation in particular.
1378 */ 1377 */
1379 offset = min_t(loff_t, offset, isize); 1378 offset = min_t(loff_t, offset, isize);
1380 if (offset != file->f_pos) 1379 offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
1381 file->f_pos = offset;
1382 1380
1383out_unlock: 1381out_unlock:
1384 xfs_iunlock_map_shared(ip, lock); 1382 xfs_iunlock_map_shared(ip, lock);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a137a73fc1fe..bccb1924ec93 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2426,6 +2426,7 @@ extern void
2426file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); 2426file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
2427extern loff_t noop_llseek(struct file *file, loff_t offset, int whence); 2427extern loff_t noop_llseek(struct file *file, loff_t offset, int whence);
2428extern loff_t no_llseek(struct file *file, loff_t offset, int whence); 2428extern loff_t no_llseek(struct file *file, loff_t offset, int whence);
2429extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize);
2429extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence); 2430extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence);
2430extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, 2431extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
2431 int whence, loff_t maxsize, loff_t eof); 2432 int whence, loff_t maxsize, loff_t eof);
diff --git a/mm/shmem.c b/mm/shmem.c
index f887358dabc5..118dfa4952f4 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1798,10 +1798,7 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence)
1798 } 1798 }
1799 } 1799 }
1800 1800
1801 if (offset >= 0 && offset != file->f_pos) { 1801 offset = vfs_setpos(file, offset, MAX_LFS_FILESIZE);
1802 file->f_pos = offset;
1803 file->f_version = 0;
1804 }
1805 mutex_unlock(&inode->i_mutex); 1802 mutex_unlock(&inode->i_mutex);
1806 return offset; 1803 return offset;
1807} 1804}