aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/dir.c75
-rw-r--r--fs/ext4/file.c9
-rw-r--r--fs/ext4/fsync.c11
-rw-r--r--fs/ext4/ioctl.c4
-rw-r--r--fs/ext4/namei.c8
-rw-r--r--fs/ext4/super.c5
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 */
334loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin) 337loff_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
389out_ok:
390 ret = offset;
391out_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 */
293loff_t ext4_llseek(struct file *file, loff_t offset, int origin) 293loff_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
306const struct file_operations ext4_file_operations = { 307const 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);
405resizefs_out: 405resizefs_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
1315static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 1315static 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 */
2093static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode, 2093static 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);
2254out_stop: 2254out_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);