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 | } |