diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-19 15:36:27 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-19 15:36:27 -0400 |
commit | 7e38180e207c8707691c12395e990a5d583c5e71 (patch) | |
tree | 50fc0973873f7bc9455a1faf536a5a5b4681fe56 /fs/btrfs/super.c | |
parent | 236454dfffb64a95ee01c50a215153f5de61c475 (diff) |
Btrfs: directory inode index is back
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 302 |
1 files changed, 43 insertions, 259 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1b286bb26f12..dff2db0d1dc2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -127,32 +127,43 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
127 | struct btrfs_path *path; | 127 | struct btrfs_path *path; |
128 | const char *name = dentry->d_name.name; | 128 | const char *name = dentry->d_name.name; |
129 | int name_len = dentry->d_name.len; | 129 | int name_len = dentry->d_name.len; |
130 | int ret; | 130 | int ret = 0; |
131 | u64 objectid; | 131 | u64 objectid; |
132 | struct btrfs_dir_item *di; | 132 | struct btrfs_dir_item *di; |
133 | 133 | ||
134 | path = btrfs_alloc_path(); | 134 | path = btrfs_alloc_path(); |
135 | BUG_ON(!path); | 135 | BUG_ON(!path); |
136 | btrfs_init_path(path); | 136 | btrfs_init_path(path); |
137 | ret = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, | 137 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, |
138 | name, name_len, -1); | 138 | name, name_len, -1); |
139 | if (ret < 0) | 139 | if (IS_ERR(di)) { |
140 | ret = PTR_ERR(di); | ||
140 | goto err; | 141 | goto err; |
141 | if (ret > 0) { | 142 | } |
143 | if (!di) { | ||
142 | ret = -ENOENT; | 144 | ret = -ENOENT; |
143 | goto err; | 145 | goto err; |
144 | } | 146 | } |
145 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | ||
146 | struct btrfs_dir_item); | ||
147 | objectid = btrfs_disk_key_objectid(&di->location); | 147 | objectid = btrfs_disk_key_objectid(&di->location); |
148 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
149 | BUG_ON(ret); | ||
150 | btrfs_release_path(root, path); | ||
148 | 151 | ||
149 | ret = btrfs_del_item(trans, root, path); | 152 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, |
153 | objectid, name, name_len, -1); | ||
154 | if (IS_ERR(di)) { | ||
155 | ret = PTR_ERR(di); | ||
156 | goto err; | ||
157 | } | ||
158 | if (!di) { | ||
159 | ret = -ENOENT; | ||
160 | goto err; | ||
161 | } | ||
162 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
150 | BUG_ON(ret); | 163 | BUG_ON(ret); |
151 | 164 | ||
152 | btrfs_release_path(root, path); | ||
153 | dentry->d_inode->i_ctime = dir->i_ctime; | 165 | dentry->d_inode->i_ctime = dir->i_ctime; |
154 | err: | 166 | err: |
155 | btrfs_release_path(root, path); | ||
156 | btrfs_free_path(path); | 167 | btrfs_free_path(path); |
157 | if (ret == 0) { | 168 | if (ret == 0) { |
158 | inode_dec_link_count(dentry->d_inode); | 169 | inode_dec_link_count(dentry->d_inode); |
@@ -388,15 +399,13 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
388 | path = btrfs_alloc_path(); | 399 | path = btrfs_alloc_path(); |
389 | BUG_ON(!path); | 400 | BUG_ON(!path); |
390 | btrfs_init_path(path); | 401 | btrfs_init_path(path); |
391 | ret = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name, | 402 | di = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name, |
392 | namelen, 0); | 403 | namelen, 0); |
393 | if (ret || !btrfs_match_dir_item_name(root, path, name, namelen)) { | 404 | if (!di || IS_ERR(di)) { |
394 | location->objectid = 0; | 405 | location->objectid = 0; |
395 | ret = 0; | 406 | ret = 0; |
396 | goto out; | 407 | goto out; |
397 | } | 408 | } |
398 | di = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | ||
399 | struct btrfs_dir_item); | ||
400 | btrfs_disk_key_to_cpu(location, &di->location); | 409 | btrfs_disk_key_to_cpu(location, &di->location); |
401 | out: | 410 | out: |
402 | btrfs_release_path(root, path); | 411 | btrfs_release_path(root, path); |
@@ -523,7 +532,10 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
523 | int advance; | 532 | int advance; |
524 | unsigned char d_type = DT_UNKNOWN; | 533 | unsigned char d_type = DT_UNKNOWN; |
525 | int over = 0; | 534 | int over = 0; |
526 | int key_type = BTRFS_DIR_ITEM_KEY; | 535 | u32 di_cur; |
536 | u32 di_total; | ||
537 | u32 di_len; | ||
538 | int key_type = BTRFS_DIR_INDEX_KEY; | ||
527 | 539 | ||
528 | /* FIXME, use a real flag for deciding about the key type */ | 540 | /* FIXME, use a real flag for deciding about the key type */ |
529 | if (root->fs_info->tree_root == root) | 541 | if (root->fs_info->tree_root == root) |
@@ -567,12 +579,20 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
567 | filp->f_pos = btrfs_disk_key_offset(&item->key); | 579 | filp->f_pos = btrfs_disk_key_offset(&item->key); |
568 | advance = 1; | 580 | advance = 1; |
569 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 581 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
570 | over = filldir(dirent, (const char *)(di + 1), | 582 | di_cur = 0; |
571 | btrfs_dir_name_len(di), | 583 | di_total = btrfs_item_size(leaf->items + slot); |
572 | btrfs_disk_key_offset(&item->key), | 584 | while(di_cur < di_total) { |
573 | btrfs_disk_key_objectid(&di->location), d_type); | 585 | over = filldir(dirent, (const char *)(di + 1), |
574 | if (over) | 586 | btrfs_dir_name_len(di), |
575 | goto nopos; | 587 | btrfs_disk_key_offset(&item->key), |
588 | btrfs_disk_key_objectid(&di->location), | ||
589 | d_type); | ||
590 | if (over) | ||
591 | goto nopos; | ||
592 | di_len = btrfs_dir_name_len(di) + sizeof(*di); | ||
593 | di_cur += di_len; | ||
594 | di = (struct btrfs_dir_item *)((char *)di + di_len); | ||
595 | } | ||
576 | } | 596 | } |
577 | filp->f_pos++; | 597 | filp->f_pos++; |
578 | nopos: | 598 | nopos: |
@@ -935,75 +955,6 @@ printk("btrfs sync_fs\n"); | |||
935 | return 0; | 955 | return 0; |
936 | } | 956 | } |
937 | 957 | ||
938 | #if 0 | ||
939 | static int btrfs_get_block_inline(struct inode *inode, sector_t iblock, | ||
940 | struct buffer_head *result, int create) | ||
941 | { | ||
942 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | ||
943 | struct btrfs_path *path; | ||
944 | struct btrfs_key key; | ||
945 | struct btrfs_leaf *leaf; | ||
946 | int num_bytes = result->b_size; | ||
947 | int item_size; | ||
948 | int ret; | ||
949 | u64 pos; | ||
950 | char *ptr; | ||
951 | int copy_size; | ||
952 | int err = 0; | ||
953 | char *safe_ptr; | ||
954 | char *data_ptr; | ||
955 | |||
956 | path = btrfs_alloc_path(); | ||
957 | BUG_ON(!path); | ||
958 | |||
959 | WARN_ON(create); | ||
960 | if (create) { | ||
961 | return 0; | ||
962 | } | ||
963 | pos = iblock << inode->i_blkbits; | ||
964 | key.objectid = inode->i_ino; | ||
965 | key.flags = 0; | ||
966 | btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY); | ||
967 | ptr = kmap(result->b_page); | ||
968 | safe_ptr = ptr; | ||
969 | ptr += (pos & (PAGE_CACHE_SIZE -1)); | ||
970 | again: | ||
971 | key.offset = pos; | ||
972 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
973 | if (ret) { | ||
974 | if (ret < 0) | ||
975 | err = ret; | ||
976 | else | ||
977 | err = 0; | ||
978 | goto out; | ||
979 | } | ||
980 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
981 | item_size = btrfs_item_size(leaf->items + path->slots[0]); | ||
982 | copy_size = min(num_bytes, item_size); | ||
983 | data_ptr = btrfs_item_ptr(leaf, path->slots[0], char); | ||
984 | WARN_ON(safe_ptr + PAGE_CACHE_SIZE < ptr + copy_size); | ||
985 | memcpy(ptr, data_ptr, copy_size); | ||
986 | pos += copy_size; | ||
987 | num_bytes -= copy_size; | ||
988 | WARN_ON(num_bytes < 0); | ||
989 | ptr += copy_size; | ||
990 | btrfs_release_path(root, path); | ||
991 | if (num_bytes != 0) { | ||
992 | if (pos >= i_size_read(inode)) | ||
993 | memset(ptr, 0, num_bytes); | ||
994 | else | ||
995 | goto again; | ||
996 | } | ||
997 | set_buffer_uptodate(result); | ||
998 | map_bh(result, inode->i_sb, 0); | ||
999 | err = 0; | ||
1000 | out: | ||
1001 | btrfs_free_path(path); | ||
1002 | kunmap(result->b_page); | ||
1003 | return err; | ||
1004 | } | ||
1005 | #endif | ||
1006 | |||
1007 | static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | 958 | static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, |
1008 | struct buffer_head *result, int create) | 959 | struct buffer_head *result, int create) |
1009 | { | 960 | { |
@@ -1907,174 +1858,6 @@ out: | |||
1907 | return num_written ? num_written : err; | 1858 | return num_written ? num_written : err; |
1908 | } | 1859 | } |
1909 | 1860 | ||
1910 | #if 0 | ||
1911 | static ssize_t inline_one_page(struct btrfs_root *root, struct inode *inode, | ||
1912 | struct page *page, loff_t pos, | ||
1913 | size_t offset, size_t write_bytes) | ||
1914 | { | ||
1915 | struct btrfs_path *path; | ||
1916 | struct btrfs_trans_handle *trans; | ||
1917 | struct btrfs_key key; | ||
1918 | struct btrfs_leaf *leaf; | ||
1919 | struct btrfs_key found_key; | ||
1920 | int ret; | ||
1921 | size_t copy_size = 0; | ||
1922 | char *dst = NULL; | ||
1923 | int err = 0; | ||
1924 | size_t num_written = 0; | ||
1925 | |||
1926 | path = btrfs_alloc_path(); | ||
1927 | BUG_ON(!path); | ||
1928 | mutex_lock(&root->fs_info->fs_mutex); | ||
1929 | trans = btrfs_start_transaction(root, 1); | ||
1930 | key.objectid = inode->i_ino; | ||
1931 | key.flags = 0; | ||
1932 | btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY); | ||
1933 | |||
1934 | again: | ||
1935 | key.offset = pos; | ||
1936 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); | ||
1937 | if (ret < 0) { | ||
1938 | err = ret; | ||
1939 | goto out; | ||
1940 | } | ||
1941 | if (ret == 0) { | ||
1942 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
1943 | btrfs_disk_key_to_cpu(&found_key, | ||
1944 | &leaf->items[path->slots[0]].key); | ||
1945 | copy_size = btrfs_item_size(leaf->items + path->slots[0]); | ||
1946 | dst = btrfs_item_ptr(leaf, path->slots[0], char); | ||
1947 | copy_size = min(write_bytes, copy_size); | ||
1948 | goto copyit; | ||
1949 | } else { | ||
1950 | int slot = path->slots[0]; | ||
1951 | if (slot > 0) { | ||
1952 | slot--; | ||
1953 | } | ||
1954 | // FIXME find max key | ||
1955 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
1956 | btrfs_disk_key_to_cpu(&found_key, | ||
1957 | &leaf->items[slot].key); | ||
1958 | if (found_key.objectid != inode->i_ino) | ||
1959 | goto insert; | ||
1960 | if (btrfs_key_type(&found_key) != BTRFS_INLINE_DATA_KEY) | ||
1961 | goto insert; | ||
1962 | copy_size = btrfs_item_size(leaf->items + slot); | ||
1963 | if (found_key.offset + copy_size <= pos) | ||
1964 | goto insert; | ||
1965 | dst = btrfs_item_ptr(leaf, path->slots[0], char); | ||
1966 | dst += pos - found_key.offset; | ||
1967 | copy_size = copy_size - (pos - found_key.offset); | ||
1968 | BUG_ON(copy_size < 0); | ||
1969 | copy_size = min(write_bytes, copy_size); | ||
1970 | WARN_ON(copy_size == 0); | ||
1971 | goto copyit; | ||
1972 | } | ||
1973 | insert: | ||
1974 | btrfs_release_path(root, path); | ||
1975 | copy_size = min(write_bytes, | ||
1976 | (size_t)BTRFS_LEAF_DATA_SIZE(root) - | ||
1977 | sizeof(struct btrfs_item) * 4); | ||
1978 | ret = btrfs_insert_empty_item(trans, root, path, &key, copy_size); | ||
1979 | BUG_ON(ret); | ||
1980 | dst = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
1981 | path->slots[0], char); | ||
1982 | copyit: | ||
1983 | WARN_ON(copy_size == 0); | ||
1984 | WARN_ON(dst + copy_size > | ||
1985 | btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
1986 | path->slots[0], char) + | ||
1987 | btrfs_item_size(btrfs_buffer_leaf(path->nodes[0])->items + | ||
1988 | path->slots[0])); | ||
1989 | btrfs_memcpy(root, path->nodes[0]->b_data, dst, | ||
1990 | page_address(page) + offset, copy_size); | ||
1991 | mark_buffer_dirty(path->nodes[0]); | ||
1992 | btrfs_release_path(root, path); | ||
1993 | pos += copy_size; | ||
1994 | offset += copy_size; | ||
1995 | num_written += copy_size; | ||
1996 | write_bytes -= copy_size; | ||
1997 | if (write_bytes) | ||
1998 | goto again; | ||
1999 | out: | ||
2000 | btrfs_free_path(path); | ||
2001 | ret = btrfs_end_transaction(trans, root); | ||
2002 | BUG_ON(ret); | ||
2003 | mutex_unlock(&root->fs_info->fs_mutex); | ||
2004 | return num_written ? num_written : err; | ||
2005 | } | ||
2006 | |||
2007 | static ssize_t btrfs_file_inline_write(struct file *file, | ||
2008 | const char __user *buf, | ||
2009 | size_t count, loff_t *ppos) | ||
2010 | { | ||
2011 | loff_t pos; | ||
2012 | size_t num_written = 0; | ||
2013 | int err = 0; | ||
2014 | int ret = 0; | ||
2015 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2016 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
2017 | unsigned long page_index; | ||
2018 | |||
2019 | if (file->f_flags & O_DIRECT) | ||
2020 | return -EINVAL; | ||
2021 | pos = *ppos; | ||
2022 | |||
2023 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | ||
2024 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | ||
2025 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | ||
2026 | if (err) | ||
2027 | goto out; | ||
2028 | if (count == 0) | ||
2029 | goto out; | ||
2030 | err = remove_suid(file->f_path.dentry); | ||
2031 | if (err) | ||
2032 | goto out; | ||
2033 | file_update_time(file); | ||
2034 | mutex_lock(&inode->i_mutex); | ||
2035 | while(count > 0) { | ||
2036 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); | ||
2037 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); | ||
2038 | struct page *page; | ||
2039 | |||
2040 | page_index = pos >> PAGE_CACHE_SHIFT; | ||
2041 | page = grab_cache_page(inode->i_mapping, page_index); | ||
2042 | if (!PageUptodate(page)) { | ||
2043 | ret = mpage_readpage(page, btrfs_get_block); | ||
2044 | BUG_ON(ret); | ||
2045 | lock_page(page); | ||
2046 | } | ||
2047 | ret = btrfs_copy_from_user(pos, 1, | ||
2048 | write_bytes, &page, buf); | ||
2049 | BUG_ON(ret); | ||
2050 | write_bytes = inline_one_page(root, inode, page, pos, | ||
2051 | offset, write_bytes); | ||
2052 | SetPageUptodate(page); | ||
2053 | if (write_bytes > 0 && pos + write_bytes > inode->i_size) { | ||
2054 | i_size_write(inode, pos + write_bytes); | ||
2055 | mark_inode_dirty(inode); | ||
2056 | } | ||
2057 | page_cache_release(page); | ||
2058 | unlock_page(page); | ||
2059 | if (write_bytes < 0) | ||
2060 | goto out_unlock; | ||
2061 | buf += write_bytes; | ||
2062 | count -= write_bytes; | ||
2063 | pos += write_bytes; | ||
2064 | num_written += write_bytes; | ||
2065 | |||
2066 | balance_dirty_pages_ratelimited(inode->i_mapping); | ||
2067 | cond_resched(); | ||
2068 | } | ||
2069 | out_unlock: | ||
2070 | mutex_unlock(&inode->i_mutex); | ||
2071 | out: | ||
2072 | *ppos = pos; | ||
2073 | current->backing_dev_info = NULL; | ||
2074 | return num_written ? num_written : err; | ||
2075 | } | ||
2076 | #endif | ||
2077 | |||
2078 | static int btrfs_read_actor(read_descriptor_t *desc, struct page *page, | 1861 | static int btrfs_read_actor(read_descriptor_t *desc, struct page *page, |
2079 | unsigned long offset, unsigned long size) | 1862 | unsigned long offset, unsigned long size) |
2080 | { | 1863 | { |
@@ -2422,6 +2205,7 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | |||
2422 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2205 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2423 | struct btrfs_ioctl_vol_args vol_args; | 2206 | struct btrfs_ioctl_vol_args vol_args; |
2424 | int ret = 0; | 2207 | int ret = 0; |
2208 | struct btrfs_dir_item *di; | ||
2425 | int namelen; | 2209 | int namelen; |
2426 | struct btrfs_path *path; | 2210 | struct btrfs_path *path; |
2427 | u64 root_dirid; | 2211 | u64 root_dirid; |
@@ -2440,12 +2224,12 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | |||
2440 | return -ENOMEM; | 2224 | return -ENOMEM; |
2441 | root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, | 2225 | root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, |
2442 | mutex_lock(&root->fs_info->fs_mutex); | 2226 | mutex_lock(&root->fs_info->fs_mutex); |
2443 | ret = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, | 2227 | di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, |
2444 | path, root_dirid, | 2228 | path, root_dirid, |
2445 | vol_args.name, namelen, 0); | 2229 | vol_args.name, namelen, 0); |
2446 | mutex_unlock(&root->fs_info->fs_mutex); | 2230 | mutex_unlock(&root->fs_info->fs_mutex); |
2447 | btrfs_free_path(path); | 2231 | btrfs_free_path(path); |
2448 | if (ret == 0) | 2232 | if (di && !IS_ERR(di)) |
2449 | return -EEXIST; | 2233 | return -EEXIST; |
2450 | 2234 | ||
2451 | if (root == root->fs_info->tree_root) | 2235 | if (root == root->fs_info->tree_root) |