Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[cascardo/linux.git] / fs / f2fs / dir.c
index 8e5309c..369f451 100644 (file)
@@ -37,7 +37,7 @@ static unsigned int bucket_blocks(unsigned int level)
                return 4;
 }
 
-unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
+static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
        [F2FS_FT_UNKNOWN]       = DT_UNKNOWN,
        [F2FS_FT_REG_FILE]      = DT_REG,
        [F2FS_FT_DIR]           = DT_DIR,
@@ -172,7 +172,10 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
        int max_slots;
        f2fs_hash_t namehash;
 
-       namehash = f2fs_dentry_hash(&name);
+       if(fname->hash)
+               namehash = cpu_to_le32(fname->hash);
+       else
+               namehash = f2fs_dentry_hash(&name);
 
        nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
        nblock = bucket_blocks(level);
@@ -212,31 +215,17 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
        return de;
 }
 
-/*
- * Find an entry in the specified directory with the wanted name.
- * It returns the page where the entry was found (as a parameter - res_page),
- * and the entry itself. Page is returned mapped and unlocked.
- * Entry is guaranteed to be valid.
- */
-struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
-                       const struct qstr *child, struct page **res_page)
+struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
+                       struct fscrypt_name *fname, struct page **res_page)
 {
        unsigned long npages = dir_blocks(dir);
        struct f2fs_dir_entry *de = NULL;
        unsigned int max_depth;
        unsigned int level;
-       struct fscrypt_name fname;
-       int err;
-
-       err = fscrypt_setup_filename(dir, child, 1, &fname);
-       if (err) {
-               *res_page = ERR_PTR(err);
-               return NULL;
-       }
 
        if (f2fs_has_inline_dentry(dir)) {
                *res_page = NULL;
-               de = find_in_inline_dir(dir, &fname, res_page);
+               de = find_in_inline_dir(dir, fname, res_page);
                goto out;
        }
 
@@ -256,11 +245,35 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
 
        for (level = 0; level < max_depth; level++) {
                *res_page = NULL;
-               de = find_in_level(dir, level, &fname, res_page);
+               de = find_in_level(dir, level, fname, res_page);
                if (de || IS_ERR(*res_page))
                        break;
        }
 out:
+       return de;
+}
+
+/*
+ * Find an entry in the specified directory with the wanted name.
+ * It returns the page where the entry was found (as a parameter - res_page),
+ * and the entry itself. Page is returned mapped and unlocked.
+ * Entry is guaranteed to be valid.
+ */
+struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
+                       const struct qstr *child, struct page **res_page)
+{
+       struct f2fs_dir_entry *de = NULL;
+       struct fscrypt_name fname;
+       int err;
+
+       err = fscrypt_setup_filename(dir, child, 1, &fname);
+       if (err) {
+               *res_page = ERR_PTR(err);
+               return NULL;
+       }
+
+       de = __f2fs_find_entry(dir, &fname, res_page);
+
        fscrypt_free_filename(&fname);
        return de;
 }
@@ -375,7 +388,8 @@ static int make_empty_dir(struct inode *inode,
 }
 
 struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
-                       const struct qstr *name, struct page *dpage)
+                       const struct qstr *new_name, const struct qstr *orig_name,
+                       struct page *dpage)
 {
        struct page *page;
        int err;
@@ -400,7 +414,7 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
                if (err)
                        goto put_error;
 
-               err = f2fs_init_security(inode, dir, name, page);
+               err = f2fs_init_security(inode, dir, orig_name, page);
                if (err)
                        goto put_error;
 
@@ -417,8 +431,8 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
                set_cold_node(inode, page);
        }
 
-       if (name)
-               init_dent_inode(name, page);
+       if (new_name)
+               init_dent_inode(new_name, page);
 
        /*
         * This file should be checkpointed during fsync.
@@ -496,7 +510,7 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d,
        de->ino = cpu_to_le32(ino);
        set_de_type(de, mode);
        for (i = 0; i < slots; i++) {
-               test_and_set_bit_le(bit_pos + i, (void *)d->bitmap);
+               __set_bit_le(bit_pos + i, (void *)d->bitmap);
                /* avoid wrong garbage data for readdir */
                if (i)
                        (de + i)->name_len = 0;
@@ -504,6 +518,7 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d,
 }
 
 int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
+                               const struct qstr *orig_name,
                                struct inode *inode, nid_t ino, umode_t mode)
 {
        unsigned int bit_pos;
@@ -530,7 +545,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
 
 start:
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-       if (time_to_inject(FAULT_DIR_DEPTH))
+       if (time_to_inject(F2FS_I_SB(dir), FAULT_DIR_DEPTH))
                return -ENOSPC;
 #endif
        if (unlikely(current_depth == MAX_DIR_HASH_DEPTH))
@@ -569,7 +584,8 @@ add_dentry:
 
        if (inode) {
                down_write(&F2FS_I(inode)->i_sem);
-               page = init_inode_metadata(inode, dir, new_name, NULL);
+               page = init_inode_metadata(inode, dir, new_name,
+                                               orig_name, NULL);
                if (IS_ERR(page)) {
                        err = PTR_ERR(page);
                        goto fail;
@@ -599,6 +615,26 @@ fail:
        return err;
 }
 
+int __f2fs_do_add_link(struct inode *dir, struct fscrypt_name *fname,
+                               struct inode *inode, nid_t ino, umode_t mode)
+{
+       struct qstr new_name;
+       int err = -EAGAIN;
+
+       new_name.name = fname_name(fname);
+       new_name.len = fname_len(fname);
+
+       if (f2fs_has_inline_dentry(dir))
+               err = f2fs_add_inline_entry(dir, &new_name, fname->usr_fname,
+                                                       inode, ino, mode);
+       if (err == -EAGAIN)
+               err = f2fs_add_regular_entry(dir, &new_name, fname->usr_fname,
+                                                       inode, ino, mode);
+
+       f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
+       return err;
+}
+
 /*
  * Caller should grab and release a rwsem by calling f2fs_lock_op() and
  * f2fs_unlock_op().
@@ -607,24 +643,15 @@ 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 qstr new_name;
        int err;
 
        err = fscrypt_setup_filename(dir, name, 0, &fname);
        if (err)
                return err;
 
-       new_name.name = fname_name(&fname);
-       new_name.len = fname_len(&fname);
-
-       err = -EAGAIN;
-       if (f2fs_has_inline_dentry(dir))
-               err = f2fs_add_inline_entry(dir, &new_name, inode, ino, mode);
-       if (err == -EAGAIN)
-               err = f2fs_add_regular_entry(dir, &new_name, inode, ino, mode);
+       err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
 
        fscrypt_free_filename(&fname);
-       f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
        return err;
 }
 
@@ -634,7 +661,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
        int err = 0;
 
        down_write(&F2FS_I(inode)->i_sem);
-       page = init_inode_metadata(inode, dir, NULL, NULL);
+       page = init_inode_metadata(inode, dir, NULL, NULL, NULL);
        if (IS_ERR(page)) {
                err = PTR_ERR(page);
                goto fail;
@@ -786,19 +813,12 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 
                if (f2fs_encrypted_inode(d->inode)) {
                        int save_len = fstr->len;
-                       int ret;
+                       int err;
 
-                       de_name.name = f2fs_kmalloc(de_name.len, GFP_NOFS);
-                       if (!de_name.name)
-                               return false;
-
-                       memcpy(de_name.name, d->filename[bit_pos], de_name.len);
-
-                       ret = fscrypt_fname_disk_to_usr(d->inode,
+                       err = fscrypt_fname_disk_to_usr(d->inode,
                                                (u32)de->hash_code, 0,
                                                &de_name, fstr);
-                       kfree(de_name.name);
-                       if (ret < 0)
+                       if (err)
                                return true;
 
                        de_name = *fstr;