diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/dir.c | 75 | ||||
-rw-r--r-- | fs/ext4/file.c | 9 | ||||
-rw-r--r-- | fs/ext4/fsync.c | 11 | ||||
-rw-r--r-- | fs/ext4/ioctl.c | 4 | ||||
-rw-r--r-- | fs/ext4/namei.c | 8 | ||||
-rw-r--r-- | fs/ext4/super.c | 5 |
6 files changed, 32 insertions, 80 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index aa39e600d159..8e07d2a5a139 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -324,74 +324,27 @@ static inline loff_t ext4_get_htree_eof(struct file *filp) | |||
324 | 324 | ||
325 | 325 | ||
326 | /* | 326 | /* |
327 | * ext4_dir_llseek() based on generic_file_llseek() to handle both | 327 | * ext4_dir_llseek() calls generic_file_llseek_size to handle htree |
328 | * non-htree and htree directories, where the "offset" is in terms | 328 | * directories, where the "offset" is in terms of the filename hash |
329 | * of the filename hash value instead of the byte offset. | 329 | * value instead of the byte offset. |
330 | * | 330 | * |
331 | * NOTE: offsets obtained *before* ext4_set_inode_flag(dir, EXT4_INODE_INDEX) | 331 | * Because we may return a 64-bit hash that is well beyond offset limits, |
332 | * will be invalid once the directory was converted into a dx directory | 332 | * we need to pass the max hash as the maximum allowable offset in |
333 | * the htree directory case. | ||
334 | * | ||
335 | * For non-htree, ext4_llseek already chooses the proper max offset. | ||
333 | */ | 336 | */ |
334 | loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin) | 337 | loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin) |
335 | { | 338 | { |
336 | struct inode *inode = file->f_mapping->host; | 339 | struct inode *inode = file->f_mapping->host; |
337 | loff_t ret = -EINVAL; | ||
338 | int dx_dir = is_dx_dir(inode); | 340 | int dx_dir = is_dx_dir(inode); |
341 | loff_t htree_max = ext4_get_htree_eof(file); | ||
339 | 342 | ||
340 | mutex_lock(&inode->i_mutex); | 343 | if (likely(dx_dir)) |
341 | 344 | return generic_file_llseek_size(file, offset, origin, | |
342 | /* NOTE: relative offsets with dx directories might not work | 345 | htree_max, htree_max); |
343 | * as expected, as it is difficult to figure out the | 346 | else |
344 | * correct offset between dx hashes */ | 347 | return ext4_llseek(file, offset, origin); |
345 | |||
346 | switch (origin) { | ||
347 | case SEEK_END: | ||
348 | if (unlikely(offset > 0)) | ||
349 | goto out_err; /* not supported for directories */ | ||
350 | |||
351 | /* so only negative offsets are left, does that have a | ||
352 | * meaning for directories at all? */ | ||
353 | if (dx_dir) | ||
354 | offset += ext4_get_htree_eof(file); | ||
355 | else | ||
356 | offset += inode->i_size; | ||
357 | break; | ||
358 | case SEEK_CUR: | ||
359 | /* | ||
360 | * Here we special-case the lseek(fd, 0, SEEK_CUR) | ||
361 | * position-querying operation. Avoid rewriting the "same" | ||
362 | * f_pos value back to the file because a concurrent read(), | ||
363 | * write() or lseek() might have altered it | ||
364 | */ | ||
365 | if (offset == 0) { | ||
366 | offset = file->f_pos; | ||
367 | goto out_ok; | ||
368 | } | ||
369 | |||
370 | offset += file->f_pos; | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | if (unlikely(offset < 0)) | ||
375 | goto out_err; | ||
376 | |||
377 | if (!dx_dir) { | ||
378 | if (offset > inode->i_sb->s_maxbytes) | ||
379 | goto out_err; | ||
380 | } else if (offset > ext4_get_htree_eof(file)) | ||
381 | goto out_err; | ||
382 | |||
383 | /* Special lock needed here? */ | ||
384 | if (offset != file->f_pos) { | ||
385 | file->f_pos = offset; | ||
386 | file->f_version = 0; | ||
387 | } | ||
388 | |||
389 | out_ok: | ||
390 | ret = offset; | ||
391 | out_err: | ||
392 | mutex_unlock(&inode->i_mutex); | ||
393 | |||
394 | return ret; | ||
395 | } | 348 | } |
396 | 349 | ||
397 | /* | 350 | /* |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index f77e795fed65..3b0e3bdaabfc 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -286,9 +286,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
286 | } | 286 | } |
287 | 287 | ||
288 | /* | 288 | /* |
289 | * ext4_llseek() copied from generic_file_llseek() to handle both | 289 | * ext4_llseek() handles both block-mapped and extent-mapped maxbytes values |
290 | * block-mapped and extent-mapped maxbytes values. This should | 290 | * by calling generic_file_llseek_size() with the appropriate maxbytes |
291 | * otherwise be identical with generic_file_llseek(). | 291 | * value for each. |
292 | */ | 292 | */ |
293 | loff_t ext4_llseek(struct file *file, loff_t offset, int origin) | 293 | loff_t ext4_llseek(struct file *file, loff_t offset, int origin) |
294 | { | 294 | { |
@@ -300,7 +300,8 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin) | |||
300 | else | 300 | else |
301 | maxbytes = inode->i_sb->s_maxbytes; | 301 | maxbytes = inode->i_sb->s_maxbytes; |
302 | 302 | ||
303 | return generic_file_llseek_size(file, offset, origin, maxbytes); | 303 | return generic_file_llseek_size(file, offset, origin, |
304 | maxbytes, i_size_read(inode)); | ||
304 | } | 305 | } |
305 | 306 | ||
306 | const struct file_operations ext4_file_operations = { | 307 | const struct file_operations ext4_file_operations = { |
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index bb6c7d811313..2a1dcea4f12e 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c | |||
@@ -135,14 +135,7 @@ static int ext4_sync_parent(struct inode *inode) | |||
135 | inode = igrab(inode); | 135 | inode = igrab(inode); |
136 | while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { | 136 | while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { |
137 | ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); | 137 | ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); |
138 | dentry = NULL; | 138 | dentry = d_find_any_alias(inode); |
139 | spin_lock(&inode->i_lock); | ||
140 | if (!list_empty(&inode->i_dentry)) { | ||
141 | dentry = list_first_entry(&inode->i_dentry, | ||
142 | struct dentry, d_alias); | ||
143 | dget(dentry); | ||
144 | } | ||
145 | spin_unlock(&inode->i_lock); | ||
146 | if (!dentry) | 139 | if (!dentry) |
147 | break; | 140 | break; |
148 | next = igrab(dentry->d_parent->d_inode); | 141 | next = igrab(dentry->d_parent->d_inode); |
@@ -232,7 +225,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
232 | 225 | ||
233 | if (!journal) { | 226 | if (!journal) { |
234 | ret = __sync_inode(inode, datasync); | 227 | ret = __sync_inode(inode, datasync); |
235 | if (!ret && !list_empty(&inode->i_dentry)) | 228 | if (!ret && !hlist_empty(&inode->i_dentry)) |
236 | ret = ext4_sync_parent(inode); | 229 | ret = ext4_sync_parent(inode); |
237 | goto out; | 230 | goto out; |
238 | } | 231 | } |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6ec6f9ee2fec..7f7dad787603 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -389,7 +389,7 @@ group_add_out: | |||
389 | if (err) | 389 | if (err) |
390 | return err; | 390 | return err; |
391 | 391 | ||
392 | err = mnt_want_write(filp->f_path.mnt); | 392 | err = mnt_want_write_file(filp); |
393 | if (err) | 393 | if (err) |
394 | goto resizefs_out; | 394 | goto resizefs_out; |
395 | 395 | ||
@@ -401,7 +401,7 @@ group_add_out: | |||
401 | } | 401 | } |
402 | if (err == 0) | 402 | if (err == 0) |
403 | err = err2; | 403 | err = err2; |
404 | mnt_drop_write(filp->f_path.mnt); | 404 | mnt_drop_write_file(filp); |
405 | resizefs_out: | 405 | resizefs_out: |
406 | ext4_resize_end(sb); | 406 | ext4_resize_end(sb); |
407 | return err; | 407 | return err; |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 37faf56e558d..2a42cc04466f 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1312,7 +1312,7 @@ errout: | |||
1312 | return NULL; | 1312 | return NULL; |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1315 | static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
1316 | { | 1316 | { |
1317 | struct inode *inode; | 1317 | struct inode *inode; |
1318 | struct ext4_dir_entry_2 *de; | 1318 | struct ext4_dir_entry_2 *de; |
@@ -2072,8 +2072,8 @@ static int ext4_add_nondir(handle_t *handle, | |||
2072 | int err = ext4_add_entry(handle, dentry, inode); | 2072 | int err = ext4_add_entry(handle, dentry, inode); |
2073 | if (!err) { | 2073 | if (!err) { |
2074 | ext4_mark_inode_dirty(handle, inode); | 2074 | ext4_mark_inode_dirty(handle, inode); |
2075 | d_instantiate(dentry, inode); | ||
2076 | unlock_new_inode(inode); | 2075 | unlock_new_inode(inode); |
2076 | d_instantiate(dentry, inode); | ||
2077 | return 0; | 2077 | return 0; |
2078 | } | 2078 | } |
2079 | drop_nlink(inode); | 2079 | drop_nlink(inode); |
@@ -2091,7 +2091,7 @@ static int ext4_add_nondir(handle_t *handle, | |||
2091 | * with d_instantiate(). | 2091 | * with d_instantiate(). |
2092 | */ | 2092 | */ |
2093 | static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 2093 | static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
2094 | struct nameidata *nd) | 2094 | bool excl) |
2095 | { | 2095 | { |
2096 | handle_t *handle; | 2096 | handle_t *handle; |
2097 | struct inode *inode; | 2097 | struct inode *inode; |
@@ -2249,8 +2249,8 @@ out_clear_inode: | |||
2249 | err = ext4_mark_inode_dirty(handle, dir); | 2249 | err = ext4_mark_inode_dirty(handle, dir); |
2250 | if (err) | 2250 | if (err) |
2251 | goto out_clear_inode; | 2251 | goto out_clear_inode; |
2252 | d_instantiate(dentry, inode); | ||
2253 | unlock_new_inode(inode); | 2252 | unlock_new_inode(inode); |
2253 | d_instantiate(dentry, inode); | ||
2254 | out_stop: | 2254 | out_stop: |
2255 | brelse(dir_block); | 2255 | brelse(dir_block); |
2256 | ext4_journal_stop(handle); | 2256 | ext4_journal_stop(handle); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a2a59796cde0..2d51cd9af225 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -4476,6 +4476,11 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
4476 | 4476 | ||
4477 | trace_ext4_sync_fs(sb, wait); | 4477 | trace_ext4_sync_fs(sb, wait); |
4478 | flush_workqueue(sbi->dio_unwritten_wq); | 4478 | flush_workqueue(sbi->dio_unwritten_wq); |
4479 | /* | ||
4480 | * Writeback quota in non-journalled quota case - journalled quota has | ||
4481 | * no dirty dquots | ||
4482 | */ | ||
4483 | dquot_writeback_dquots(sb, -1); | ||
4479 | if (jbd2_journal_start_commit(sbi->s_journal, &target)) { | 4484 | if (jbd2_journal_start_commit(sbi->s_journal, &target)) { |
4480 | if (wait) | 4485 | if (wait) |
4481 | jbd2_log_wait_commit(sbi->s_journal, target); | 4486 | jbd2_log_wait_commit(sbi->s_journal, target); |