diff options
-rw-r--r-- | fs/btrfs/file.c | 15 | ||||
-rw-r--r-- | fs/ceph/file.c | 11 | ||||
-rw-r--r-- | fs/ext4/file.c | 24 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 12 | ||||
-rw-r--r-- | fs/read_write.c | 19 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 6 | ||||
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | mm/shmem.c | 5 |
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 | } | ||
2442 | out: | 2429 | out: |
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 | ||
880 | out: | 871 | out: |
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 | ||
2661 | out: | 2651 | out: |
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 | ||
44 | static 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 | */ | ||
56 | loff_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 | } |
69 | EXPORT_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 | } |
121 | EXPORT_SYMBOL(generic_file_llseek_size); | 134 | EXPORT_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 | ||
1270 | out: | 1270 | out: |
1271 | if (offset != file->f_pos) | 1271 | offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes); |
1272 | file->f_pos = offset; | ||
1273 | 1272 | ||
1274 | out_unlock: | 1273 | out_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 | ||
1383 | out_unlock: | 1381 | out_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 | |||
2426 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); | 2426 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); |
2427 | extern loff_t noop_llseek(struct file *file, loff_t offset, int whence); | 2427 | extern loff_t noop_llseek(struct file *file, loff_t offset, int whence); |
2428 | extern loff_t no_llseek(struct file *file, loff_t offset, int whence); | 2428 | extern loff_t no_llseek(struct file *file, loff_t offset, int whence); |
2429 | extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize); | ||
2429 | extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence); | 2430 | extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence); |
2430 | extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, | 2431 | extern 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 | } |