Merge tag 'mfd-for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
[cascardo/linux.git] / fs / f2fs / dir.c
index 7c1678b..faa7495 100644 (file)
@@ -172,8 +172,6 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
 
        namehash = f2fs_dentry_hash(&name);
 
-       f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH);
-
        nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
        nblock = bucket_blocks(level);
 
@@ -238,6 +236,14 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
                goto out;
 
        max_depth = F2FS_I(dir)->i_current_depth;
+       if (unlikely(max_depth > MAX_DIR_HASH_DEPTH)) {
+               f2fs_msg(F2FS_I_SB(dir)->sb, KERN_WARNING,
+                               "Corrupted max_depth of %lu: %u",
+                               dir->i_ino, max_depth);
+               max_depth = MAX_DIR_HASH_DEPTH;
+               F2FS_I(dir)->i_current_depth = max_depth;
+               mark_inode_dirty(dir);
+       }
 
        for (level = 0; level < max_depth; level++) {
                de = find_in_level(dir, level, &fname, res_page);
@@ -444,7 +450,7 @@ error:
        /* once the failed inode becomes a bad inode, i_mode is S_IFREG */
        truncate_inode_pages(&inode->i_data, 0);
        truncate_blocks(inode, 0, false);
-       remove_dirty_dir_inode(inode);
+       remove_dirty_inode(inode);
        remove_inode_page(inode);
        return ERR_PTR(err);
 }
@@ -630,6 +636,7 @@ fail:
        f2fs_put_page(dentry_page, 1);
 out:
        f2fs_fname_free_filename(&fname);
+       f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
        return err;
 }
 
@@ -651,6 +658,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
        clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
 fail:
        up_write(&F2FS_I(inode)->i_sem);
+       f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
        return err;
 }
 
@@ -695,6 +703,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
        int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
        int i;
 
+       f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
+
        if (f2fs_has_inline_dentry(dir))
                return f2fs_delete_inline_entry(dentry, page, dir, inode);
 
@@ -855,25 +865,27 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 
        for (; n < npages; n++) {
                dentry_page = get_lock_data_page(inode, n, false);
-               if (IS_ERR(dentry_page))
-                       continue;
+               if (IS_ERR(dentry_page)) {
+                       err = PTR_ERR(dentry_page);
+                       if (err == -ENOENT)
+                               continue;
+                       else
+                               goto out;
+               }
 
                dentry_blk = kmap(dentry_page);
 
                make_dentry_ptr(inode, &d, (void *)dentry_blk, 1);
 
-               if (f2fs_fill_dentries(ctx, &d, n * NR_DENTRY_IN_BLOCK, &fstr))
-                       goto stop;
+               if (f2fs_fill_dentries(ctx, &d, n * NR_DENTRY_IN_BLOCK, &fstr)) {
+                       kunmap(dentry_page);
+                       f2fs_put_page(dentry_page, 1);
+                       break;
+               }
 
                ctx->pos = (n + 1) * NR_DENTRY_IN_BLOCK;
                kunmap(dentry_page);
                f2fs_put_page(dentry_page, 1);
-               dentry_page = NULL;
-       }
-stop:
-       if (dentry_page && !IS_ERR(dentry_page)) {
-               kunmap(dentry_page);
-               f2fs_put_page(dentry_page, 1);
        }
 out:
        f2fs_fname_crypto_free_buffer(&fstr);