Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
[cascardo/linux.git] / fs / f2fs / dir.c
index b54f871..b1a7d57 100644 (file)
@@ -37,7 +37,7 @@ static unsigned int bucket_blocks(unsigned int level)
                return 4;
 }
 
-static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
+unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
        [F2FS_FT_UNKNOWN]       = DT_UNKNOWN,
        [F2FS_FT_REG_FILE]      = DT_REG,
        [F2FS_FT_DIR]           = DT_DIR,
@@ -59,7 +59,7 @@ static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
        [S_IFLNK >> S_SHIFT]    = F2FS_FT_SYMLINK,
 };
 
-static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
+void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
 {
        umode_t mode = inode->i_mode;
        de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
@@ -90,51 +90,70 @@ static bool early_match_name(size_t namelen, f2fs_hash_t namehash,
 }
 
 static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
-                       struct qstr *name, int *max_slots,
-                       f2fs_hash_t namehash, struct page **res_page)
+                               struct qstr *name, int *max_slots,
+                               struct page **res_page)
+{
+       struct f2fs_dentry_block *dentry_blk;
+       struct f2fs_dir_entry *de;
+       struct f2fs_dentry_ptr d;
+
+       dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page);
+
+       make_dentry_ptr(&d, (void *)dentry_blk, 1);
+       de = find_target_dentry(name, max_slots, &d);
+
+       if (de)
+               *res_page = dentry_page;
+       else
+               kunmap(dentry_page);
+
+       /*
+        * For the most part, it should be a bug when name_len is zero.
+        * We stop here for figuring out where the bugs has occurred.
+        */
+       f2fs_bug_on(F2FS_P_SB(dentry_page), d.max < 0);
+       return de;
+}
+
+struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots,
+                                               struct f2fs_dentry_ptr *d)
 {
        struct f2fs_dir_entry *de;
        unsigned long bit_pos = 0;
-       struct f2fs_dentry_block *dentry_blk = kmap(dentry_page);
-       const void *dentry_bits = &dentry_blk->dentry_bitmap;
+       f2fs_hash_t namehash = f2fs_dentry_hash(name);
        int max_len = 0;
 
-       while (bit_pos < NR_DENTRY_IN_BLOCK) {
-               if (!test_bit_le(bit_pos, dentry_bits)) {
+       if (max_slots)
+               *max_slots = 0;
+       while (bit_pos < d->max) {
+               if (!test_bit_le(bit_pos, d->bitmap)) {
                        if (bit_pos == 0)
                                max_len = 1;
-                       else if (!test_bit_le(bit_pos - 1, dentry_bits))
+                       else if (!test_bit_le(bit_pos - 1, d->bitmap))
                                max_len++;
                        bit_pos++;
                        continue;
                }
-               de = &dentry_blk->dentry[bit_pos];
-               if (early_match_name(name->len, namehash, de)) {
-                       if (!memcmp(dentry_blk->filename[bit_pos],
-                                                       name->name,
-                                                       name->len)) {
-                               *res_page = dentry_page;
-                               goto found;
-                       }
-               }
-               if (max_len > *max_slots) {
+               de = &d->dentry[bit_pos];
+               if (early_match_name(name->len, namehash, de) &&
+                       !memcmp(d->filename[bit_pos], name->name, name->len))
+                       goto found;
+
+               if (max_slots && *max_slots >= 0 && max_len > *max_slots) {
                        *max_slots = max_len;
                        max_len = 0;
                }
 
-               /*
-                * For the most part, it should be a bug when name_len is zero.
-                * We stop here for figuring out where the bugs has occurred.
-                */
-               f2fs_bug_on(F2FS_P_SB(dentry_page), !de->name_len);
+               /* remain bug on condition */
+               if (unlikely(!de->name_len))
+                       d->max = -1;
 
                bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
        }
 
        de = NULL;
-       kunmap(dentry_page);
 found:
-       if (max_len > *max_slots)
+       if (max_slots && max_len > *max_slots)
                *max_slots = max_len;
        return de;
 }
@@ -149,7 +168,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
        struct page *dentry_page;
        struct f2fs_dir_entry *de = NULL;
        bool room = false;
-       int max_slots = 0;
+       int max_slots;
 
        f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH);
 
@@ -168,8 +187,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
                        continue;
                }
 
-               de = find_in_block(dentry_page, name, &max_slots,
-                                       namehash, res_page);
+               de = find_in_block(dentry_page, name, &max_slots, res_page);
                if (de)
                        break;
 
@@ -201,6 +219,9 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
        unsigned int max_depth;
        unsigned int level;
 
+       if (f2fs_has_inline_dentry(dir))
+               return find_in_inline_dir(dir, child, res_page);
+
        if (npages == 0)
                return NULL;
 
@@ -227,6 +248,9 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
        struct f2fs_dir_entry *de;
        struct f2fs_dentry_block *dentry_blk;
 
+       if (f2fs_has_inline_dentry(dir))
+               return f2fs_parent_inline_dir(dir, p);
+
        page = get_lock_data_page(dir, 0);
        if (IS_ERR(page))
                return NULL;
@@ -247,7 +271,7 @@ ino_t f2fs_inode_by_name(struct inode *dir, struct qstr *qstr)
        de = f2fs_find_entry(dir, qstr, &page);
        if (de) {
                res = le32_to_cpu(de->ino);
-               kunmap(page);
+               f2fs_dentry_kunmap(dir, page);
                f2fs_put_page(page, 0);
        }
 
@@ -257,11 +281,13 @@ ino_t f2fs_inode_by_name(struct inode *dir, struct qstr *qstr)
 void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
                struct page *page, struct inode *inode)
 {
+       enum page_type type = f2fs_has_inline_dentry(dir) ? NODE : DATA;
        lock_page(page);
-       f2fs_wait_on_page_writeback(page, DATA);
+       f2fs_wait_on_page_writeback(page, type);
        de->ino = cpu_to_le32(inode->i_ino);
        set_de_type(de, inode);
-       kunmap(page);
+       if (!f2fs_has_inline_dentry(dir))
+               kunmap(page);
        set_page_dirty(page);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
        mark_inode_dirty(dir);
@@ -296,36 +322,48 @@ int update_dent_inode(struct inode *inode, const struct qstr *name)
        return 0;
 }
 
-static int make_empty_dir(struct inode *inode,
-               struct inode *parent, struct page *page)
+void do_make_empty_dir(struct inode *inode, struct inode *parent,
+                                       struct f2fs_dentry_ptr *d)
 {
-       struct page *dentry_page;
-       struct f2fs_dentry_block *dentry_blk;
        struct f2fs_dir_entry *de;
 
-       dentry_page = get_new_data_page(inode, page, 0, true);
-       if (IS_ERR(dentry_page))
-               return PTR_ERR(dentry_page);
-
-
-       dentry_blk = kmap_atomic(dentry_page);
-
-       de = &dentry_blk->dentry[0];
+       de = &d->dentry[0];
        de->name_len = cpu_to_le16(1);
        de->hash_code = 0;
        de->ino = cpu_to_le32(inode->i_ino);
-       memcpy(dentry_blk->filename[0], ".", 1);
+       memcpy(d->filename[0], ".", 1);
        set_de_type(de, inode);
 
-       de = &dentry_blk->dentry[1];
+       de = &d->dentry[1];
        de->hash_code = 0;
        de->name_len = cpu_to_le16(2);
        de->ino = cpu_to_le32(parent->i_ino);
-       memcpy(dentry_blk->filename[1], "..", 2);
+       memcpy(d->filename[1], "..", 2);
        set_de_type(de, inode);
 
-       test_and_set_bit_le(0, &dentry_blk->dentry_bitmap);
-       test_and_set_bit_le(1, &dentry_blk->dentry_bitmap);
+       test_and_set_bit_le(0, (void *)d->bitmap);
+       test_and_set_bit_le(1, (void *)d->bitmap);
+}
+
+static int make_empty_dir(struct inode *inode,
+               struct inode *parent, struct page *page)
+{
+       struct page *dentry_page;
+       struct f2fs_dentry_block *dentry_blk;
+       struct f2fs_dentry_ptr d;
+
+       if (f2fs_has_inline_dentry(inode))
+               return make_empty_inline_dir(inode, parent, page);
+
+       dentry_page = get_new_data_page(inode, page, 0, true);
+       if (IS_ERR(dentry_page))
+               return PTR_ERR(dentry_page);
+
+       dentry_blk = kmap_atomic(dentry_page);
+
+       make_dentry_ptr(&d, (void *)dentry_blk, 1);
+       do_make_empty_dir(inode, parent, &d);
+
        kunmap_atomic(dentry_blk);
 
        set_page_dirty(dentry_page);
@@ -333,8 +371,8 @@ static int make_empty_dir(struct inode *inode,
        return 0;
 }
 
-static struct page *init_inode_metadata(struct inode *inode,
-               struct inode *dir, const struct qstr *name)
+struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
+                       const struct qstr *name, struct page *dpage)
 {
        struct page *page;
        int err;
@@ -350,7 +388,7 @@ static struct page *init_inode_metadata(struct inode *inode,
                                goto error;
                }
 
-               err = f2fs_init_acl(inode, dir, page);
+               err = f2fs_init_acl(inode, dir, page, dpage);
                if (err)
                        goto put_error;
 
@@ -395,7 +433,7 @@ error:
        return ERR_PTR(err);
 }
 
-static void update_parent_metadata(struct inode *dir, struct inode *inode,
+void update_parent_metadata(struct inode *dir, struct inode *inode,
                                                unsigned int current_depth)
 {
        if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
@@ -417,27 +455,23 @@ static void update_parent_metadata(struct inode *dir, struct inode *inode,
                clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
 }
 
-static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots)
+int room_for_filename(const void *bitmap, int slots, int max_slots)
 {
        int bit_start = 0;
        int zero_start, zero_end;
 next:
-       zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap,
-                                               NR_DENTRY_IN_BLOCK,
-                                               bit_start);
-       if (zero_start >= NR_DENTRY_IN_BLOCK)
-               return NR_DENTRY_IN_BLOCK;
+       zero_start = find_next_zero_bit_le(bitmap, max_slots, bit_start);
+       if (zero_start >= max_slots)
+               return max_slots;
 
-       zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap,
-                                               NR_DENTRY_IN_BLOCK,
-                                               zero_start);
+       zero_end = find_next_bit_le(bitmap, max_slots, zero_start);
        if (zero_end - zero_start >= slots)
                return zero_start;
 
        bit_start = zero_end + 1;
 
-       if (zero_end + 1 >= NR_DENTRY_IN_BLOCK)
-               return NR_DENTRY_IN_BLOCK;
+       if (zero_end + 1 >= max_slots)
+               return max_slots;
        goto next;
 }
 
@@ -463,6 +497,14 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
        int err = 0;
        int i;
 
+       if (f2fs_has_inline_dentry(dir)) {
+               err = f2fs_add_inline_entry(dir, name, inode);
+               if (!err || err != -EAGAIN)
+                       return err;
+               else
+                       err = 0;
+       }
+
        dentry_hash = f2fs_dentry_hash(name);
        level = 0;
        current_depth = F2FS_I(dir)->i_current_depth;
@@ -491,7 +533,8 @@ start:
                        return PTR_ERR(dentry_page);
 
                dentry_blk = kmap(dentry_page);
-               bit_pos = room_for_filename(dentry_blk, slots);
+               bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
+                                               slots, NR_DENTRY_IN_BLOCK);
                if (bit_pos < NR_DENTRY_IN_BLOCK)
                        goto add_dentry;
 
@@ -506,7 +549,7 @@ add_dentry:
        f2fs_wait_on_page_writeback(dentry_page, DATA);
 
        down_write(&F2FS_I(inode)->i_sem);
-       page = init_inode_metadata(inode, dir, name);
+       page = init_inode_metadata(inode, dir, name, NULL);
        if (IS_ERR(page)) {
                err = PTR_ERR(page);
                goto fail;
@@ -545,7 +588,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);
+       page = init_inode_metadata(inode, dir, NULL, NULL);
        if (IS_ERR(page)) {
                err = PTR_ERR(page);
                goto fail;
@@ -560,26 +603,57 @@ fail:
        return err;
 }
 
+void f2fs_drop_nlink(struct inode *dir, struct inode *inode, struct page *page)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
+
+       down_write(&F2FS_I(inode)->i_sem);
+
+       if (S_ISDIR(inode->i_mode)) {
+               drop_nlink(dir);
+               if (page)
+                       update_inode(dir, page);
+               else
+                       update_inode_page(dir);
+       }
+       inode->i_ctime = CURRENT_TIME;
+
+       drop_nlink(inode);
+       if (S_ISDIR(inode->i_mode)) {
+               drop_nlink(inode);
+               i_size_write(inode, 0);
+       }
+       up_write(&F2FS_I(inode)->i_sem);
+       update_inode_page(inode);
+
+       if (inode->i_nlink == 0)
+               add_orphan_inode(sbi, inode->i_ino);
+       else
+               release_orphan_inode(sbi);
+}
+
 /*
  * It only removes the dentry from the dentry page, corresponding name
  * entry in name page does not need to be touched during deletion.
  */
 void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
-                                               struct inode *inode)
+                                       struct inode *dir, struct inode *inode)
 {
        struct  f2fs_dentry_block *dentry_blk;
        unsigned int bit_pos;
-       struct inode *dir = page->mapping->host;
        int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
        int i;
 
+       if (f2fs_has_inline_dentry(dir))
+               return f2fs_delete_inline_entry(dentry, page, dir, inode);
+
        lock_page(page);
        f2fs_wait_on_page_writeback(page, DATA);
 
        dentry_blk = page_address(page);
        bit_pos = dentry - dentry_blk->dentry;
        for (i = 0; i < slots; i++)
-               test_and_clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+               clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
 
        /* Let's check and deallocate this dentry page */
        bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
@@ -590,29 +664,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
 
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 
-       if (inode) {
-               struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
-
-               down_write(&F2FS_I(inode)->i_sem);
-
-               if (S_ISDIR(inode->i_mode)) {
-                       drop_nlink(dir);
-                       update_inode_page(dir);
-               }
-               inode->i_ctime = CURRENT_TIME;
-               drop_nlink(inode);
-               if (S_ISDIR(inode->i_mode)) {
-                       drop_nlink(inode);
-                       i_size_write(inode, 0);
-               }
-               up_write(&F2FS_I(inode)->i_sem);
-               update_inode_page(inode);
-
-               if (inode->i_nlink == 0)
-                       add_orphan_inode(sbi, inode->i_ino);
-               else
-                       release_orphan_inode(sbi);
-       }
+       if (inode)
+               f2fs_drop_nlink(dir, inode, NULL);
 
        if (bit_pos == NR_DENTRY_IN_BLOCK) {
                truncate_hole(dir, page->index, page->index + 1);
@@ -628,9 +681,12 @@ bool f2fs_empty_dir(struct inode *dir)
        unsigned long bidx;
        struct page *dentry_page;
        unsigned int bit_pos;
-       struct  f2fs_dentry_block *dentry_blk;
+       struct f2fs_dentry_block *dentry_blk;
        unsigned long nblock = dir_blocks(dir);
 
+       if (f2fs_has_inline_dentry(dir))
+               return f2fs_empty_inline_dir(dir);
+
        for (bidx = 0; bidx < nblock; bidx++) {
                dentry_page = get_lock_data_page(dir, bidx);
                if (IS_ERR(dentry_page)) {
@@ -640,7 +696,6 @@ bool f2fs_empty_dir(struct inode *dir)
                                return false;
                }
 
-
                dentry_blk = kmap_atomic(dentry_page);
                if (bidx == 0)
                        bit_pos = 2;
@@ -659,19 +714,48 @@ bool f2fs_empty_dir(struct inode *dir)
        return true;
 }
 
+bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
+                                               unsigned int start_pos)
+{
+       unsigned char d_type = DT_UNKNOWN;
+       unsigned int bit_pos;
+       struct f2fs_dir_entry *de = NULL;
+
+       bit_pos = ((unsigned long)ctx->pos % d->max);
+
+       while (bit_pos < d->max) {
+               bit_pos = find_next_bit_le(d->bitmap, d->max, bit_pos);
+               if (bit_pos >= d->max)
+                       break;
+
+               de = &d->dentry[bit_pos];
+               if (de->file_type < F2FS_FT_MAX)
+                       d_type = f2fs_filetype_table[de->file_type];
+               else
+                       d_type = DT_UNKNOWN;
+               if (!dir_emit(ctx, d->filename[bit_pos],
+                                       le16_to_cpu(de->name_len),
+                                       le32_to_cpu(de->ino), d_type))
+                       return true;
+
+               bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
+               ctx->pos = start_pos + bit_pos;
+       }
+       return false;
+}
+
 static int f2fs_readdir(struct file *file, struct dir_context *ctx)
 {
        struct inode *inode = file_inode(file);
        unsigned long npages = dir_blocks(inode);
-       unsigned int bit_pos = 0;
        struct f2fs_dentry_block *dentry_blk = NULL;
-       struct f2fs_dir_entry *de = NULL;
        struct page *dentry_page = NULL;
        struct file_ra_state *ra = &file->f_ra;
        unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK);
-       unsigned char d_type = DT_UNKNOWN;
+       struct f2fs_dentry_ptr d;
 
-       bit_pos = ((unsigned long)ctx->pos % NR_DENTRY_IN_BLOCK);
+       if (f2fs_has_inline_dentry(inode))
+               return f2fs_read_inline_dir(file, ctx);
 
        /* readahead for multi pages of dir */
        if (npages - n > 1 && !ra_has_index(ra, n))
@@ -684,28 +768,12 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
                        continue;
 
                dentry_blk = kmap(dentry_page);
-               while (bit_pos < NR_DENTRY_IN_BLOCK) {
-                       bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
-                                                       NR_DENTRY_IN_BLOCK,
-                                                       bit_pos);
-                       if (bit_pos >= NR_DENTRY_IN_BLOCK)
-                               break;
-
-                       de = &dentry_blk->dentry[bit_pos];
-                       if (de->file_type < F2FS_FT_MAX)
-                               d_type = f2fs_filetype_table[de->file_type];
-                       else
-                               d_type = DT_UNKNOWN;
-                       if (!dir_emit(ctx,
-                                       dentry_blk->filename[bit_pos],
-                                       le16_to_cpu(de->name_len),
-                                       le32_to_cpu(de->ino), d_type))
-                               goto stop;
 
-                       bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
-                       ctx->pos = n * NR_DENTRY_IN_BLOCK + bit_pos;
-               }
-               bit_pos = 0;
+               make_dentry_ptr(&d, (void *)dentry_blk, 1);
+
+               if (f2fs_fill_dentries(ctx, &d, n * NR_DENTRY_IN_BLOCK))
+                       goto stop;
+
                ctx->pos = (n + 1) * NR_DENTRY_IN_BLOCK;
                kunmap(dentry_page);
                f2fs_put_page(dentry_page, 1);