1 /* 2 * Copyright (C) 2007 Oracle. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public 14 * License along with this program; if not, write to the 15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 * Boston, MA 021110-1307, USA. 17 */ 18 19 #include "ctree.h" 20 #include "disk-io.h" 21 #include "hash.h" 22 #include "transaction.h" 23 24 /* 25 * insert a name into a directory, doing overflow properly if there is a hash 26 * collision. data_size indicates how big the item inserted should be. On 27 * success a struct btrfs_dir_item pointer is returned, otherwise it is 28 * an ERR_PTR. 29 * 30 * The name is not copied into the dir item, you have to do that yourself. 31 */ 32 static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle 33 *trans, 34 struct btrfs_root *root, 35 struct btrfs_path *path, 36 struct btrfs_key *cpu_key, 37 u32 data_size, 38 const char *name, 39 int name_len) 40 { 41 int ret; 42 char *ptr; 43 struct btrfs_item *item; 44 struct extent_buffer *leaf; 45 46 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); 47 if (ret == -EEXIST) { 48 struct btrfs_dir_item *di; 49 di = btrfs_match_dir_item_name(root, path, name, name_len); 50 if (di) 51 return ERR_PTR(-EEXIST); 52 ret = btrfs_extend_item(trans, root, path, data_size); 53 } 54 if (ret < 0) 55 return ERR_PTR(ret); 56 WARN_ON(ret > 0); 57 leaf = path->nodes[0]; 58 item = btrfs_item_nr(leaf, path->slots[0]); 59 ptr = btrfs_item_ptr(leaf, path->slots[0], char); 60 BUG_ON(data_size > btrfs_item_size(leaf, item)); 61 ptr += btrfs_item_size(leaf, item) - data_size; 62 return (struct btrfs_dir_item *)ptr; 63 } 64 65 /* 66 * xattrs work a lot like directories, this inserts an xattr item 67 * into the tree 68 */ 69 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, 70 struct btrfs_root *root, 71 struct btrfs_path *path, u64 objectid, 72 const char *name, u16 name_len, 73 const void *data, u16 data_len) 74 { 75 int ret = 0; 76 struct btrfs_dir_item *dir_item; 77 unsigned long name_ptr, data_ptr; 78 struct btrfs_key key, location; 79 struct btrfs_disk_key disk_key; 80 struct extent_buffer *leaf; 81 u32 data_size; 82 83 BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root)); 84 85 key.objectid = objectid; 86 btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); 87 key.offset = btrfs_name_hash(name, name_len); 88 89 data_size = sizeof(*dir_item) + name_len + data_len; 90 dir_item = insert_with_overflow(trans, root, path, &key, data_size, 91 name, name_len); 92 /* 93 * FIXME: at some point we should handle xattr's that are larger than 94 * what we can fit in our leaf. We set location to NULL b/c we arent 95 * pointing at anything else, that will change if we store the xattr 96 * data in a separate inode. 97 */ 98 BUG_ON(IS_ERR(dir_item)); 99 memset(&location, 0, sizeof(location)); 100 101 leaf = path->nodes[0]; 102 btrfs_cpu_key_to_disk(&disk_key, &location); 103 btrfs_set_dir_item_key(leaf, dir_item, &disk_key); 104 btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR); 105 btrfs_set_dir_name_len(leaf, dir_item, name_len); 106 btrfs_set_dir_transid(leaf, dir_item, trans->transid); 107 btrfs_set_dir_data_len(leaf, dir_item, data_len); 108 name_ptr = (unsigned long)(dir_item + 1); 109 data_ptr = (unsigned long)((char *)name_ptr + name_len); 110 111 write_extent_buffer(leaf, name, name_ptr, name_len); 112 write_extent_buffer(leaf, data, data_ptr, data_len); 113 btrfs_mark_buffer_dirty(path->nodes[0]); 114 115 return ret; 116 } 117 118 /* 119 * insert a directory item in the tree, doing all the magic for 120 * both indexes. 'dir' indicates which objectid to insert it into, 121 * 'location' is the key to stuff into the directory item, 'type' is the 122 * type of the inode we're pointing to, and 'index' is the sequence number 123 * to use for the second index (if one is created). 124 */ 125 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root 126 *root, const char *name, int name_len, 127 struct inode *dir, struct btrfs_key *location, 128 u8 type, u64 index) 129 { 130 int ret = 0; 131 int ret2 = 0; 132 struct btrfs_path *path; 133 struct btrfs_dir_item *dir_item; 134 struct extent_buffer *leaf; 135 unsigned long name_ptr; 136 struct btrfs_key key; 137 struct btrfs_disk_key disk_key; 138 u32 data_size; 139 140 key.objectid = btrfs_ino(dir); 141 btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); 142 key.offset = btrfs_name_hash(name, name_len); 143 144 path = btrfs_alloc_path(); 145 if (!path) 146 return -ENOMEM; 147 path->leave_spinning = 1; 148 149 btrfs_cpu_key_to_disk(&disk_key, location); 150 151 data_size = sizeof(*dir_item) + name_len; 152 dir_item = insert_with_overflow(trans, root, path, &key, data_size, 153 name, name_len); 154 if (IS_ERR(dir_item)) { 155 ret = PTR_ERR(dir_item); 156 if (ret == -EEXIST) 157 goto second_insert; 158 goto out_free; 159 } 160 161 leaf = path->nodes[0]; 162 btrfs_set_dir_item_key(leaf, dir_item, &disk_key); 163 btrfs_set_dir_type(leaf, dir_item, type); 164 btrfs_set_dir_data_len(leaf, dir_item, 0); 165 btrfs_set_dir_name_len(leaf, dir_item, name_len); 166 btrfs_set_dir_transid(leaf, dir_item, trans->transid); 167 name_ptr = (unsigned long)(dir_item + 1); 168 169 write_extent_buffer(leaf, name, name_ptr, name_len); 170 btrfs_mark_buffer_dirty(leaf); 171 172 second_insert: 173 /* FIXME, use some real flag for selecting the extra index */ 174 if (root == root->fs_info->tree_root) { 175 ret = 0; 176 goto out_free; 177 } 178 btrfs_release_path(path); 179 180 ret2 = btrfs_insert_delayed_dir_index(trans, root, name, name_len, dir, 181 &disk_key, type, index); 182 out_free: 183 btrfs_free_path(path); 184 if (ret) 185 return ret; 186 if (ret2) 187 return ret2; 188 return 0; 189 } 190 191 /* 192 * lookup a directory item based on name. 'dir' is the objectid 193 * we're searching in, and 'mod' tells us if you plan on deleting the 194 * item (use mod < 0) or changing the options (use mod > 0) 195 */ 196 struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, 197 struct btrfs_root *root, 198 struct btrfs_path *path, u64 dir, 199 const char *name, int name_len, 200 int mod) 201 { 202 int ret; 203 struct btrfs_key key; 204 int ins_len = mod < 0 ? -1 : 0; 205 int cow = mod != 0; 206 struct btrfs_key found_key; 207 struct extent_buffer *leaf; 208 209 key.objectid = dir; 210 btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); 211 212 key.offset = btrfs_name_hash(name, name_len); 213 214 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); 215 if (ret < 0) 216 return ERR_PTR(ret); 217 if (ret > 0) { 218 if (path->slots[0] == 0) 219 return NULL; 220 path->slots[0]--; 221 } 222 223 leaf = path->nodes[0]; 224 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 225 226 if (found_key.objectid != dir || 227 btrfs_key_type(&found_key) != BTRFS_DIR_ITEM_KEY || 228 found_key.offset != key.offset) 229 return NULL; 230 231 return btrfs_match_dir_item_name(root, path, name, name_len); 232 } 233 234 /* 235 * lookup a directory item based on index. 'dir' is the objectid 236 * we're searching in, and 'mod' tells us if you plan on deleting the 237 * item (use mod < 0) or changing the options (use mod > 0) 238 * 239 * The name is used to make sure the index really points to the name you were 240 * looking for. 241 */ 242 struct btrfs_dir_item * 243 btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, 244 struct btrfs_root *root, 245 struct btrfs_path *path, u64 dir, 246 u64 objectid, const char *name, int name_len, 247 int mod) 248 { 249 int ret; 250 struct btrfs_key key; 251 int ins_len = mod < 0 ? -1 : 0; 252 int cow = mod != 0; 253 254 key.objectid = dir; 255 btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); 256 key.offset = objectid; 257 258 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); 259 if (ret < 0) 260 return ERR_PTR(ret); 261 if (ret > 0) 262 return ERR_PTR(-ENOENT); 263 return btrfs_match_dir_item_name(root, path, name, name_len); 264 } 265 266 struct btrfs_dir_item * 267 btrfs_search_dir_index_item(struct btrfs_root *root, 268 struct btrfs_path *path, u64 dirid, 269 const char *name, int name_len) 270 { 271 struct extent_buffer *leaf; 272 struct btrfs_dir_item *di; 273 struct btrfs_key key; 274 u32 nritems; 275 int ret; 276 277 key.objectid = dirid; 278 key.type = BTRFS_DIR_INDEX_KEY; 279 key.offset = 0; 280 281 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 282 if (ret < 0) 283 return ERR_PTR(ret); 284 285 leaf = path->nodes[0]; 286 nritems = btrfs_header_nritems(leaf); 287 288 while (1) { 289 if (path->slots[0] >= nritems) { 290 ret = btrfs_next_leaf(root, path); 291 if (ret < 0) 292 return ERR_PTR(ret); 293 if (ret > 0) 294 break; 295 leaf = path->nodes[0]; 296 nritems = btrfs_header_nritems(leaf); 297 continue; 298 } 299 300 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 301 if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY) 302 break; 303 304 di = btrfs_match_dir_item_name(root, path, name, name_len); 305 if (di) 306 return di; 307 308 path->slots[0]++; 309 } 310 return NULL; 311 } 312 313 struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, 314 struct btrfs_root *root, 315 struct btrfs_path *path, u64 dir, 316 const char *name, u16 name_len, 317 int mod) 318 { 319 int ret; 320 struct btrfs_key key; 321 int ins_len = mod < 0 ? -1 : 0; 322 int cow = mod != 0; 323 struct btrfs_key found_key; 324 struct extent_buffer *leaf; 325 326 key.objectid = dir; 327 btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY); 328 key.offset = btrfs_name_hash(name, name_len); 329 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); 330 if (ret < 0) 331 return ERR_PTR(ret); 332 if (ret > 0) { 333 if (path->slots[0] == 0) 334 return NULL; 335 path->slots[0]--; 336 } 337 338 leaf = path->nodes[0]; 339 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 340 341 if (found_key.objectid != dir || 342 btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY || 343 found_key.offset != key.offset) 344 return NULL; 345 346 return btrfs_match_dir_item_name(root, path, name, name_len); 347 } 348 349 /* 350 * helper function to look at the directory item pointed to by 'path' 351 * this walks through all the entries in a dir item and finds one 352 * for a specific name. 353 */ 354 struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, 355 struct btrfs_path *path, 356 const char *name, int name_len) 357 { 358 struct btrfs_dir_item *dir_item; 359 unsigned long name_ptr; 360 u32 total_len; 361 u32 cur = 0; 362 u32 this_len; 363 struct extent_buffer *leaf; 364 365 leaf = path->nodes[0]; 366 dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); 367 if (verify_dir_item(root, leaf, dir_item)) 368 return NULL; 369 370 total_len = btrfs_item_size_nr(leaf, path->slots[0]); 371 while (cur < total_len) { 372 this_len = sizeof(*dir_item) + 373 btrfs_dir_name_len(leaf, dir_item) + 374 btrfs_dir_data_len(leaf, dir_item); 375 name_ptr = (unsigned long)(dir_item + 1); 376 377 if (btrfs_dir_name_len(leaf, dir_item) == name_len && 378 memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) 379 return dir_item; 380 381 cur += this_len; 382 dir_item = (struct btrfs_dir_item *)((char *)dir_item + 383 this_len); 384 } 385 return NULL; 386 } 387 388 /* 389 * given a pointer into a directory item, delete it. This 390 * handles items that have more than one entry in them. 391 */ 392 int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, 393 struct btrfs_root *root, 394 struct btrfs_path *path, 395 struct btrfs_dir_item *di) 396 { 397 398 struct extent_buffer *leaf; 399 u32 sub_item_len; 400 u32 item_len; 401 int ret = 0; 402 403 leaf = path->nodes[0]; 404 sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) + 405 btrfs_dir_data_len(leaf, di); 406 item_len = btrfs_item_size_nr(leaf, path->slots[0]); 407 if (sub_item_len == item_len) { 408 ret = btrfs_del_item(trans, root, path); 409 } else { 410 /* MARKER */ 411 unsigned long ptr = (unsigned long)di; 412 unsigned long start; 413 414 start = btrfs_item_ptr_offset(leaf, path->slots[0]); 415 memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, 416 item_len - (ptr + sub_item_len - start)); 417 ret = btrfs_truncate_item(trans, root, path, 418 item_len - sub_item_len, 1); 419 } 420 return ret; 421 } 422 423 int verify_dir_item(struct btrfs_root *root, 424 struct extent_buffer *leaf, 425 struct btrfs_dir_item *dir_item) 426 { 427 u16 namelen = BTRFS_NAME_LEN; 428 u8 type = btrfs_dir_type(leaf, dir_item); 429 430 if (type >= BTRFS_FT_MAX) { 431 printk(KERN_CRIT "btrfs: invalid dir item type: %d\n", 432 (int)type); 433 return 1; 434 } 435 436 if (type == BTRFS_FT_XATTR) 437 namelen = XATTR_NAME_MAX; 438 439 if (btrfs_dir_name_len(leaf, dir_item) > namelen) { 440 printk(KERN_CRIT "btrfs: invalid dir item name len: %u\n", 441 (unsigned)btrfs_dir_data_len(leaf, dir_item)); 442 return 1; 443 } 444 445 /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */ 446 if (btrfs_dir_data_len(leaf, dir_item) > BTRFS_MAX_XATTR_SIZE(root)) { 447 printk(KERN_CRIT "btrfs: invalid dir item data len: %u\n", 448 (unsigned)btrfs_dir_data_len(leaf, dir_item)); 449 return 1; 450 } 451 452 return 0; 453 } 454