]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/f2fs/dir.c
Add support for the AudioInjector.net Octo sound card
[mirror_ubuntu-zesty-kernel.git] / fs / f2fs / dir.c
index 827c5daef4fca7d9168833ccc3388cd2dc6c071c..54aa30ee028f64375ff57a415d94b28b61973188 100644 (file)
@@ -207,9 +207,13 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
                f2fs_put_page(dentry_page, 0);
        }
 
-       if (!de && room && F2FS_I(dir)->chash != namehash) {
-               F2FS_I(dir)->chash = namehash;
-               F2FS_I(dir)->clevel = level;
+       /* This is to increase the speed of f2fs_create */
+       if (!de && room) {
+               F2FS_I(dir)->task = current;
+               if (F2FS_I(dir)->chash != namehash) {
+                       F2FS_I(dir)->chash = namehash;
+                       F2FS_I(dir)->clevel = level;
+               }
        }
 
        return de;
@@ -643,14 +647,34 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
                                struct inode *inode, nid_t ino, umode_t mode)
 {
        struct fscrypt_name fname;
+       struct page *page = NULL;
+       struct f2fs_dir_entry *de = NULL;
        int err;
 
        err = fscrypt_setup_filename(dir, name, 0, &fname);
        if (err)
                return err;
 
-       err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
-
+       /*
+        * An immature stakable filesystem shows a race condition between lookup
+        * and create. If we have same task when doing lookup and create, it's
+        * definitely fine as expected by VFS normally. Otherwise, let's just
+        * verify on-disk dentry one more time, which guarantees filesystem
+        * consistency more.
+        */
+       if (current != F2FS_I(dir)->task) {
+               de = __f2fs_find_entry(dir, &fname, &page);
+               F2FS_I(dir)->task = NULL;
+       }
+       if (de) {
+               f2fs_dentry_kunmap(dir, page);
+               f2fs_put_page(page, 0);
+               err = -EEXIST;
+       } else if (IS_ERR(page)) {
+               err = PTR_ERR(page);
+       } else {
+               err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
+       }
        fscrypt_free_filename(&fname);
        return err;
 }