diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-06-07 22:13:21 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-06-07 22:13:21 -0400 |
commit | fabb568183de7996257080260d3537fa75b3667e (patch) | |
tree | 60d047f6d5b264347e8f51f16ccd6dc07277c23d /fs/btrfs/super.c | |
parent | fbdc762b4e1833b5d75cada5aabeadccd8379792 (diff) |
Btrfs: d_type optimization
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 0eb64d6eaf9d..b58b4cf66766 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -43,6 +43,18 @@ static int drop_extents(struct btrfs_trans_handle *trans, | |||
43 | static int btrfs_get_block(struct inode *inode, sector_t iblock, | 43 | static int btrfs_get_block(struct inode *inode, sector_t iblock, |
44 | struct buffer_head *result, int create); | 44 | struct buffer_head *result, int create); |
45 | 45 | ||
46 | |||
47 | #define S_SHIFT 12 | ||
48 | static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { | ||
49 | [S_IFREG >> S_SHIFT] = BTRFS_FT_REG_FILE, | ||
50 | [S_IFDIR >> S_SHIFT] = BTRFS_FT_DIR, | ||
51 | [S_IFCHR >> S_SHIFT] = BTRFS_FT_CHRDEV, | ||
52 | [S_IFBLK >> S_SHIFT] = BTRFS_FT_BLKDEV, | ||
53 | [S_IFIFO >> S_SHIFT] = BTRFS_FT_FIFO, | ||
54 | [S_IFSOCK >> S_SHIFT] = BTRFS_FT_SOCK, | ||
55 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, | ||
56 | }; | ||
57 | |||
46 | static void btrfs_read_locked_inode(struct inode *inode) | 58 | static void btrfs_read_locked_inode(struct inode *inode) |
47 | { | 59 | { |
48 | struct btrfs_path *path; | 60 | struct btrfs_path *path; |
@@ -785,6 +797,9 @@ static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path, | |||
785 | break; | 797 | break; |
786 | } | 798 | } |
787 | } | 799 | } |
800 | static unsigned char btrfs_filetype_table[] = { | ||
801 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK | ||
802 | }; | ||
788 | 803 | ||
789 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 804 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
790 | { | 805 | { |
@@ -799,7 +814,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
799 | struct btrfs_leaf *leaf; | 814 | struct btrfs_leaf *leaf; |
800 | int slot; | 815 | int slot; |
801 | int advance; | 816 | int advance; |
802 | unsigned char d_type = DT_UNKNOWN; | 817 | unsigned char d_type; |
803 | int over = 0; | 818 | int over = 0; |
804 | u32 di_cur; | 819 | u32 di_cur; |
805 | u32 di_total; | 820 | u32 di_total; |
@@ -853,6 +868,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
853 | di_cur = 0; | 868 | di_cur = 0; |
854 | di_total = btrfs_item_size(leaf->items + slot); | 869 | di_total = btrfs_item_size(leaf->items + slot); |
855 | while(di_cur < di_total) { | 870 | while(di_cur < di_total) { |
871 | d_type = btrfs_filetype_table[btrfs_dir_type(di)]; | ||
856 | over = filldir(dirent, (const char *)(di + 1), | 872 | over = filldir(dirent, (const char *)(di + 1), |
857 | btrfs_dir_name_len(di), | 873 | btrfs_dir_name_len(di), |
858 | btrfs_disk_key_offset(&item->key), | 874 | btrfs_disk_key_offset(&item->key), |
@@ -1012,6 +1028,11 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
1012 | return inode; | 1028 | return inode; |
1013 | } | 1029 | } |
1014 | 1030 | ||
1031 | static inline u8 btrfs_inode_type(struct inode *inode) | ||
1032 | { | ||
1033 | return btrfs_type_by_mode[(inode->i_mode & S_IFMT) >> S_SHIFT]; | ||
1034 | } | ||
1035 | |||
1015 | static int btrfs_add_link(struct btrfs_trans_handle *trans, | 1036 | static int btrfs_add_link(struct btrfs_trans_handle *trans, |
1016 | struct dentry *dentry, struct inode *inode) | 1037 | struct dentry *dentry, struct inode *inode) |
1017 | { | 1038 | { |
@@ -1026,7 +1047,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
1026 | ret = btrfs_insert_dir_item(trans, root, | 1047 | ret = btrfs_insert_dir_item(trans, root, |
1027 | dentry->d_name.name, dentry->d_name.len, | 1048 | dentry->d_name.name, dentry->d_name.len, |
1028 | dentry->d_parent->d_inode->i_ino, | 1049 | dentry->d_parent->d_inode->i_ino, |
1029 | &key, 0); | 1050 | &key, btrfs_inode_type(inode)); |
1030 | if (ret == 0) { | 1051 | if (ret == 0) { |
1031 | dentry->d_parent->d_inode->i_size += dentry->d_name.len * 2; | 1052 | dentry->d_parent->d_inode->i_size += dentry->d_name.len * 2; |
1032 | ret = btrfs_update_inode(trans, root, | 1053 | ret = btrfs_update_inode(trans, root, |
@@ -1150,12 +1171,12 @@ static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans, | |||
1150 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 1171 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
1151 | 1172 | ||
1152 | ret = btrfs_insert_dir_item(trans, root, buf, 1, objectid, | 1173 | ret = btrfs_insert_dir_item(trans, root, buf, 1, objectid, |
1153 | &key, 1); | 1174 | &key, BTRFS_FT_DIR); |
1154 | if (ret) | 1175 | if (ret) |
1155 | goto error; | 1176 | goto error; |
1156 | key.objectid = dirid; | 1177 | key.objectid = dirid; |
1157 | ret = btrfs_insert_dir_item(trans, root, buf, 2, objectid, | 1178 | ret = btrfs_insert_dir_item(trans, root, buf, 2, objectid, |
1158 | &key, 1); | 1179 | &key, BTRFS_FT_DIR); |
1159 | if (ret) | 1180 | if (ret) |
1160 | goto error; | 1181 | goto error; |
1161 | error: | 1182 | error: |
@@ -1265,6 +1286,10 @@ printk("btrfs sync_fs\n"); | |||
1265 | return 0; | 1286 | return 0; |
1266 | } | 1287 | } |
1267 | 1288 | ||
1289 | #define BTRFS_GET_BLOCK_NO_CREATE 0 | ||
1290 | #define BTRFS_GET_BLOCK_CREATE 1 | ||
1291 | #define BTRFS_GET_BLOCK_NO_DIRECT 2 | ||
1292 | |||
1268 | static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | 1293 | static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, |
1269 | struct buffer_head *result, int create) | 1294 | struct buffer_head *result, int create) |
1270 | { | 1295 | { |
@@ -1286,7 +1311,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1286 | path = btrfs_alloc_path(); | 1311 | path = btrfs_alloc_path(); |
1287 | BUG_ON(!path); | 1312 | BUG_ON(!path); |
1288 | btrfs_init_path(path); | 1313 | btrfs_init_path(path); |
1289 | if (create) { | 1314 | if (create & BTRFS_GET_BLOCK_CREATE) { |
1290 | WARN_ON(1); | 1315 | WARN_ON(1); |
1291 | /* this almost but not quite works */ | 1316 | /* this almost but not quite works */ |
1292 | trans = btrfs_start_transaction(root, 1); | 1317 | trans = btrfs_start_transaction(root, 1); |
@@ -1349,6 +1374,11 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1349 | char *ptr; | 1374 | char *ptr; |
1350 | char *map; | 1375 | char *map; |
1351 | u32 size; | 1376 | u32 size; |
1377 | |||
1378 | if (create & BTRFS_GET_BLOCK_NO_DIRECT) { | ||
1379 | err = -EINVAL; | ||
1380 | goto out; | ||
1381 | } | ||
1352 | size = btrfs_file_extent_inline_len(leaf->items + | 1382 | size = btrfs_file_extent_inline_len(leaf->items + |
1353 | path->slots[0]); | 1383 | path->slots[0]); |
1354 | extent_end = (extent_start + size) >> inode->i_blkbits; | 1384 | extent_end = (extent_start + size) >> inode->i_blkbits; |
@@ -1367,7 +1397,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1367 | btrfs_map_bh_to_logical(root, result, 0); | 1397 | btrfs_map_bh_to_logical(root, result, 0); |
1368 | } | 1398 | } |
1369 | not_found: | 1399 | not_found: |
1370 | if (create) { | 1400 | if (create & BTRFS_GET_BLOCK_CREATE) { |
1371 | struct btrfs_key ins; | 1401 | struct btrfs_key ins; |
1372 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, | 1402 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, |
1373 | 1, alloc_hint, (u64)-1, | 1403 | 1, alloc_hint, (u64)-1, |
@@ -1399,6 +1429,21 @@ static int btrfs_get_block(struct inode *inode, sector_t iblock, | |||
1399 | return err; | 1429 | return err; |
1400 | } | 1430 | } |
1401 | 1431 | ||
1432 | static int btrfs_get_block_bmap(struct inode *inode, sector_t iblock, | ||
1433 | struct buffer_head *result, int create) | ||
1434 | { | ||
1435 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1436 | mutex_lock(&root->fs_info->fs_mutex); | ||
1437 | btrfs_get_block_lock(inode, iblock, result, BTRFS_GET_BLOCK_NO_DIRECT); | ||
1438 | mutex_unlock(&root->fs_info->fs_mutex); | ||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | static sector_t btrfs_bmap(struct address_space *as, sector_t block) | ||
1443 | { | ||
1444 | return generic_block_bmap(as, block, btrfs_get_block_bmap); | ||
1445 | } | ||
1446 | |||
1402 | static int btrfs_prepare_write(struct file *file, struct page *page, | 1447 | static int btrfs_prepare_write(struct file *file, struct page *page, |
1403 | unsigned from, unsigned to) | 1448 | unsigned from, unsigned to) |
1404 | { | 1449 | { |
@@ -2428,7 +2473,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
2428 | key.offset = (u64)-1; | 2473 | key.offset = (u64)-1; |
2429 | dir = root->fs_info->sb->s_root->d_inode; | 2474 | dir = root->fs_info->sb->s_root->d_inode; |
2430 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, | 2475 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, |
2431 | name, namelen, dir->i_ino, &key, 0); | 2476 | name, namelen, dir->i_ino, &key, |
2477 | BTRFS_FT_DIR); | ||
2432 | BUG_ON(ret); | 2478 | BUG_ON(ret); |
2433 | 2479 | ||
2434 | ret = btrfs_commit_transaction(trans, root); | 2480 | ret = btrfs_commit_transaction(trans, root); |
@@ -2505,7 +2551,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2505 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, | 2551 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, |
2506 | name, namelen, | 2552 | name, namelen, |
2507 | root->fs_info->sb->s_root->d_inode->i_ino, | 2553 | root->fs_info->sb->s_root->d_inode->i_ino, |
2508 | &key, 0); | 2554 | &key, BTRFS_FT_DIR); |
2509 | 2555 | ||
2510 | BUG_ON(ret); | 2556 | BUG_ON(ret); |
2511 | 2557 | ||
@@ -2833,7 +2879,8 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
2833 | btrfs_release_path(root, path); | 2879 | btrfs_release_path(root, path); |
2834 | 2880 | ||
2835 | ret = btrfs_insert_dir_item(trans, root, "..", 2, | 2881 | ret = btrfs_insert_dir_item(trans, root, "..", 2, |
2836 | old_inode->i_ino, location, 0); | 2882 | old_inode->i_ino, location, |
2883 | BTRFS_FT_DIR); | ||
2837 | if (ret) | 2884 | if (ret) |
2838 | goto out_fail; | 2885 | goto out_fail; |
2839 | } | 2886 | } |
@@ -3003,6 +3050,7 @@ static struct address_space_operations btrfs_aops = { | |||
3003 | .sync_page = block_sync_page, | 3050 | .sync_page = block_sync_page, |
3004 | .prepare_write = btrfs_prepare_write, | 3051 | .prepare_write = btrfs_prepare_write, |
3005 | .commit_write = btrfs_commit_write, | 3052 | .commit_write = btrfs_commit_write, |
3053 | .bmap = btrfs_bmap, | ||
3006 | }; | 3054 | }; |
3007 | 3055 | ||
3008 | static struct address_space_operations btrfs_symlink_aops = { | 3056 | static struct address_space_operations btrfs_symlink_aops = { |