mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
f2fs: fix multiple f2fs_add_link() calls having same name
am: d00d1b71d9
Change-Id: I2a53ea79d79f68575a8024b4d2e7ae6caa3f574d
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -431,6 +431,7 @@ struct f2fs_inode_info {
|
||||
atomic_t dirty_pages; /* # of dirty pages */
|
||||
f2fs_hash_t chash; /* hash value of given file name */
|
||||
unsigned int clevel; /* maximum level of given file name */
|
||||
struct task_struct *task; /* lookup and create consistency */
|
||||
nid_t i_xattr_nid; /* node id that contains xattrs */
|
||||
unsigned long long xattr_ver; /* cp version of xattr modification */
|
||||
loff_t last_disk_size; /* lastly written file size */
|
||||
|
||||
Reference in New Issue
Block a user