diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/backref.c | 68 | ||||
-rw-r--r-- | fs/btrfs/backref.h | 5 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 53 | ||||
-rw-r--r-- | fs/btrfs/hash.h | 10 | ||||
-rw-r--r-- | fs/btrfs/inode-item.c | 285 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 23 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 345 |
7 files changed, 710 insertions, 79 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 7084431b7c9c..dc963121d1db 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -1109,6 +1109,74 @@ static int inode_ref_info(u64 inum, u64 ioff, struct btrfs_root *fs_root, | |||
1109 | found_key); | 1109 | found_key); |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, | ||
1113 | u64 start_off, struct btrfs_path *path, | ||
1114 | struct btrfs_inode_extref **ret_extref, | ||
1115 | u64 *found_off) | ||
1116 | { | ||
1117 | int ret, slot; | ||
1118 | struct btrfs_key key; | ||
1119 | struct btrfs_key found_key; | ||
1120 | struct btrfs_inode_extref *extref; | ||
1121 | struct extent_buffer *leaf; | ||
1122 | unsigned long ptr; | ||
1123 | |||
1124 | key.objectid = inode_objectid; | ||
1125 | btrfs_set_key_type(&key, BTRFS_INODE_EXTREF_KEY); | ||
1126 | key.offset = start_off; | ||
1127 | |||
1128 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
1129 | if (ret < 0) | ||
1130 | return ret; | ||
1131 | |||
1132 | while (1) { | ||
1133 | leaf = path->nodes[0]; | ||
1134 | slot = path->slots[0]; | ||
1135 | if (slot >= btrfs_header_nritems(leaf)) { | ||
1136 | /* | ||
1137 | * If the item at offset is not found, | ||
1138 | * btrfs_search_slot will point us to the slot | ||
1139 | * where it should be inserted. In our case | ||
1140 | * that will be the slot directly before the | ||
1141 | * next INODE_REF_KEY_V2 item. In the case | ||
1142 | * that we're pointing to the last slot in a | ||
1143 | * leaf, we must move one leaf over. | ||
1144 | */ | ||
1145 | ret = btrfs_next_leaf(root, path); | ||
1146 | if (ret) { | ||
1147 | if (ret >= 1) | ||
1148 | ret = -ENOENT; | ||
1149 | break; | ||
1150 | } | ||
1151 | continue; | ||
1152 | } | ||
1153 | |||
1154 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
1155 | |||
1156 | /* | ||
1157 | * Check that we're still looking at an extended ref key for | ||
1158 | * this particular objectid. If we have different | ||
1159 | * objectid or type then there are no more to be found | ||
1160 | * in the tree and we can exit. | ||
1161 | */ | ||
1162 | ret = -ENOENT; | ||
1163 | if (found_key.objectid != inode_objectid) | ||
1164 | break; | ||
1165 | if (btrfs_key_type(&found_key) != BTRFS_INODE_EXTREF_KEY) | ||
1166 | break; | ||
1167 | |||
1168 | ret = 0; | ||
1169 | ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); | ||
1170 | extref = (struct btrfs_inode_extref *)ptr; | ||
1171 | *ret_extref = extref; | ||
1172 | if (found_off) | ||
1173 | *found_off = found_key.offset; | ||
1174 | break; | ||
1175 | } | ||
1176 | |||
1177 | return ret; | ||
1178 | } | ||
1179 | |||
1112 | /* | 1180 | /* |
1113 | * this iterates to turn a btrfs_inode_ref into a full filesystem path. elements | 1181 | * this iterates to turn a btrfs_inode_ref into a full filesystem path. elements |
1114 | * of the path are separated by '/' and the path is guaranteed to be | 1182 | * of the path are separated by '/' and the path is guaranteed to be |
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index 4fda5d8029a7..0b920c113952 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h | |||
@@ -70,4 +70,9 @@ struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, | |||
70 | struct btrfs_path *path); | 70 | struct btrfs_path *path); |
71 | void free_ipath(struct inode_fs_paths *ipath); | 71 | void free_ipath(struct inode_fs_paths *ipath); |
72 | 72 | ||
73 | int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, | ||
74 | u64 start_off, struct btrfs_path *path, | ||
75 | struct btrfs_inode_extref **ret_extref, | ||
76 | u64 *found_off); | ||
77 | |||
73 | #endif | 78 | #endif |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 399521ab61da..50dcd0fbae11 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -154,6 +154,13 @@ struct btrfs_ordered_sum; | |||
154 | */ | 154 | */ |
155 | #define BTRFS_NAME_LEN 255 | 155 | #define BTRFS_NAME_LEN 255 |
156 | 156 | ||
157 | /* | ||
158 | * Theoretical limit is larger, but we keep this down to a sane | ||
159 | * value. That should limit greatly the possibility of collisions on | ||
160 | * inode ref items. | ||
161 | */ | ||
162 | #define BTRFS_LINK_MAX 65535U | ||
163 | |||
157 | /* 32 bytes in various csum fields */ | 164 | /* 32 bytes in various csum fields */ |
158 | #define BTRFS_CSUM_SIZE 32 | 165 | #define BTRFS_CSUM_SIZE 32 |
159 | 166 | ||
@@ -489,6 +496,8 @@ struct btrfs_super_block { | |||
489 | */ | 496 | */ |
490 | #define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) | 497 | #define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) |
491 | 498 | ||
499 | #define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) | ||
500 | |||
492 | #define BTRFS_FEATURE_COMPAT_SUPP 0ULL | 501 | #define BTRFS_FEATURE_COMPAT_SUPP 0ULL |
493 | #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL | 502 | #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL |
494 | #define BTRFS_FEATURE_INCOMPAT_SUPP \ | 503 | #define BTRFS_FEATURE_INCOMPAT_SUPP \ |
@@ -496,7 +505,8 @@ struct btrfs_super_block { | |||
496 | BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ | 505 | BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ |
497 | BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \ | 506 | BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \ |
498 | BTRFS_FEATURE_INCOMPAT_BIG_METADATA | \ | 507 | BTRFS_FEATURE_INCOMPAT_BIG_METADATA | \ |
499 | BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO) | 508 | BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO | \ |
509 | BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF) | ||
500 | 510 | ||
501 | /* | 511 | /* |
502 | * A leaf is full of items. offset and size tell us where to find | 512 | * A leaf is full of items. offset and size tell us where to find |
@@ -643,6 +653,14 @@ struct btrfs_inode_ref { | |||
643 | /* name goes here */ | 653 | /* name goes here */ |
644 | } __attribute__ ((__packed__)); | 654 | } __attribute__ ((__packed__)); |
645 | 655 | ||
656 | struct btrfs_inode_extref { | ||
657 | __le64 parent_objectid; | ||
658 | __le64 index; | ||
659 | __le16 name_len; | ||
660 | __u8 name[0]; | ||
661 | /* name goes here */ | ||
662 | } __attribute__ ((__packed__)); | ||
663 | |||
646 | struct btrfs_timespec { | 664 | struct btrfs_timespec { |
647 | __le64 sec; | 665 | __le64 sec; |
648 | __le32 nsec; | 666 | __le32 nsec; |
@@ -1601,6 +1619,7 @@ struct btrfs_ioctl_defrag_range_args { | |||
1601 | */ | 1619 | */ |
1602 | #define BTRFS_INODE_ITEM_KEY 1 | 1620 | #define BTRFS_INODE_ITEM_KEY 1 |
1603 | #define BTRFS_INODE_REF_KEY 12 | 1621 | #define BTRFS_INODE_REF_KEY 12 |
1622 | #define BTRFS_INODE_EXTREF_KEY 13 | ||
1604 | #define BTRFS_XATTR_ITEM_KEY 24 | 1623 | #define BTRFS_XATTR_ITEM_KEY 24 |
1605 | #define BTRFS_ORPHAN_ITEM_KEY 48 | 1624 | #define BTRFS_ORPHAN_ITEM_KEY 48 |
1606 | /* reserve 2-15 close to the inode for later flexibility */ | 1625 | /* reserve 2-15 close to the inode for later flexibility */ |
@@ -1987,6 +2006,13 @@ BTRFS_SETGET_STACK_FUNCS(block_group_flags, | |||
1987 | BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16); | 2006 | BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16); |
1988 | BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64); | 2007 | BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64); |
1989 | 2008 | ||
2009 | /* struct btrfs_inode_extref */ | ||
2010 | BTRFS_SETGET_FUNCS(inode_extref_parent, struct btrfs_inode_extref, | ||
2011 | parent_objectid, 64); | ||
2012 | BTRFS_SETGET_FUNCS(inode_extref_name_len, struct btrfs_inode_extref, | ||
2013 | name_len, 16); | ||
2014 | BTRFS_SETGET_FUNCS(inode_extref_index, struct btrfs_inode_extref, index, 64); | ||
2015 | |||
1990 | /* struct btrfs_inode_item */ | 2016 | /* struct btrfs_inode_item */ |
1991 | BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64); | 2017 | BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64); |
1992 | BTRFS_SETGET_FUNCS(inode_sequence, struct btrfs_inode_item, sequence, 64); | 2018 | BTRFS_SETGET_FUNCS(inode_sequence, struct btrfs_inode_item, sequence, 64); |
@@ -3184,12 +3210,12 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, | |||
3184 | struct btrfs_root *root, | 3210 | struct btrfs_root *root, |
3185 | const char *name, int name_len, | 3211 | const char *name, int name_len, |
3186 | u64 inode_objectid, u64 ref_objectid, u64 *index); | 3212 | u64 inode_objectid, u64 ref_objectid, u64 *index); |
3187 | struct btrfs_inode_ref * | 3213 | int btrfs_get_inode_ref_index(struct btrfs_trans_handle *trans, |
3188 | btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans, | 3214 | struct btrfs_root *root, |
3189 | struct btrfs_root *root, | 3215 | struct btrfs_path *path, |
3190 | struct btrfs_path *path, | 3216 | const char *name, int name_len, |
3191 | const char *name, int name_len, | 3217 | u64 inode_objectid, u64 ref_objectid, int mod, |
3192 | u64 inode_objectid, u64 ref_objectid, int mod); | 3218 | u64 *ret_index); |
3193 | int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans, | 3219 | int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans, |
3194 | struct btrfs_root *root, | 3220 | struct btrfs_root *root, |
3195 | struct btrfs_path *path, u64 objectid); | 3221 | struct btrfs_path *path, u64 objectid); |
@@ -3197,6 +3223,19 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | |||
3197 | *root, struct btrfs_path *path, | 3223 | *root, struct btrfs_path *path, |
3198 | struct btrfs_key *location, int mod); | 3224 | struct btrfs_key *location, int mod); |
3199 | 3225 | ||
3226 | struct btrfs_inode_extref * | ||
3227 | btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans, | ||
3228 | struct btrfs_root *root, | ||
3229 | struct btrfs_path *path, | ||
3230 | const char *name, int name_len, | ||
3231 | u64 inode_objectid, u64 ref_objectid, int ins_len, | ||
3232 | int cow); | ||
3233 | |||
3234 | int btrfs_find_name_in_ext_backref(struct btrfs_path *path, | ||
3235 | u64 ref_objectid, const char *name, | ||
3236 | int name_len, | ||
3237 | struct btrfs_inode_extref **extref_ret); | ||
3238 | |||
3200 | /* file-item.c */ | 3239 | /* file-item.c */ |
3201 | int btrfs_del_csums(struct btrfs_trans_handle *trans, | 3240 | int btrfs_del_csums(struct btrfs_trans_handle *trans, |
3202 | struct btrfs_root *root, u64 bytenr, u64 len); | 3241 | struct btrfs_root *root, u64 bytenr, u64 len); |
diff --git a/fs/btrfs/hash.h b/fs/btrfs/hash.h index db2ff9773b99..1d982812ab67 100644 --- a/fs/btrfs/hash.h +++ b/fs/btrfs/hash.h | |||
@@ -24,4 +24,14 @@ static inline u64 btrfs_name_hash(const char *name, int len) | |||
24 | { | 24 | { |
25 | return crc32c((u32)~1, name, len); | 25 | return crc32c((u32)~1, name, len); |
26 | } | 26 | } |
27 | |||
28 | /* | ||
29 | * Figure the key offset of an extended inode ref | ||
30 | */ | ||
31 | static inline u64 btrfs_extref_hash(u64 parent_objectid, const char *name, | ||
32 | int len) | ||
33 | { | ||
34 | return (u64) crc32c(parent_objectid, name, len); | ||
35 | } | ||
36 | |||
27 | #endif | 37 | #endif |
diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index a13cf1a96c73..48b8fda93132 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include "ctree.h" | 19 | #include "ctree.h" |
20 | #include "disk-io.h" | 20 | #include "disk-io.h" |
21 | #include "hash.h" | ||
21 | #include "transaction.h" | 22 | #include "transaction.h" |
22 | #include "print-tree.h" | 23 | #include "print-tree.h" |
23 | 24 | ||
@@ -50,18 +51,57 @@ static int find_name_in_backref(struct btrfs_path *path, const char *name, | |||
50 | return 0; | 51 | return 0; |
51 | } | 52 | } |
52 | 53 | ||
53 | struct btrfs_inode_ref * | 54 | int btrfs_find_name_in_ext_backref(struct btrfs_path *path, u64 ref_objectid, |
55 | const char *name, int name_len, | ||
56 | struct btrfs_inode_extref **extref_ret) | ||
57 | { | ||
58 | struct extent_buffer *leaf; | ||
59 | struct btrfs_inode_extref *extref; | ||
60 | unsigned long ptr; | ||
61 | unsigned long name_ptr; | ||
62 | u32 item_size; | ||
63 | u32 cur_offset = 0; | ||
64 | int ref_name_len; | ||
65 | |||
66 | leaf = path->nodes[0]; | ||
67 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); | ||
68 | ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); | ||
69 | |||
70 | /* | ||
71 | * Search all extended backrefs in this item. We're only | ||
72 | * looking through any collisions so most of the time this is | ||
73 | * just going to compare against one buffer. If all is well, | ||
74 | * we'll return success and the inode ref object. | ||
75 | */ | ||
76 | while (cur_offset < item_size) { | ||
77 | extref = (struct btrfs_inode_extref *) (ptr + cur_offset); | ||
78 | name_ptr = (unsigned long)(&extref->name); | ||
79 | ref_name_len = btrfs_inode_extref_name_len(leaf, extref); | ||
80 | |||
81 | if (ref_name_len == name_len && | ||
82 | btrfs_inode_extref_parent(leaf, extref) == ref_objectid && | ||
83 | (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)) { | ||
84 | if (extref_ret) | ||
85 | *extref_ret = extref; | ||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | cur_offset += ref_name_len + sizeof(*extref); | ||
90 | } | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static struct btrfs_inode_ref * | ||
54 | btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans, | 95 | btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans, |
55 | struct btrfs_root *root, | 96 | struct btrfs_root *root, |
56 | struct btrfs_path *path, | 97 | struct btrfs_path *path, |
57 | const char *name, int name_len, | 98 | const char *name, int name_len, |
58 | u64 inode_objectid, u64 ref_objectid, int mod) | 99 | u64 inode_objectid, u64 ref_objectid, int ins_len, |
100 | int cow) | ||
59 | { | 101 | { |
102 | int ret; | ||
60 | struct btrfs_key key; | 103 | struct btrfs_key key; |
61 | struct btrfs_inode_ref *ref; | 104 | struct btrfs_inode_ref *ref; |
62 | int ins_len = mod < 0 ? -1 : 0; | ||
63 | int cow = mod != 0; | ||
64 | int ret; | ||
65 | 105 | ||
66 | key.objectid = inode_objectid; | 106 | key.objectid = inode_objectid; |
67 | key.type = BTRFS_INODE_REF_KEY; | 107 | key.type = BTRFS_INODE_REF_KEY; |
@@ -77,13 +117,150 @@ btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans, | |||
77 | return ref; | 117 | return ref; |
78 | } | 118 | } |
79 | 119 | ||
80 | int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, | 120 | /* Returns NULL if no extref found */ |
121 | struct btrfs_inode_extref * | ||
122 | btrfs_lookup_inode_extref(struct btrfs_trans_handle *trans, | ||
123 | struct btrfs_root *root, | ||
124 | struct btrfs_path *path, | ||
125 | const char *name, int name_len, | ||
126 | u64 inode_objectid, u64 ref_objectid, int ins_len, | ||
127 | int cow) | ||
128 | { | ||
129 | int ret; | ||
130 | struct btrfs_key key; | ||
131 | struct btrfs_inode_extref *extref; | ||
132 | |||
133 | key.objectid = inode_objectid; | ||
134 | key.type = BTRFS_INODE_EXTREF_KEY; | ||
135 | key.offset = btrfs_extref_hash(ref_objectid, name, name_len); | ||
136 | |||
137 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); | ||
138 | if (ret < 0) | ||
139 | return ERR_PTR(ret); | ||
140 | if (ret > 0) | ||
141 | return NULL; | ||
142 | if (!btrfs_find_name_in_ext_backref(path, ref_objectid, name, name_len, &extref)) | ||
143 | return NULL; | ||
144 | return extref; | ||
145 | } | ||
146 | |||
147 | int btrfs_get_inode_ref_index(struct btrfs_trans_handle *trans, | ||
148 | struct btrfs_root *root, | ||
149 | struct btrfs_path *path, | ||
150 | const char *name, int name_len, | ||
151 | u64 inode_objectid, u64 ref_objectid, int mod, | ||
152 | u64 *ret_index) | ||
153 | { | ||
154 | struct btrfs_inode_ref *ref; | ||
155 | struct btrfs_inode_extref *extref; | ||
156 | int ins_len = mod < 0 ? -1 : 0; | ||
157 | int cow = mod != 0; | ||
158 | |||
159 | ref = btrfs_lookup_inode_ref(trans, root, path, name, name_len, | ||
160 | inode_objectid, ref_objectid, ins_len, | ||
161 | cow); | ||
162 | if (IS_ERR(ref)) | ||
163 | return PTR_ERR(ref); | ||
164 | |||
165 | if (ref != NULL) { | ||
166 | *ret_index = btrfs_inode_ref_index(path->nodes[0], ref); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | btrfs_release_path(path); | ||
171 | |||
172 | extref = btrfs_lookup_inode_extref(trans, root, path, name, | ||
173 | name_len, inode_objectid, | ||
174 | ref_objectid, ins_len, cow); | ||
175 | if (IS_ERR(extref)) | ||
176 | return PTR_ERR(extref); | ||
177 | |||
178 | if (extref) { | ||
179 | *ret_index = btrfs_inode_extref_index(path->nodes[0], extref); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | return -ENOENT; | ||
184 | } | ||
185 | |||
186 | int btrfs_del_inode_extref(struct btrfs_trans_handle *trans, | ||
81 | struct btrfs_root *root, | 187 | struct btrfs_root *root, |
82 | const char *name, int name_len, | 188 | const char *name, int name_len, |
83 | u64 inode_objectid, u64 ref_objectid, u64 *index) | 189 | u64 inode_objectid, u64 ref_objectid, u64 *index) |
84 | { | 190 | { |
85 | struct btrfs_path *path; | 191 | struct btrfs_path *path; |
86 | struct btrfs_key key; | 192 | struct btrfs_key key; |
193 | struct btrfs_inode_extref *extref; | ||
194 | struct extent_buffer *leaf; | ||
195 | int ret; | ||
196 | int del_len = name_len + sizeof(*extref); | ||
197 | unsigned long ptr; | ||
198 | unsigned long item_start; | ||
199 | u32 item_size; | ||
200 | |||
201 | key.objectid = inode_objectid; | ||
202 | btrfs_set_key_type(&key, BTRFS_INODE_EXTREF_KEY); | ||
203 | key.offset = btrfs_extref_hash(ref_objectid, name, name_len); | ||
204 | |||
205 | path = btrfs_alloc_path(); | ||
206 | if (!path) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | path->leave_spinning = 1; | ||
210 | |||
211 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | ||
212 | if (ret > 0) | ||
213 | ret = -ENOENT; | ||
214 | if (ret < 0) | ||
215 | goto out; | ||
216 | |||
217 | /* | ||
218 | * Sanity check - did we find the right item for this name? | ||
219 | * This should always succeed so error here will make the FS | ||
220 | * readonly. | ||
221 | */ | ||
222 | if (!btrfs_find_name_in_ext_backref(path, ref_objectid, | ||
223 | name, name_len, &extref)) { | ||
224 | btrfs_std_error(root->fs_info, -ENOENT); | ||
225 | ret = -EROFS; | ||
226 | goto out; | ||
227 | } | ||
228 | |||
229 | leaf = path->nodes[0]; | ||
230 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); | ||
231 | if (index) | ||
232 | *index = btrfs_inode_extref_index(leaf, extref); | ||
233 | |||
234 | if (del_len == item_size) { | ||
235 | /* | ||
236 | * Common case only one ref in the item, remove the | ||
237 | * whole item. | ||
238 | */ | ||
239 | ret = btrfs_del_item(trans, root, path); | ||
240 | goto out; | ||
241 | } | ||
242 | |||
243 | ptr = (unsigned long)extref; | ||
244 | item_start = btrfs_item_ptr_offset(leaf, path->slots[0]); | ||
245 | |||
246 | memmove_extent_buffer(leaf, ptr, ptr + del_len, | ||
247 | item_size - (ptr + del_len - item_start)); | ||
248 | |||
249 | btrfs_truncate_item(trans, root, path, item_size - del_len, 1); | ||
250 | |||
251 | out: | ||
252 | btrfs_free_path(path); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, | ||
258 | struct btrfs_root *root, | ||
259 | const char *name, int name_len, | ||
260 | u64 inode_objectid, u64 ref_objectid, u64 *index) | ||
261 | { | ||
262 | struct btrfs_path *path; | ||
263 | struct btrfs_key key; | ||
87 | struct btrfs_inode_ref *ref; | 264 | struct btrfs_inode_ref *ref; |
88 | struct extent_buffer *leaf; | 265 | struct extent_buffer *leaf; |
89 | unsigned long ptr; | 266 | unsigned long ptr; |
@@ -91,6 +268,7 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, | |||
91 | u32 item_size; | 268 | u32 item_size; |
92 | u32 sub_item_len; | 269 | u32 sub_item_len; |
93 | int ret; | 270 | int ret; |
271 | int search_ext_refs = 0; | ||
94 | int del_len = name_len + sizeof(*ref); | 272 | int del_len = name_len + sizeof(*ref); |
95 | 273 | ||
96 | key.objectid = inode_objectid; | 274 | key.objectid = inode_objectid; |
@@ -106,12 +284,14 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, | |||
106 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 284 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
107 | if (ret > 0) { | 285 | if (ret > 0) { |
108 | ret = -ENOENT; | 286 | ret = -ENOENT; |
287 | search_ext_refs = 1; | ||
109 | goto out; | 288 | goto out; |
110 | } else if (ret < 0) { | 289 | } else if (ret < 0) { |
111 | goto out; | 290 | goto out; |
112 | } | 291 | } |
113 | if (!find_name_in_backref(path, name, name_len, &ref)) { | 292 | if (!find_name_in_backref(path, name, name_len, &ref)) { |
114 | ret = -ENOENT; | 293 | ret = -ENOENT; |
294 | search_ext_refs = 1; | ||
115 | goto out; | 295 | goto out; |
116 | } | 296 | } |
117 | leaf = path->nodes[0]; | 297 | leaf = path->nodes[0]; |
@@ -129,8 +309,78 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, | |||
129 | item_start = btrfs_item_ptr_offset(leaf, path->slots[0]); | 309 | item_start = btrfs_item_ptr_offset(leaf, path->slots[0]); |
130 | memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, | 310 | memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, |
131 | item_size - (ptr + sub_item_len - item_start)); | 311 | item_size - (ptr + sub_item_len - item_start)); |
132 | btrfs_truncate_item(trans, root, path, | 312 | btrfs_truncate_item(trans, root, path, item_size - sub_item_len, 1); |
133 | item_size - sub_item_len, 1); | 313 | out: |
314 | btrfs_free_path(path); | ||
315 | |||
316 | if (search_ext_refs) { | ||
317 | /* | ||
318 | * No refs were found, or we could not find the | ||
319 | * name in our ref array. Find and remove the extended | ||
320 | * inode ref then. | ||
321 | */ | ||
322 | return btrfs_del_inode_extref(trans, root, name, name_len, | ||
323 | inode_objectid, ref_objectid, index); | ||
324 | } | ||
325 | |||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * btrfs_insert_inode_extref() - Inserts an extended inode ref into a tree. | ||
331 | * | ||
332 | * The caller must have checked against BTRFS_LINK_MAX already. | ||
333 | */ | ||
334 | static int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans, | ||
335 | struct btrfs_root *root, | ||
336 | const char *name, int name_len, | ||
337 | u64 inode_objectid, u64 ref_objectid, u64 index) | ||
338 | { | ||
339 | struct btrfs_inode_extref *extref; | ||
340 | int ret; | ||
341 | int ins_len = name_len + sizeof(*extref); | ||
342 | unsigned long ptr; | ||
343 | struct btrfs_path *path; | ||
344 | struct btrfs_key key; | ||
345 | struct extent_buffer *leaf; | ||
346 | struct btrfs_item *item; | ||
347 | |||
348 | key.objectid = inode_objectid; | ||
349 | key.type = BTRFS_INODE_EXTREF_KEY; | ||
350 | key.offset = btrfs_extref_hash(ref_objectid, name, name_len); | ||
351 | |||
352 | path = btrfs_alloc_path(); | ||
353 | if (!path) | ||
354 | return -ENOMEM; | ||
355 | |||
356 | path->leave_spinning = 1; | ||
357 | ret = btrfs_insert_empty_item(trans, root, path, &key, | ||
358 | ins_len); | ||
359 | if (ret == -EEXIST) { | ||
360 | if (btrfs_find_name_in_ext_backref(path, ref_objectid, | ||
361 | name, name_len, NULL)) | ||
362 | goto out; | ||
363 | |||
364 | btrfs_extend_item(trans, root, path, ins_len); | ||
365 | ret = 0; | ||
366 | } | ||
367 | if (ret < 0) | ||
368 | goto out; | ||
369 | |||
370 | leaf = path->nodes[0]; | ||
371 | item = btrfs_item_nr(leaf, path->slots[0]); | ||
372 | ptr = (unsigned long)btrfs_item_ptr(leaf, path->slots[0], char); | ||
373 | ptr += btrfs_item_size(leaf, item) - ins_len; | ||
374 | extref = (struct btrfs_inode_extref *)ptr; | ||
375 | |||
376 | btrfs_set_inode_extref_name_len(path->nodes[0], extref, name_len); | ||
377 | btrfs_set_inode_extref_index(path->nodes[0], extref, index); | ||
378 | btrfs_set_inode_extref_parent(path->nodes[0], extref, ref_objectid); | ||
379 | |||
380 | ptr = (unsigned long)&extref->name; | ||
381 | write_extent_buffer(path->nodes[0], name, ptr, name_len); | ||
382 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
383 | |||
134 | out: | 384 | out: |
135 | btrfs_free_path(path); | 385 | btrfs_free_path(path); |
136 | return ret; | 386 | return ret; |
@@ -191,6 +441,19 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, | |||
191 | 441 | ||
192 | out: | 442 | out: |
193 | btrfs_free_path(path); | 443 | btrfs_free_path(path); |
444 | |||
445 | if (ret == -EMLINK) { | ||
446 | struct btrfs_super_block *disk_super = root->fs_info->super_copy; | ||
447 | /* We ran out of space in the ref array. Need to | ||
448 | * add an extended ref. */ | ||
449 | if (btrfs_super_incompat_flags(disk_super) | ||
450 | & BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF) | ||
451 | ret = btrfs_insert_inode_extref(trans, root, name, | ||
452 | name_len, | ||
453 | inode_objectid, | ||
454 | ref_objectid, index); | ||
455 | } | ||
456 | |||
194 | return ret; | 457 | return ret; |
195 | } | 458 | } |
196 | 459 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1c50f7c4f5ac..596305e4d75b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2903,7 +2903,6 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir, | |||
2903 | struct btrfs_trans_handle *trans; | 2903 | struct btrfs_trans_handle *trans; |
2904 | struct btrfs_root *root = BTRFS_I(dir)->root; | 2904 | struct btrfs_root *root = BTRFS_I(dir)->root; |
2905 | struct btrfs_path *path; | 2905 | struct btrfs_path *path; |
2906 | struct btrfs_inode_ref *ref; | ||
2907 | struct btrfs_dir_item *di; | 2906 | struct btrfs_dir_item *di; |
2908 | struct inode *inode = dentry->d_inode; | 2907 | struct inode *inode = dentry->d_inode; |
2909 | u64 index; | 2908 | u64 index; |
@@ -3017,17 +3016,17 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir, | |||
3017 | } | 3016 | } |
3018 | btrfs_release_path(path); | 3017 | btrfs_release_path(path); |
3019 | 3018 | ||
3020 | ref = btrfs_lookup_inode_ref(trans, root, path, | 3019 | ret = btrfs_get_inode_ref_index(trans, root, path, dentry->d_name.name, |
3021 | dentry->d_name.name, dentry->d_name.len, | 3020 | dentry->d_name.len, ino, dir_ino, 0, |
3022 | ino, dir_ino, 0); | 3021 | &index); |
3023 | if (IS_ERR(ref)) { | 3022 | if (ret) { |
3024 | err = PTR_ERR(ref); | 3023 | err = ret; |
3025 | goto out; | 3024 | goto out; |
3026 | } | 3025 | } |
3027 | BUG_ON(!ref); /* Logic error */ | 3026 | |
3028 | if (check_path_shared(root, path)) | 3027 | if (check_path_shared(root, path)) |
3029 | goto out; | 3028 | goto out; |
3030 | index = btrfs_inode_ref_index(path->nodes[0], ref); | 3029 | |
3031 | btrfs_release_path(path); | 3030 | btrfs_release_path(path); |
3032 | 3031 | ||
3033 | /* | 3032 | /* |
@@ -4743,6 +4742,12 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
4743 | btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); | 4742 | btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); |
4744 | key[0].offset = 0; | 4743 | key[0].offset = 0; |
4745 | 4744 | ||
4745 | /* | ||
4746 | * Start new inodes with an inode_ref. This is slightly more | ||
4747 | * efficient for small numbers of hard links since they will | ||
4748 | * be packed into one item. Extended refs will kick in if we | ||
4749 | * add more hard links than can fit in the ref item. | ||
4750 | */ | ||
4746 | key[1].objectid = objectid; | 4751 | key[1].objectid = objectid; |
4747 | btrfs_set_key_type(&key[1], BTRFS_INODE_REF_KEY); | 4752 | btrfs_set_key_type(&key[1], BTRFS_INODE_REF_KEY); |
4748 | key[1].offset = ref_objectid; | 4753 | key[1].offset = ref_objectid; |
@@ -5049,7 +5054,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
5049 | if (root->objectid != BTRFS_I(inode)->root->objectid) | 5054 | if (root->objectid != BTRFS_I(inode)->root->objectid) |
5050 | return -EXDEV; | 5055 | return -EXDEV; |
5051 | 5056 | ||
5052 | if (inode->i_nlink == ~0U) | 5057 | if (inode->i_nlink >= BTRFS_LINK_MAX) |
5053 | return -EMLINK; | 5058 | return -EMLINK; |
5054 | 5059 | ||
5055 | err = btrfs_set_inode_index(dir, &index); | 5060 | err = btrfs_set_inode_index(dir, &index); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 15dae589e59f..1d7b34844323 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -24,8 +24,10 @@ | |||
24 | #include "disk-io.h" | 24 | #include "disk-io.h" |
25 | #include "locking.h" | 25 | #include "locking.h" |
26 | #include "print-tree.h" | 26 | #include "print-tree.h" |
27 | #include "backref.h" | ||
27 | #include "compat.h" | 28 | #include "compat.h" |
28 | #include "tree-log.h" | 29 | #include "tree-log.h" |
30 | #include "hash.h" | ||
29 | 31 | ||
30 | /* magic values for the inode_only field in btrfs_log_inode: | 32 | /* magic values for the inode_only field in btrfs_log_inode: |
31 | * | 33 | * |
@@ -743,6 +745,7 @@ out: | |||
743 | */ | 745 | */ |
744 | static noinline int backref_in_log(struct btrfs_root *log, | 746 | static noinline int backref_in_log(struct btrfs_root *log, |
745 | struct btrfs_key *key, | 747 | struct btrfs_key *key, |
748 | u64 ref_objectid, | ||
746 | char *name, int namelen) | 749 | char *name, int namelen) |
747 | { | 750 | { |
748 | struct btrfs_path *path; | 751 | struct btrfs_path *path; |
@@ -763,8 +766,17 @@ static noinline int backref_in_log(struct btrfs_root *log, | |||
763 | if (ret != 0) | 766 | if (ret != 0) |
764 | goto out; | 767 | goto out; |
765 | 768 | ||
766 | item_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]); | ||
767 | ptr = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]); | 769 | ptr = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]); |
770 | |||
771 | if (key->type == BTRFS_INODE_EXTREF_KEY) { | ||
772 | if (btrfs_find_name_in_ext_backref(path, ref_objectid, | ||
773 | name, namelen, NULL)) | ||
774 | match = 1; | ||
775 | |||
776 | goto out; | ||
777 | } | ||
778 | |||
779 | item_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]); | ||
768 | ptr_end = ptr + item_size; | 780 | ptr_end = ptr + item_size; |
769 | while (ptr < ptr_end) { | 781 | while (ptr < ptr_end) { |
770 | ref = (struct btrfs_inode_ref *)ptr; | 782 | ref = (struct btrfs_inode_ref *)ptr; |
@@ -790,27 +802,36 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, | |||
790 | struct btrfs_path *path, | 802 | struct btrfs_path *path, |
791 | struct btrfs_root *log_root, | 803 | struct btrfs_root *log_root, |
792 | struct inode *dir, struct inode *inode, | 804 | struct inode *dir, struct inode *inode, |
793 | struct btrfs_key *key, | ||
794 | struct extent_buffer *eb, | 805 | struct extent_buffer *eb, |
795 | struct btrfs_inode_ref *ref, | 806 | u64 inode_objectid, u64 parent_objectid, |
796 | char *name, int namelen, int *search_done) | 807 | u64 ref_index, char *name, int namelen, |
808 | int *search_done) | ||
797 | { | 809 | { |
798 | int ret; | 810 | int ret; |
811 | char *victim_name; | ||
812 | int victim_name_len; | ||
813 | struct extent_buffer *leaf; | ||
799 | struct btrfs_dir_item *di; | 814 | struct btrfs_dir_item *di; |
815 | struct btrfs_key search_key; | ||
816 | struct btrfs_inode_extref *extref; | ||
800 | 817 | ||
801 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); | 818 | again: |
819 | /* Search old style refs */ | ||
820 | search_key.objectid = inode_objectid; | ||
821 | search_key.type = BTRFS_INODE_REF_KEY; | ||
822 | search_key.offset = parent_objectid; | ||
823 | ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); | ||
802 | if (ret == 0) { | 824 | if (ret == 0) { |
803 | char *victim_name; | ||
804 | int victim_name_len; | ||
805 | struct btrfs_inode_ref *victim_ref; | 825 | struct btrfs_inode_ref *victim_ref; |
806 | unsigned long ptr; | 826 | unsigned long ptr; |
807 | unsigned long ptr_end; | 827 | unsigned long ptr_end; |
808 | struct extent_buffer *leaf = path->nodes[0]; | 828 | |
829 | leaf = path->nodes[0]; | ||
809 | 830 | ||
810 | /* are we trying to overwrite a back ref for the root directory | 831 | /* are we trying to overwrite a back ref for the root directory |
811 | * if so, just jump out, we're done | 832 | * if so, just jump out, we're done |
812 | */ | 833 | */ |
813 | if (key->objectid == key->offset) | 834 | if (search_key.objectid == search_key.offset) |
814 | return 1; | 835 | return 1; |
815 | 836 | ||
816 | /* check all the names in this back reference to see | 837 | /* check all the names in this back reference to see |
@@ -830,7 +851,9 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, | |||
830 | (unsigned long)(victim_ref + 1), | 851 | (unsigned long)(victim_ref + 1), |
831 | victim_name_len); | 852 | victim_name_len); |
832 | 853 | ||
833 | if (!backref_in_log(log_root, key, victim_name, | 854 | if (!backref_in_log(log_root, &search_key, |
855 | parent_objectid, | ||
856 | victim_name, | ||
834 | victim_name_len)) { | 857 | victim_name_len)) { |
835 | btrfs_inc_nlink(inode); | 858 | btrfs_inc_nlink(inode); |
836 | btrfs_release_path(path); | 859 | btrfs_release_path(path); |
@@ -838,9 +861,14 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, | |||
838 | ret = btrfs_unlink_inode(trans, root, dir, | 861 | ret = btrfs_unlink_inode(trans, root, dir, |
839 | inode, victim_name, | 862 | inode, victim_name, |
840 | victim_name_len); | 863 | victim_name_len); |
864 | BUG_ON(ret); | ||
841 | btrfs_run_delayed_items(trans, root); | 865 | btrfs_run_delayed_items(trans, root); |
866 | kfree(victim_name); | ||
867 | *search_done = 1; | ||
868 | goto again; | ||
842 | } | 869 | } |
843 | kfree(victim_name); | 870 | kfree(victim_name); |
871 | |||
844 | ptr = (unsigned long)(victim_ref + 1) + victim_name_len; | 872 | ptr = (unsigned long)(victim_ref + 1) + victim_name_len; |
845 | } | 873 | } |
846 | BUG_ON(ret); | 874 | BUG_ON(ret); |
@@ -853,10 +881,74 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, | |||
853 | } | 881 | } |
854 | btrfs_release_path(path); | 882 | btrfs_release_path(path); |
855 | 883 | ||
884 | /* Same search but for extended refs */ | ||
885 | extref = btrfs_lookup_inode_extref(NULL, root, path, name, namelen, | ||
886 | inode_objectid, parent_objectid, 0, | ||
887 | 0); | ||
888 | if (!IS_ERR_OR_NULL(extref)) { | ||
889 | u32 item_size; | ||
890 | u32 cur_offset = 0; | ||
891 | unsigned long base; | ||
892 | struct inode *victim_parent; | ||
893 | |||
894 | leaf = path->nodes[0]; | ||
895 | |||
896 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); | ||
897 | base = btrfs_item_ptr_offset(leaf, path->slots[0]); | ||
898 | |||
899 | while (cur_offset < item_size) { | ||
900 | extref = (struct btrfs_inode_extref *)base + cur_offset; | ||
901 | |||
902 | victim_name_len = btrfs_inode_extref_name_len(leaf, extref); | ||
903 | |||
904 | if (btrfs_inode_extref_parent(leaf, extref) != parent_objectid) | ||
905 | goto next; | ||
906 | |||
907 | victim_name = kmalloc(victim_name_len, GFP_NOFS); | ||
908 | read_extent_buffer(leaf, victim_name, (unsigned long)&extref->name, | ||
909 | victim_name_len); | ||
910 | |||
911 | search_key.objectid = inode_objectid; | ||
912 | search_key.type = BTRFS_INODE_EXTREF_KEY; | ||
913 | search_key.offset = btrfs_extref_hash(parent_objectid, | ||
914 | victim_name, | ||
915 | victim_name_len); | ||
916 | ret = 0; | ||
917 | if (!backref_in_log(log_root, &search_key, | ||
918 | parent_objectid, victim_name, | ||
919 | victim_name_len)) { | ||
920 | ret = -ENOENT; | ||
921 | victim_parent = read_one_inode(root, | ||
922 | parent_objectid); | ||
923 | if (victim_parent) { | ||
924 | btrfs_inc_nlink(inode); | ||
925 | btrfs_release_path(path); | ||
926 | |||
927 | ret = btrfs_unlink_inode(trans, root, | ||
928 | victim_parent, | ||
929 | inode, | ||
930 | victim_name, | ||
931 | victim_name_len); | ||
932 | btrfs_run_delayed_items(trans, root); | ||
933 | } | ||
934 | BUG_ON(ret); | ||
935 | iput(victim_parent); | ||
936 | kfree(victim_name); | ||
937 | *search_done = 1; | ||
938 | goto again; | ||
939 | } | ||
940 | kfree(victim_name); | ||
941 | BUG_ON(ret); | ||
942 | next: | ||
943 | cur_offset += victim_name_len + sizeof(*extref); | ||
944 | } | ||
945 | *search_done = 1; | ||
946 | } | ||
947 | btrfs_release_path(path); | ||
948 | |||
856 | /* look for a conflicting sequence number */ | 949 | /* look for a conflicting sequence number */ |
857 | di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), | 950 | di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), |
858 | btrfs_inode_ref_index(eb, ref), | 951 | ref_index, name, namelen, 0); |
859 | name, namelen, 0); | ||
860 | if (di && !IS_ERR(di)) { | 952 | if (di && !IS_ERR(di)) { |
861 | ret = drop_one_dir_item(trans, root, path, dir, di); | 953 | ret = drop_one_dir_item(trans, root, path, dir, di); |
862 | BUG_ON(ret); | 954 | BUG_ON(ret); |
@@ -875,6 +967,48 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, | |||
875 | return 0; | 967 | return 0; |
876 | } | 968 | } |
877 | 969 | ||
970 | static int extref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr, | ||
971 | u32 *namelen, char **name, u64 *index, | ||
972 | u64 *parent_objectid) | ||
973 | { | ||
974 | struct btrfs_inode_extref *extref; | ||
975 | |||
976 | extref = (struct btrfs_inode_extref *)ref_ptr; | ||
977 | |||
978 | *namelen = btrfs_inode_extref_name_len(eb, extref); | ||
979 | *name = kmalloc(*namelen, GFP_NOFS); | ||
980 | if (*name == NULL) | ||
981 | return -ENOMEM; | ||
982 | |||
983 | read_extent_buffer(eb, *name, (unsigned long)&extref->name, | ||
984 | *namelen); | ||
985 | |||
986 | *index = btrfs_inode_extref_index(eb, extref); | ||
987 | if (parent_objectid) | ||
988 | *parent_objectid = btrfs_inode_extref_parent(eb, extref); | ||
989 | |||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | static int ref_get_fields(struct extent_buffer *eb, unsigned long ref_ptr, | ||
994 | u32 *namelen, char **name, u64 *index) | ||
995 | { | ||
996 | struct btrfs_inode_ref *ref; | ||
997 | |||
998 | ref = (struct btrfs_inode_ref *)ref_ptr; | ||
999 | |||
1000 | *namelen = btrfs_inode_ref_name_len(eb, ref); | ||
1001 | *name = kmalloc(*namelen, GFP_NOFS); | ||
1002 | if (*name == NULL) | ||
1003 | return -ENOMEM; | ||
1004 | |||
1005 | read_extent_buffer(eb, *name, (unsigned long)(ref + 1), *namelen); | ||
1006 | |||
1007 | *index = btrfs_inode_ref_index(eb, ref); | ||
1008 | |||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
878 | /* | 1012 | /* |
879 | * replay one inode back reference item found in the log tree. | 1013 | * replay one inode back reference item found in the log tree. |
880 | * eb, slot and key refer to the buffer and key found in the log tree. | 1014 | * eb, slot and key refer to the buffer and key found in the log tree. |
@@ -888,7 +1022,6 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
888 | struct extent_buffer *eb, int slot, | 1022 | struct extent_buffer *eb, int slot, |
889 | struct btrfs_key *key) | 1023 | struct btrfs_key *key) |
890 | { | 1024 | { |
891 | struct btrfs_inode_ref *ref; | ||
892 | struct inode *dir; | 1025 | struct inode *dir; |
893 | struct inode *inode; | 1026 | struct inode *inode; |
894 | unsigned long ref_ptr; | 1027 | unsigned long ref_ptr; |
@@ -897,6 +1030,27 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
897 | int namelen; | 1030 | int namelen; |
898 | int ret; | 1031 | int ret; |
899 | int search_done = 0; | 1032 | int search_done = 0; |
1033 | int log_ref_ver = 0; | ||
1034 | u64 parent_objectid; | ||
1035 | u64 inode_objectid; | ||
1036 | u64 ref_index; | ||
1037 | int ref_struct_size; | ||
1038 | |||
1039 | ref_ptr = btrfs_item_ptr_offset(eb, slot); | ||
1040 | ref_end = ref_ptr + btrfs_item_size_nr(eb, slot); | ||
1041 | |||
1042 | if (key->type == BTRFS_INODE_EXTREF_KEY) { | ||
1043 | struct btrfs_inode_extref *r; | ||
1044 | |||
1045 | ref_struct_size = sizeof(struct btrfs_inode_extref); | ||
1046 | log_ref_ver = 1; | ||
1047 | r = (struct btrfs_inode_extref *)ref_ptr; | ||
1048 | parent_objectid = btrfs_inode_extref_parent(eb, r); | ||
1049 | } else { | ||
1050 | ref_struct_size = sizeof(struct btrfs_inode_ref); | ||
1051 | parent_objectid = key->offset; | ||
1052 | } | ||
1053 | inode_objectid = key->objectid; | ||
900 | 1054 | ||
901 | /* | 1055 | /* |
902 | * it is possible that we didn't log all the parent directories | 1056 | * it is possible that we didn't log all the parent directories |
@@ -904,32 +1058,38 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
904 | * copy the back ref in. The link count fixup code will take | 1058 | * copy the back ref in. The link count fixup code will take |
905 | * care of the rest | 1059 | * care of the rest |
906 | */ | 1060 | */ |
907 | dir = read_one_inode(root, key->offset); | 1061 | dir = read_one_inode(root, parent_objectid); |
908 | if (!dir) | 1062 | if (!dir) |
909 | return -ENOENT; | 1063 | return -ENOENT; |
910 | 1064 | ||
911 | inode = read_one_inode(root, key->objectid); | 1065 | inode = read_one_inode(root, inode_objectid); |
912 | if (!inode) { | 1066 | if (!inode) { |
913 | iput(dir); | 1067 | iput(dir); |
914 | return -EIO; | 1068 | return -EIO; |
915 | } | 1069 | } |
916 | 1070 | ||
917 | ref_ptr = btrfs_item_ptr_offset(eb, slot); | ||
918 | ref_end = ref_ptr + btrfs_item_size_nr(eb, slot); | ||
919 | |||
920 | while (ref_ptr < ref_end) { | 1071 | while (ref_ptr < ref_end) { |
921 | ref = (struct btrfs_inode_ref *)ref_ptr; | 1072 | if (log_ref_ver) { |
922 | 1073 | ret = extref_get_fields(eb, ref_ptr, &namelen, &name, | |
923 | namelen = btrfs_inode_ref_name_len(eb, ref); | 1074 | &ref_index, &parent_objectid); |
924 | name = kmalloc(namelen, GFP_NOFS); | 1075 | /* |
925 | BUG_ON(!name); | 1076 | * parent object can change from one array |
926 | 1077 | * item to another. | |
927 | read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen); | 1078 | */ |
1079 | if (!dir) | ||
1080 | dir = read_one_inode(root, parent_objectid); | ||
1081 | if (!dir) | ||
1082 | return -ENOENT; | ||
1083 | } else { | ||
1084 | ret = ref_get_fields(eb, ref_ptr, &namelen, &name, | ||
1085 | &ref_index); | ||
1086 | } | ||
1087 | if (ret) | ||
1088 | return ret; | ||
928 | 1089 | ||
929 | /* if we already have a perfect match, we're done */ | 1090 | /* if we already have a perfect match, we're done */ |
930 | if (!inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode), | 1091 | if (!inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode), |
931 | btrfs_inode_ref_index(eb, ref), | 1092 | ref_index, name, namelen)) { |
932 | name, namelen)) { | ||
933 | /* | 1093 | /* |
934 | * look for a conflicting back reference in the | 1094 | * look for a conflicting back reference in the |
935 | * metadata. if we find one we have to unlink that name | 1095 | * metadata. if we find one we have to unlink that name |
@@ -940,8 +1100,10 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
940 | 1100 | ||
941 | if (!search_done) { | 1101 | if (!search_done) { |
942 | ret = __add_inode_ref(trans, root, path, log, | 1102 | ret = __add_inode_ref(trans, root, path, log, |
943 | dir, inode, key, eb, ref, | 1103 | dir, inode, eb, |
944 | name, namelen, | 1104 | inode_objectid, |
1105 | parent_objectid, | ||
1106 | ref_index, name, namelen, | ||
945 | &search_done); | 1107 | &search_done); |
946 | if (ret == 1) | 1108 | if (ret == 1) |
947 | goto out; | 1109 | goto out; |
@@ -950,14 +1112,18 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
950 | 1112 | ||
951 | /* insert our name */ | 1113 | /* insert our name */ |
952 | ret = btrfs_add_link(trans, dir, inode, name, namelen, | 1114 | ret = btrfs_add_link(trans, dir, inode, name, namelen, |
953 | 0, btrfs_inode_ref_index(eb, ref)); | 1115 | 0, ref_index); |
954 | BUG_ON(ret); | 1116 | BUG_ON(ret); |
955 | 1117 | ||
956 | btrfs_update_inode(trans, root, inode); | 1118 | btrfs_update_inode(trans, root, inode); |
957 | } | 1119 | } |
958 | 1120 | ||
959 | ref_ptr = (unsigned long)(ref + 1) + namelen; | 1121 | ref_ptr = (unsigned long)(ref_ptr + ref_struct_size) + namelen; |
960 | kfree(name); | 1122 | kfree(name); |
1123 | if (log_ref_ver) { | ||
1124 | iput(dir); | ||
1125 | dir = NULL; | ||
1126 | } | ||
961 | } | 1127 | } |
962 | 1128 | ||
963 | /* finally write the back reference in the inode */ | 1129 | /* finally write the back reference in the inode */ |
@@ -981,25 +1147,55 @@ static int insert_orphan_item(struct btrfs_trans_handle *trans, | |||
981 | return ret; | 1147 | return ret; |
982 | } | 1148 | } |
983 | 1149 | ||
1150 | static int count_inode_extrefs(struct btrfs_root *root, | ||
1151 | struct inode *inode, struct btrfs_path *path) | ||
1152 | { | ||
1153 | int ret = 0; | ||
1154 | int name_len; | ||
1155 | unsigned int nlink = 0; | ||
1156 | u32 item_size; | ||
1157 | u32 cur_offset = 0; | ||
1158 | u64 inode_objectid = btrfs_ino(inode); | ||
1159 | u64 offset = 0; | ||
1160 | unsigned long ptr; | ||
1161 | struct btrfs_inode_extref *extref; | ||
1162 | struct extent_buffer *leaf; | ||
984 | 1163 | ||
985 | /* | 1164 | while (1) { |
986 | * There are a few corners where the link count of the file can't | 1165 | ret = btrfs_find_one_extref(root, inode_objectid, offset, path, |
987 | * be properly maintained during replay. So, instead of adding | 1166 | &extref, &offset); |
988 | * lots of complexity to the log code, we just scan the backrefs | 1167 | if (ret) |
989 | * for any file that has been through replay. | 1168 | break; |
990 | * | 1169 | |
991 | * The scan will update the link count on the inode to reflect the | 1170 | leaf = path->nodes[0]; |
992 | * number of back refs found. If it goes down to zero, the iput | 1171 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); |
993 | * will free the inode. | 1172 | ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); |
994 | */ | 1173 | |
995 | static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | 1174 | while (cur_offset < item_size) { |
996 | struct btrfs_root *root, | 1175 | extref = (struct btrfs_inode_extref *) (ptr + cur_offset); |
997 | struct inode *inode) | 1176 | name_len = btrfs_inode_extref_name_len(leaf, extref); |
1177 | |||
1178 | nlink++; | ||
1179 | |||
1180 | cur_offset += name_len + sizeof(*extref); | ||
1181 | } | ||
1182 | |||
1183 | offset++; | ||
1184 | btrfs_release_path(path); | ||
1185 | } | ||
1186 | btrfs_release_path(path); | ||
1187 | |||
1188 | if (ret < 0) | ||
1189 | return ret; | ||
1190 | return nlink; | ||
1191 | } | ||
1192 | |||
1193 | static int count_inode_refs(struct btrfs_root *root, | ||
1194 | struct inode *inode, struct btrfs_path *path) | ||
998 | { | 1195 | { |
999 | struct btrfs_path *path; | ||
1000 | int ret; | 1196 | int ret; |
1001 | struct btrfs_key key; | 1197 | struct btrfs_key key; |
1002 | u64 nlink = 0; | 1198 | unsigned int nlink = 0; |
1003 | unsigned long ptr; | 1199 | unsigned long ptr; |
1004 | unsigned long ptr_end; | 1200 | unsigned long ptr_end; |
1005 | int name_len; | 1201 | int name_len; |
@@ -1009,10 +1205,6 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | |||
1009 | key.type = BTRFS_INODE_REF_KEY; | 1205 | key.type = BTRFS_INODE_REF_KEY; |
1010 | key.offset = (u64)-1; | 1206 | key.offset = (u64)-1; |
1011 | 1207 | ||
1012 | path = btrfs_alloc_path(); | ||
1013 | if (!path) | ||
1014 | return -ENOMEM; | ||
1015 | |||
1016 | while (1) { | 1208 | while (1) { |
1017 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 1209 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
1018 | if (ret < 0) | 1210 | if (ret < 0) |
@@ -1046,6 +1238,50 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | |||
1046 | btrfs_release_path(path); | 1238 | btrfs_release_path(path); |
1047 | } | 1239 | } |
1048 | btrfs_release_path(path); | 1240 | btrfs_release_path(path); |
1241 | |||
1242 | return nlink; | ||
1243 | } | ||
1244 | |||
1245 | /* | ||
1246 | * There are a few corners where the link count of the file can't | ||
1247 | * be properly maintained during replay. So, instead of adding | ||
1248 | * lots of complexity to the log code, we just scan the backrefs | ||
1249 | * for any file that has been through replay. | ||
1250 | * | ||
1251 | * The scan will update the link count on the inode to reflect the | ||
1252 | * number of back refs found. If it goes down to zero, the iput | ||
1253 | * will free the inode. | ||
1254 | */ | ||
1255 | static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | ||
1256 | struct btrfs_root *root, | ||
1257 | struct inode *inode) | ||
1258 | { | ||
1259 | struct btrfs_path *path; | ||
1260 | int ret; | ||
1261 | u64 nlink = 0; | ||
1262 | u64 ino = btrfs_ino(inode); | ||
1263 | |||
1264 | path = btrfs_alloc_path(); | ||
1265 | if (!path) | ||
1266 | return -ENOMEM; | ||
1267 | |||
1268 | ret = count_inode_refs(root, inode, path); | ||
1269 | if (ret < 0) | ||
1270 | goto out; | ||
1271 | |||
1272 | nlink = ret; | ||
1273 | |||
1274 | ret = count_inode_extrefs(root, inode, path); | ||
1275 | if (ret == -ENOENT) | ||
1276 | ret = 0; | ||
1277 | |||
1278 | if (ret < 0) | ||
1279 | goto out; | ||
1280 | |||
1281 | nlink += ret; | ||
1282 | |||
1283 | ret = 0; | ||
1284 | |||
1049 | if (nlink != inode->i_nlink) { | 1285 | if (nlink != inode->i_nlink) { |
1050 | set_nlink(inode, nlink); | 1286 | set_nlink(inode, nlink); |
1051 | btrfs_update_inode(trans, root, inode); | 1287 | btrfs_update_inode(trans, root, inode); |
@@ -1061,9 +1297,10 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | |||
1061 | ret = insert_orphan_item(trans, root, ino); | 1297 | ret = insert_orphan_item(trans, root, ino); |
1062 | BUG_ON(ret); | 1298 | BUG_ON(ret); |
1063 | } | 1299 | } |
1064 | btrfs_free_path(path); | ||
1065 | 1300 | ||
1066 | return 0; | 1301 | out: |
1302 | btrfs_free_path(path); | ||
1303 | return ret; | ||
1067 | } | 1304 | } |
1068 | 1305 | ||
1069 | static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, | 1306 | static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, |
@@ -1710,6 +1947,10 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1710 | ret = add_inode_ref(wc->trans, root, log, path, | 1947 | ret = add_inode_ref(wc->trans, root, log, path, |
1711 | eb, i, &key); | 1948 | eb, i, &key); |
1712 | BUG_ON(ret && ret != -ENOENT); | 1949 | BUG_ON(ret && ret != -ENOENT); |
1950 | } else if (key.type == BTRFS_INODE_EXTREF_KEY) { | ||
1951 | ret = add_inode_ref(wc->trans, root, log, path, | ||
1952 | eb, i, &key); | ||
1953 | BUG_ON(ret && ret != -ENOENT); | ||
1713 | } else if (key.type == BTRFS_EXTENT_DATA_KEY) { | 1954 | } else if (key.type == BTRFS_EXTENT_DATA_KEY) { |
1714 | ret = replay_one_extent(wc->trans, root, path, | 1955 | ret = replay_one_extent(wc->trans, root, path, |
1715 | eb, i, &key); | 1956 | eb, i, &key); |