diff options
Diffstat (limited to 'fs/read_write.c')
| -rw-r--r-- | fs/read_write.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 969a6d9c020b..5cc6924eb158 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -50,6 +50,14 @@ generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin) | |||
| 50 | offset += inode->i_size; | 50 | offset += inode->i_size; |
| 51 | break; | 51 | break; |
| 52 | case SEEK_CUR: | 52 | case SEEK_CUR: |
| 53 | /* | ||
| 54 | * Here we special-case the lseek(fd, 0, SEEK_CUR) | ||
| 55 | * position-querying operation. Avoid rewriting the "same" | ||
| 56 | * f_pos value back to the file because a concurrent read(), | ||
| 57 | * write() or lseek() might have altered it | ||
| 58 | */ | ||
| 59 | if (offset == 0) | ||
| 60 | return file->f_pos; | ||
| 53 | offset += file->f_pos; | 61 | offset += file->f_pos; |
| 54 | break; | 62 | break; |
| 55 | } | 63 | } |
| @@ -105,6 +113,10 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin) | |||
| 105 | offset += i_size_read(file->f_path.dentry->d_inode); | 113 | offset += i_size_read(file->f_path.dentry->d_inode); |
| 106 | break; | 114 | break; |
| 107 | case SEEK_CUR: | 115 | case SEEK_CUR: |
| 116 | if (offset == 0) { | ||
| 117 | retval = file->f_pos; | ||
| 118 | goto out; | ||
| 119 | } | ||
| 108 | offset += file->f_pos; | 120 | offset += file->f_pos; |
| 109 | } | 121 | } |
| 110 | retval = -EINVAL; | 122 | retval = -EINVAL; |
| @@ -115,6 +127,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin) | |||
| 115 | } | 127 | } |
| 116 | retval = offset; | 128 | retval = offset; |
| 117 | } | 129 | } |
| 130 | out: | ||
| 118 | unlock_kernel(); | 131 | unlock_kernel(); |
| 119 | return retval; | 132 | return retval; |
| 120 | } | 133 | } |
