2 * Copyright (C) 2014 Fujitsu. All rights reserved.
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.
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.
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.
20 * Unlike inode.c in kernel, which can use most of the kernel infrastructure
21 * like inode/dentry things, in user-land, we can only use inode number to
22 * do directly operation on extent buffer, which may cause extra searching,
23 * but should not be a huge problem since progs is less performance sensitive.
28 #include "transaction.h"
33 * Find a free inode index for later btrfs_add_link().
34 * Currently just search from the largest dir_index and +1.
36 static int btrfs_find_free_dir_index(struct btrfs_root
*root
, u64 dir_ino
,
39 struct btrfs_path
*path
;
41 struct btrfs_key found_key
;
48 path
= btrfs_alloc_path();
52 key
.objectid
= dir_ino
;
53 key
.type
= BTRFS_DIR_INDEX_KEY
;
56 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
60 if (path
->slots
[0] == 0) {
61 ret
= btrfs_prev_leaf(root
, path
);
66 * This shouldn't happen since there must be a leaf
67 * containing the DIR_ITEM.
68 * Can only happen when the previous leaf is corrupted.
76 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
, path
->slots
[0]);
77 if (found_key
.objectid
!= dir_ino
||
78 found_key
.type
!= BTRFS_DIR_INDEX_KEY
)
80 ret_val
= found_key
.offset
+ 1;
82 btrfs_free_path(path
);
88 /* Check the dir_item/index conflicts before insert */
89 int check_dir_conflict(struct btrfs_root
*root
, char *name
, int namelen
,
92 struct btrfs_path
*path
;
94 struct btrfs_inode_item
*inode_item
;
95 struct btrfs_dir_item
*dir_item
;
98 path
= btrfs_alloc_path();
102 /* Given dir exists? */
104 key
.type
= BTRFS_INODE_ITEM_KEY
;
106 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
115 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
116 struct btrfs_inode_item
);
117 if (!(btrfs_inode_mode(path
->nodes
[0], inode_item
) & S_IFDIR
)) {
121 btrfs_release_path(path
);
123 /* Name conflicting? */
124 dir_item
= btrfs_lookup_dir_item(NULL
, root
, path
, dir
, name
,
126 if (IS_ERR(dir_item
)) {
127 ret
= PTR_ERR(dir_item
);
134 btrfs_release_path(path
);
136 /* Index conflicting? */
137 dir_item
= btrfs_lookup_dir_index(NULL
, root
, path
, dir
, name
,
139 if (IS_ERR(dir_item
) && PTR_ERR(dir_item
) == -ENOENT
)
141 if (IS_ERR(dir_item
)) {
142 ret
= PTR_ERR(dir_item
);
151 btrfs_free_path(path
);
156 * Add dir_item/index for 'parent_ino' if add_backref is true, also insert a
157 * backref from the ino to parent dir and update the nlink(Kernel version does
160 * Currently only supports adding link from an inode to another inode.
162 int btrfs_add_link(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
163 u64 ino
, u64 parent_ino
, char *name
, int namelen
,
164 u8 type
, u64
*index
, int add_backref
)
166 struct btrfs_path
*path
;
167 struct btrfs_key key
;
168 struct btrfs_inode_item
*inode_item
;
174 path
= btrfs_alloc_path();
178 if (index
&& *index
) {
181 ret
= btrfs_find_free_dir_index(root
, parent_ino
, &ret_index
);
186 ret
= check_dir_conflict(root
, name
, namelen
, parent_ino
, ret_index
);
192 ret
= btrfs_insert_inode_ref(trans
, root
, name
, namelen
,
193 ino
, parent_ino
, ret_index
);
197 /* Update nlinks for the inode */
199 key
.type
= BTRFS_INODE_ITEM_KEY
;
201 ret
= btrfs_search_slot(trans
, root
, &key
, path
, 1, 1);
207 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
208 struct btrfs_inode_item
);
209 nlink
= btrfs_inode_nlink(path
->nodes
[0], inode_item
);
211 btrfs_set_inode_nlink(path
->nodes
[0], inode_item
, nlink
);
212 btrfs_mark_buffer_dirty(path
->nodes
[0]);
213 btrfs_release_path(path
);
216 /* Add dir_item and dir_index */
218 key
.type
= BTRFS_INODE_ITEM_KEY
;
220 ret
= btrfs_insert_dir_item(trans
, root
, name
, namelen
, parent_ino
,
221 &key
, type
, ret_index
);
225 /* Update inode size of the parent inode */
226 key
.objectid
= parent_ino
;
227 key
.type
= BTRFS_INODE_ITEM_KEY
;
229 ret
= btrfs_search_slot(trans
, root
, &key
, path
, 1, 1);
232 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
233 struct btrfs_inode_item
);
234 inode_size
= btrfs_inode_size(path
->nodes
[0], inode_item
);
235 inode_size
+= namelen
* 2;
236 btrfs_set_inode_size(path
->nodes
[0], inode_item
, inode_size
);
237 btrfs_mark_buffer_dirty(path
->nodes
[0]);
238 btrfs_release_path(path
);
241 btrfs_free_path(path
);
242 if (ret
== 0 && index
)
247 int btrfs_add_orphan_item(struct btrfs_trans_handle
*trans
,
248 struct btrfs_root
*root
, struct btrfs_path
*path
,
251 struct btrfs_key key
;
253 key
.objectid
= BTRFS_ORPHAN_OBJECTID
;
254 key
.type
= BTRFS_ORPHAN_ITEM_KEY
;
257 return btrfs_insert_empty_item(trans
, root
, path
, &key
, 0);
261 * Unlink an inode, which will remove its backref and corresponding dir_index/
262 * dir_item if any of them exists.
264 * If an inode's nlink is reduced to 0 and 'add_orphan' is true, it will be
265 * added to orphan inode and waiting to be deleted by next kernel mount.
267 int btrfs_unlink(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
268 u64 ino
, u64 parent_ino
, u64 index
, const char *name
,
269 int namelen
, int add_orphan
)
271 struct btrfs_path
*path
;
272 struct btrfs_key key
;
273 struct btrfs_inode_item
*inode_item
;
274 struct btrfs_inode_ref
*inode_ref
;
275 struct btrfs_dir_item
*dir_item
;
278 int del_inode_ref
= 0;
279 int del_dir_item
= 0;
280 int del_dir_index
= 0;
283 path
= btrfs_alloc_path();
287 /* check the ref and backref exists */
288 inode_ref
= btrfs_lookup_inode_ref(trans
, root
, path
, name
, namelen
,
289 ino
, parent_ino
, index
, 0);
290 if (IS_ERR(inode_ref
)) {
291 ret
= PTR_ERR(inode_ref
);
296 btrfs_release_path(path
);
298 dir_item
= btrfs_lookup_dir_item(NULL
, root
, path
, parent_ino
,
300 if (IS_ERR(dir_item
)) {
301 ret
= PTR_ERR(dir_item
);
306 btrfs_release_path(path
);
308 dir_item
= btrfs_lookup_dir_index(NULL
, root
, path
, parent_ino
,
309 name
, namelen
, index
, 0);
311 * Since lookup_dir_index() will return -ENOENT when not found,
312 * we need to do extra check.
314 if (IS_ERR(dir_item
) && PTR_ERR(dir_item
) == -ENOENT
)
316 if (IS_ERR(dir_item
)) {
317 ret
= PTR_ERR(dir_item
);
322 btrfs_release_path(path
);
324 if (!del_inode_ref
&& !del_dir_item
&& !del_dir_index
) {
325 /* All not found, shouldn't happen */
331 /* Only decrease nlink when deleting inode_ref */
333 key
.type
= BTRFS_INODE_ITEM_KEY
;
335 ret
= btrfs_search_slot(trans
, root
, &key
, path
, -1, 1);
341 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
342 struct btrfs_inode_item
);
343 nlinks
= btrfs_inode_nlink(path
->nodes
[0], inode_item
);
346 btrfs_set_inode_nlink(path
->nodes
[0], inode_item
, nlinks
);
347 btrfs_mark_buffer_dirty(path
->nodes
[0]);
348 btrfs_release_path(path
);
350 /* For nlinks == 0, add it to orphan list if needed */
351 if (nlinks
== 0 && add_orphan
) {
352 ret
= btrfs_add_orphan_item(trans
, root
, path
, ino
);
355 btrfs_mark_buffer_dirty(path
->nodes
[0]);
356 btrfs_release_path(path
);
359 ret
= btrfs_del_inode_ref(trans
, root
, name
, namelen
, ino
,
366 dir_item
= btrfs_lookup_dir_index(trans
, root
, path
,
367 parent_ino
, name
, namelen
,
369 if (IS_ERR(dir_item
)) {
370 ret
= PTR_ERR(dir_item
);
377 ret
= btrfs_delete_one_dir_name(trans
, root
, path
, dir_item
);
380 btrfs_release_path(path
);
382 /* Update inode size of the parent inode */
383 key
.objectid
= parent_ino
;
384 key
.type
= BTRFS_INODE_ITEM_KEY
;
386 ret
= btrfs_search_slot(trans
, root
, &key
, path
, 1, 1);
389 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
390 struct btrfs_inode_item
);
391 inode_size
= btrfs_inode_size(path
->nodes
[0], inode_item
);
392 if (inode_size
>= namelen
)
393 inode_size
-= namelen
;
394 btrfs_set_inode_size(path
->nodes
[0], inode_item
, inode_size
);
395 btrfs_mark_buffer_dirty(path
->nodes
[0]);
396 btrfs_release_path(path
);
400 dir_item
= btrfs_lookup_dir_item(trans
, root
, path
, parent_ino
,
402 if (IS_ERR(dir_item
)) {
403 ret
= PTR_ERR(dir_item
);
410 ret
= btrfs_delete_one_dir_name(trans
, root
, path
, dir_item
);
413 btrfs_release_path(path
);
415 /* Update inode size of the parent inode */
416 key
.objectid
= parent_ino
;
417 key
.type
= BTRFS_INODE_ITEM_KEY
;
419 ret
= btrfs_search_slot(trans
, root
, &key
, path
, 1, 1);
422 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
423 struct btrfs_inode_item
);
424 inode_size
= btrfs_inode_size(path
->nodes
[0], inode_item
);
425 if (inode_size
>= namelen
)
426 inode_size
-= namelen
;
427 btrfs_set_inode_size(path
->nodes
[0], inode_item
, inode_size
);
428 btrfs_mark_buffer_dirty(path
->nodes
[0]);
429 btrfs_release_path(path
);
433 btrfs_free_path(path
);
437 /* Fill inode item with 'mode'. Uid/gid to root/root */
438 static void fill_inode_item(struct btrfs_trans_handle
*trans
,
439 struct btrfs_inode_item
*inode_item
,
442 time_t now
= time(NULL
);
444 btrfs_set_stack_inode_generation(inode_item
, trans
->transid
);
445 btrfs_set_stack_inode_uid(inode_item
, 0);
446 btrfs_set_stack_inode_gid(inode_item
, 0);
447 btrfs_set_stack_inode_size(inode_item
, 0);
448 btrfs_set_stack_inode_mode(inode_item
, mode
);
449 btrfs_set_stack_inode_nlink(inode_item
, nlink
);
450 btrfs_set_stack_timespec_sec(&inode_item
->atime
, now
);
451 btrfs_set_stack_timespec_nsec(&inode_item
->atime
, 0);
452 btrfs_set_stack_timespec_sec(&inode_item
->mtime
, now
);
453 btrfs_set_stack_timespec_nsec(&inode_item
->mtime
, 0);
454 btrfs_set_stack_timespec_sec(&inode_item
->ctime
, now
);
455 btrfs_set_stack_timespec_nsec(&inode_item
->ctime
, 0);
459 * Unlike kernel btrfs_new_inode(), we only create the INODE_ITEM, without
461 * The backref is added by btrfs_add_link().
463 int btrfs_new_inode(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
466 struct btrfs_inode_item inode_item
= {0};
469 fill_inode_item(trans
, &inode_item
, mode
, 0);
470 ret
= btrfs_insert_inode(trans
, root
, ino
, &inode_item
);
475 * Change inode flags to given value
477 int btrfs_change_inode_flags(struct btrfs_trans_handle
*trans
,
478 struct btrfs_root
*root
, u64 ino
, u64 flags
)
480 struct btrfs_inode_item
*item
;
481 struct btrfs_path
*path
;
482 struct btrfs_key key
;
485 path
= btrfs_alloc_path();
490 key
.type
= BTRFS_INODE_ITEM_KEY
;
493 ret
= btrfs_search_slot(trans
, root
, &key
, path
, 0, 1);
501 item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
502 struct btrfs_inode_item
);
503 btrfs_set_inode_flags(path
->nodes
[0], item
, flags
);
504 btrfs_mark_buffer_dirty(path
->nodes
[0]);
506 btrfs_free_path(path
);
511 * Make a dir under the parent inode 'parent_ino' with 'name'
512 * and 'mode', The owner will be root/root.
514 int btrfs_mkdir(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
515 char *name
, int namelen
, u64 parent_ino
, u64
*ino
, int mode
)
517 struct btrfs_dir_item
*dir_item
;
518 struct btrfs_path
*path
;
522 path
= btrfs_alloc_path();
529 dir_item
= btrfs_lookup_dir_item(NULL
, root
, path
, parent_ino
,
531 if (IS_ERR(dir_item
)) {
532 ret
= PTR_ERR(dir_item
);
537 struct btrfs_key found_key
;
540 * Already have conflicting name, check if it is a dir.
541 * Either way, no need to continue.
543 btrfs_dir_item_key_to_cpu(path
->nodes
[0], dir_item
, &found_key
);
544 ret_ino
= found_key
.objectid
;
545 if (btrfs_dir_type(path
->nodes
[0], dir_item
) != BTRFS_FT_DIR
)
552 * This is *UNSAFE* if some leaf is corrupted,
553 * only used as a fallback method. Caller should either
554 * ensure the fs is OK or pass ino with unused inode number.
556 ret
= btrfs_find_free_objectid(NULL
, root
, parent_ino
,
560 ret
= btrfs_new_inode(trans
, root
, ret_ino
, mode
| S_IFDIR
);
563 ret
= btrfs_add_link(trans
, root
, ret_ino
, parent_ino
, name
, namelen
,
564 BTRFS_FT_DIR
, NULL
, 1);
568 btrfs_free_path(path
);