0001
0002
0003
0004
0005
0006 #include "ctree.h"
0007 #include "disk-io.h"
0008 #include "transaction.h"
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
0019 *trans,
0020 struct btrfs_root *root,
0021 struct btrfs_path *path,
0022 struct btrfs_key *cpu_key,
0023 u32 data_size,
0024 const char *name,
0025 int name_len)
0026 {
0027 struct btrfs_fs_info *fs_info = root->fs_info;
0028 int ret;
0029 char *ptr;
0030 struct extent_buffer *leaf;
0031
0032 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
0033 if (ret == -EEXIST) {
0034 struct btrfs_dir_item *di;
0035 di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
0036 if (di)
0037 return ERR_PTR(-EEXIST);
0038 btrfs_extend_item(path, data_size);
0039 } else if (ret < 0)
0040 return ERR_PTR(ret);
0041 WARN_ON(ret > 0);
0042 leaf = path->nodes[0];
0043 ptr = btrfs_item_ptr(leaf, path->slots[0], char);
0044 ASSERT(data_size <= btrfs_item_size(leaf, path->slots[0]));
0045 ptr += btrfs_item_size(leaf, path->slots[0]) - data_size;
0046 return (struct btrfs_dir_item *)ptr;
0047 }
0048
0049
0050
0051
0052
0053 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
0054 struct btrfs_root *root,
0055 struct btrfs_path *path, u64 objectid,
0056 const char *name, u16 name_len,
0057 const void *data, u16 data_len)
0058 {
0059 int ret = 0;
0060 struct btrfs_dir_item *dir_item;
0061 unsigned long name_ptr, data_ptr;
0062 struct btrfs_key key, location;
0063 struct btrfs_disk_key disk_key;
0064 struct extent_buffer *leaf;
0065 u32 data_size;
0066
0067 if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(root->fs_info))
0068 return -ENOSPC;
0069
0070 key.objectid = objectid;
0071 key.type = BTRFS_XATTR_ITEM_KEY;
0072 key.offset = btrfs_name_hash(name, name_len);
0073
0074 data_size = sizeof(*dir_item) + name_len + data_len;
0075 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
0076 name, name_len);
0077 if (IS_ERR(dir_item))
0078 return PTR_ERR(dir_item);
0079 memset(&location, 0, sizeof(location));
0080
0081 leaf = path->nodes[0];
0082 btrfs_cpu_key_to_disk(&disk_key, &location);
0083 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
0084 btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR);
0085 btrfs_set_dir_name_len(leaf, dir_item, name_len);
0086 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
0087 btrfs_set_dir_data_len(leaf, dir_item, data_len);
0088 name_ptr = (unsigned long)(dir_item + 1);
0089 data_ptr = (unsigned long)((char *)name_ptr + name_len);
0090
0091 write_extent_buffer(leaf, name, name_ptr, name_len);
0092 write_extent_buffer(leaf, data, data_ptr, data_len);
0093 btrfs_mark_buffer_dirty(path->nodes[0]);
0094
0095 return ret;
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, const char *name,
0107 int name_len, struct btrfs_inode *dir,
0108 struct btrfs_key *location, u8 type, u64 index)
0109 {
0110 int ret = 0;
0111 int ret2 = 0;
0112 struct btrfs_root *root = dir->root;
0113 struct btrfs_path *path;
0114 struct btrfs_dir_item *dir_item;
0115 struct extent_buffer *leaf;
0116 unsigned long name_ptr;
0117 struct btrfs_key key;
0118 struct btrfs_disk_key disk_key;
0119 u32 data_size;
0120
0121 key.objectid = btrfs_ino(dir);
0122 key.type = BTRFS_DIR_ITEM_KEY;
0123 key.offset = btrfs_name_hash(name, name_len);
0124
0125 path = btrfs_alloc_path();
0126 if (!path)
0127 return -ENOMEM;
0128
0129 btrfs_cpu_key_to_disk(&disk_key, location);
0130
0131 data_size = sizeof(*dir_item) + name_len;
0132 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
0133 name, name_len);
0134 if (IS_ERR(dir_item)) {
0135 ret = PTR_ERR(dir_item);
0136 if (ret == -EEXIST)
0137 goto second_insert;
0138 goto out_free;
0139 }
0140
0141 leaf = path->nodes[0];
0142 btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
0143 btrfs_set_dir_type(leaf, dir_item, type);
0144 btrfs_set_dir_data_len(leaf, dir_item, 0);
0145 btrfs_set_dir_name_len(leaf, dir_item, name_len);
0146 btrfs_set_dir_transid(leaf, dir_item, trans->transid);
0147 name_ptr = (unsigned long)(dir_item + 1);
0148
0149 write_extent_buffer(leaf, name, name_ptr, name_len);
0150 btrfs_mark_buffer_dirty(leaf);
0151
0152 second_insert:
0153
0154 if (root == root->fs_info->tree_root) {
0155 ret = 0;
0156 goto out_free;
0157 }
0158 btrfs_release_path(path);
0159
0160 ret2 = btrfs_insert_delayed_dir_index(trans, name, name_len, dir,
0161 &disk_key, type, index);
0162 out_free:
0163 btrfs_free_path(path);
0164 if (ret)
0165 return ret;
0166 if (ret2)
0167 return ret2;
0168 return 0;
0169 }
0170
0171 static struct btrfs_dir_item *btrfs_lookup_match_dir(
0172 struct btrfs_trans_handle *trans,
0173 struct btrfs_root *root, struct btrfs_path *path,
0174 struct btrfs_key *key, const char *name,
0175 int name_len, int mod)
0176 {
0177 const int ins_len = (mod < 0 ? -1 : 0);
0178 const int cow = (mod != 0);
0179 int ret;
0180
0181 ret = btrfs_search_slot(trans, root, key, path, ins_len, cow);
0182 if (ret < 0)
0183 return ERR_PTR(ret);
0184 if (ret > 0)
0185 return ERR_PTR(-ENOENT);
0186
0187 return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
0188 }
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
0207 struct btrfs_root *root,
0208 struct btrfs_path *path, u64 dir,
0209 const char *name, int name_len,
0210 int mod)
0211 {
0212 struct btrfs_key key;
0213 struct btrfs_dir_item *di;
0214
0215 key.objectid = dir;
0216 key.type = BTRFS_DIR_ITEM_KEY;
0217 key.offset = btrfs_name_hash(name, name_len);
0218
0219 di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
0220 if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
0221 return NULL;
0222
0223 return di;
0224 }
0225
0226 int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
0227 const char *name, int name_len)
0228 {
0229 int ret;
0230 struct btrfs_key key;
0231 struct btrfs_dir_item *di;
0232 int data_size;
0233 struct extent_buffer *leaf;
0234 int slot;
0235 struct btrfs_path *path;
0236
0237 path = btrfs_alloc_path();
0238 if (!path)
0239 return -ENOMEM;
0240
0241 key.objectid = dir;
0242 key.type = BTRFS_DIR_ITEM_KEY;
0243 key.offset = btrfs_name_hash(name, name_len);
0244
0245 di = btrfs_lookup_match_dir(NULL, root, path, &key, name, name_len, 0);
0246 if (IS_ERR(di)) {
0247 ret = PTR_ERR(di);
0248
0249 if (ret == -ENOENT) {
0250 ret = 0;
0251 goto out;
0252 }
0253
0254 if (ret < 0)
0255 goto out;
0256 }
0257
0258
0259 if (di) {
0260
0261 ret = -EEXIST;
0262 goto out;
0263 }
0264
0265
0266
0267
0268
0269 data_size = sizeof(*di) + name_len;
0270 leaf = path->nodes[0];
0271 slot = path->slots[0];
0272 if (data_size + btrfs_item_size(leaf, slot) +
0273 sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root->fs_info)) {
0274 ret = -EOVERFLOW;
0275 } else {
0276
0277 ret = 0;
0278 }
0279 out:
0280 btrfs_free_path(path);
0281 return ret;
0282 }
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302 struct btrfs_dir_item *
0303 btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
0304 struct btrfs_root *root,
0305 struct btrfs_path *path, u64 dir,
0306 u64 index, const char *name, int name_len,
0307 int mod)
0308 {
0309 struct btrfs_dir_item *di;
0310 struct btrfs_key key;
0311
0312 key.objectid = dir;
0313 key.type = BTRFS_DIR_INDEX_KEY;
0314 key.offset = index;
0315
0316 di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
0317 if (di == ERR_PTR(-ENOENT))
0318 return NULL;
0319
0320 return di;
0321 }
0322
0323 struct btrfs_dir_item *
0324 btrfs_search_dir_index_item(struct btrfs_root *root,
0325 struct btrfs_path *path, u64 dirid,
0326 const char *name, int name_len)
0327 {
0328 struct btrfs_dir_item *di;
0329 struct btrfs_key key;
0330 int ret;
0331
0332 key.objectid = dirid;
0333 key.type = BTRFS_DIR_INDEX_KEY;
0334 key.offset = 0;
0335
0336 btrfs_for_each_slot(root, &key, &key, path, ret) {
0337 if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY)
0338 break;
0339
0340 di = btrfs_match_dir_item_name(root->fs_info, path,
0341 name, name_len);
0342 if (di)
0343 return di;
0344 }
0345
0346 if (ret > 0)
0347 ret = 0;
0348
0349 return ERR_PTR(ret);
0350 }
0351
0352 struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
0353 struct btrfs_root *root,
0354 struct btrfs_path *path, u64 dir,
0355 const char *name, u16 name_len,
0356 int mod)
0357 {
0358 struct btrfs_key key;
0359 struct btrfs_dir_item *di;
0360
0361 key.objectid = dir;
0362 key.type = BTRFS_XATTR_ITEM_KEY;
0363 key.offset = btrfs_name_hash(name, name_len);
0364
0365 di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
0366 if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
0367 return NULL;
0368
0369 return di;
0370 }
0371
0372
0373
0374
0375
0376
0377 struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info,
0378 struct btrfs_path *path,
0379 const char *name, int name_len)
0380 {
0381 struct btrfs_dir_item *dir_item;
0382 unsigned long name_ptr;
0383 u32 total_len;
0384 u32 cur = 0;
0385 u32 this_len;
0386 struct extent_buffer *leaf;
0387
0388 leaf = path->nodes[0];
0389 dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
0390
0391 total_len = btrfs_item_size(leaf, path->slots[0]);
0392 while (cur < total_len) {
0393 this_len = sizeof(*dir_item) +
0394 btrfs_dir_name_len(leaf, dir_item) +
0395 btrfs_dir_data_len(leaf, dir_item);
0396 name_ptr = (unsigned long)(dir_item + 1);
0397
0398 if (btrfs_dir_name_len(leaf, dir_item) == name_len &&
0399 memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
0400 return dir_item;
0401
0402 cur += this_len;
0403 dir_item = (struct btrfs_dir_item *)((char *)dir_item +
0404 this_len);
0405 }
0406 return NULL;
0407 }
0408
0409
0410
0411
0412
0413 int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
0414 struct btrfs_root *root,
0415 struct btrfs_path *path,
0416 struct btrfs_dir_item *di)
0417 {
0418
0419 struct extent_buffer *leaf;
0420 u32 sub_item_len;
0421 u32 item_len;
0422 int ret = 0;
0423
0424 leaf = path->nodes[0];
0425 sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) +
0426 btrfs_dir_data_len(leaf, di);
0427 item_len = btrfs_item_size(leaf, path->slots[0]);
0428 if (sub_item_len == item_len) {
0429 ret = btrfs_del_item(trans, root, path);
0430 } else {
0431
0432 unsigned long ptr = (unsigned long)di;
0433 unsigned long start;
0434
0435 start = btrfs_item_ptr_offset(leaf, path->slots[0]);
0436 memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
0437 item_len - (ptr + sub_item_len - start));
0438 btrfs_truncate_item(path, item_len - sub_item_len, 1);
0439 }
0440 return ret;
0441 }