diff options
-rw-r--r-- | fs/ext4/dir.c | 2 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/file.c | 44 |
3 files changed, 45 insertions, 2 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 374510f72baa..ece76fb6a40c 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -39,7 +39,7 @@ static int ext4_release_dir(struct inode *inode, | |||
39 | struct file *filp); | 39 | struct file *filp); |
40 | 40 | ||
41 | const struct file_operations ext4_dir_operations = { | 41 | const struct file_operations ext4_dir_operations = { |
42 | .llseek = generic_file_llseek, | 42 | .llseek = ext4_llseek, |
43 | .read = generic_read_dir, | 43 | .read = generic_read_dir, |
44 | .readdir = ext4_readdir, /* we take BKL. needed?*/ | 44 | .readdir = ext4_readdir, /* we take BKL. needed?*/ |
45 | .unlocked_ioctl = ext4_ioctl, | 45 | .unlocked_ioctl = ext4_ioctl, |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 4c5fe37b237d..e1c01552a3df 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2006,6 +2006,7 @@ extern const struct file_operations ext4_dir_operations; | |||
2006 | /* file.c */ | 2006 | /* file.c */ |
2007 | extern const struct inode_operations ext4_file_inode_operations; | 2007 | extern const struct inode_operations ext4_file_inode_operations; |
2008 | extern const struct file_operations ext4_file_operations; | 2008 | extern const struct file_operations ext4_file_operations; |
2009 | extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); | ||
2009 | 2010 | ||
2010 | /* namei.c */ | 2011 | /* namei.c */ |
2011 | extern const struct inode_operations ext4_dir_inode_operations; | 2012 | extern const struct inode_operations ext4_dir_inode_operations; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index ee92b66d4558..5a5c55ddceef 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -130,8 +130,50 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
130 | return dquot_file_open(inode, filp); | 130 | return dquot_file_open(inode, filp); |
131 | } | 131 | } |
132 | 132 | ||
133 | /* | ||
134 | * ext4_llseek() copied from generic_file_llseek() to handle both | ||
135 | * block-mapped and extent-mapped maxbytes values. This should | ||
136 | * otherwise be identical with generic_file_llseek(). | ||
137 | */ | ||
138 | loff_t ext4_llseek(struct file *file, loff_t offset, int origin) | ||
139 | { | ||
140 | struct inode *inode = file->f_mapping->host; | ||
141 | loff_t maxbytes; | ||
142 | |||
143 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | ||
144 | maxbytes = EXT4_SB(inode->i_sb)->s_bitmap_maxbytes; | ||
145 | else | ||
146 | maxbytes = inode->i_sb->s_maxbytes; | ||
147 | mutex_lock(&inode->i_mutex); | ||
148 | switch (origin) { | ||
149 | case SEEK_END: | ||
150 | offset += inode->i_size; | ||
151 | break; | ||
152 | case SEEK_CUR: | ||
153 | if (offset == 0) { | ||
154 | mutex_unlock(&inode->i_mutex); | ||
155 | return file->f_pos; | ||
156 | } | ||
157 | offset += file->f_pos; | ||
158 | break; | ||
159 | } | ||
160 | |||
161 | if (offset < 0 || offset > maxbytes) { | ||
162 | mutex_unlock(&inode->i_mutex); | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | if (offset != file->f_pos) { | ||
167 | file->f_pos = offset; | ||
168 | file->f_version = 0; | ||
169 | } | ||
170 | mutex_unlock(&inode->i_mutex); | ||
171 | |||
172 | return offset; | ||
173 | } | ||
174 | |||
133 | const struct file_operations ext4_file_operations = { | 175 | const struct file_operations ext4_file_operations = { |
134 | .llseek = generic_file_llseek, | 176 | .llseek = ext4_llseek, |
135 | .read = do_sync_read, | 177 | .read = do_sync_read, |
136 | .write = do_sync_write, | 178 | .write = do_sync_write, |
137 | .aio_read = generic_file_aio_read, | 179 | .aio_read = generic_file_aio_read, |