btrfs-progs: mute coverity warnings about deadcode
[platform/upstream/btrfs-progs.git] / inode.c
1 /*
2  * Copyright (C) 2014 Fujitsu.  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 /*
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 performence sensitive.
24  */
25 #include <sys/stat.h>
26
27 #include "ctree.h"
28 #include "transaction.h"
29 #include "disk-io.h"
30 #include "time.h"
31
32 /*
33  * Find a free inode index for later btrfs_add_link().
34  * Currently just search from the largest dir_index and +1.
35  */
36 static int btrfs_find_free_dir_index(struct btrfs_root *root, u64 dir_ino,
37                                      u64 *ret_ino)
38 {
39         struct btrfs_path *path;
40         struct btrfs_key key;
41         struct btrfs_key found_key;
42         u64 ret_val = 2;
43         int ret = 0;
44
45         if (!ret_ino)
46                 return 0;
47
48         path = btrfs_alloc_path();
49         if (!path)
50                 return -ENOMEM;
51
52         key.objectid = dir_ino;
53         key.type = BTRFS_DIR_INDEX_KEY;
54         key.offset = (u64)-1;
55
56         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
57         if (ret < 0)
58                 goto out;
59         ret = 0;
60         if (path->slots[0] == 0) {
61                 ret = btrfs_prev_leaf(root, path);
62                 if (ret < 0)
63                         goto out;
64                 if (ret > 0) {
65                         /*
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.
69                          */
70                         ret = -EIO;
71                         goto out;
72                 }
73         } else {
74                 path->slots[0]--;
75         }
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)
79                 goto out;
80         ret_val = found_key.offset + 1;
81 out:
82         btrfs_free_path(path);
83         if (ret == 0)
84                 *ret_ino = ret_val;
85         return ret;
86 }
87
88 /* Check the dir_item/index conflicts before insert */
89 int check_dir_conflict(struct btrfs_root *root, char *name, int namelen,
90                        u64 dir, u64 index)
91 {
92         struct btrfs_path *path;
93         struct btrfs_key key;
94         struct btrfs_inode_item *inode_item;
95         struct btrfs_dir_item *dir_item;
96         int ret = 0;
97
98         path = btrfs_alloc_path();
99         if (!path)
100                 return -ENOMEM;
101
102         /* Given dir exists? */
103         key.objectid = dir;
104         key.type = BTRFS_INODE_ITEM_KEY;
105         key.offset = 0;
106         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
107         if (ret < 0)
108                 goto out;
109         if (ret > 0) {
110                 ret = -ENOENT;
111                 goto out;
112         }
113
114         /* Is it a dir? */
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)) {
118                 ret = -ENOTDIR;
119                 goto out;
120         }
121         btrfs_release_path(path);
122
123         /* Name conflicting? */
124         dir_item = btrfs_lookup_dir_item(NULL, root, path, dir, name,
125                                          namelen, 0);
126         if (IS_ERR(dir_item)) {
127                 ret = PTR_ERR(dir_item);
128                 goto out;
129         }
130         if (dir_item) {
131                 ret = -EEXIST;
132                 goto out;
133         }
134         btrfs_release_path(path);
135
136         /* Index conflicting? */
137         dir_item = btrfs_lookup_dir_index(NULL, root, path, dir, name,
138                                           namelen, index, 0);
139         if (IS_ERR(dir_item) && PTR_ERR(dir_item) == -ENOENT)
140                 dir_item = NULL;
141         if (IS_ERR(dir_item)) {
142                 ret = PTR_ERR(dir_item);
143                 goto out;
144         }
145         if (dir_item) {
146                 ret = -EEXIST;
147                 goto out;
148         }
149
150 out:
151         btrfs_free_path(path);
152         return ret;
153 }
154
155 /*
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
158  * not do this thing)
159  *
160  * Currently only supports adding link from an inode to another inode.
161  */
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)
165 {
166         struct btrfs_path *path;
167         struct btrfs_key key;
168         struct btrfs_inode_item *inode_item;
169         u32 nlink;
170         u64 inode_size;
171         u64 ret_index = 0;
172         int ret = 0;
173
174         path = btrfs_alloc_path();
175         if (!path)
176                 return -ENOMEM;
177
178         if (index && *index) {
179                 ret_index = *index;
180         } else {
181                 ret = btrfs_find_free_dir_index(root, parent_ino, &ret_index);
182                 if (ret < 0)
183                         goto out;
184         }
185
186         ret = check_dir_conflict(root, name, namelen, parent_ino, ret_index);
187         if (ret < 0)
188                 goto out;
189
190         /* Add inode ref */
191         if (add_backref) {
192                 ret = btrfs_insert_inode_ref(trans, root, name, namelen,
193                                              ino, parent_ino, ret_index);
194                 if (ret < 0)
195                         goto out;
196
197                 /* Update nlinks for the inode */
198                 key.objectid = ino;
199                 key.type = BTRFS_INODE_ITEM_KEY;
200                 key.offset = 0;
201                 ret = btrfs_search_slot(trans, root, &key, path, 1, 1);
202                 if (ret) {
203                         if (ret > 0)
204                                 ret = -ENOENT;
205                         goto out;
206                 }
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);
210                 nlink++;
211                 btrfs_set_inode_nlink(path->nodes[0], inode_item, nlink);
212                 btrfs_mark_buffer_dirty(path->nodes[0]);
213                 btrfs_release_path(path);
214         }
215
216         /* Add dir_item and dir_index */
217         key.objectid = ino;
218         key.type = BTRFS_INODE_ITEM_KEY;
219         key.offset = 0;
220         ret = btrfs_insert_dir_item(trans, root, name, namelen, parent_ino,
221                                     &key, type, ret_index);
222         if (ret < 0)
223                 goto out;
224
225         /* Update inode size of the parent inode */
226         key.objectid = parent_ino;
227         key.type = BTRFS_INODE_ITEM_KEY;
228         key.offset = 0;
229         ret = btrfs_search_slot(trans, root, &key, path, 1, 1);
230         if (ret)
231                 goto out;
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);
239
240 out:
241         btrfs_free_path(path);
242         if (ret == 0 && index)
243                 *index = ret_index;
244         return ret;
245 }
246
247 int btrfs_add_orphan_item(struct btrfs_trans_handle *trans,
248                           struct btrfs_root *root, struct btrfs_path *path,
249                           u64 ino)
250 {
251         struct btrfs_key key;
252
253         key.objectid = BTRFS_ORPHAN_OBJECTID;
254         key.type = BTRFS_ORPHAN_ITEM_KEY;
255         key.offset = ino;
256
257         return btrfs_insert_empty_item(trans, root, path, &key, 0);
258 }
259
260 /*
261  * Unlink an inode, which will remove its backref and corresponding dir_index/
262  * dir_item if any of them exists.
263  *
264  * If an inode's nlink is reduced to 0 and 'add_orphan' is true, it will be
265  * added to orphan inode and wairing to be deleted by next kernel mount.
266  */
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)
270 {
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;
276         u64 inode_size;
277         u32 nlinks;
278         int del_inode_ref = 0;
279         int del_dir_item = 0;
280         int del_dir_index = 0;
281         int ret = 0;
282
283         path = btrfs_alloc_path();
284         if (!path)
285                 return -ENOMEM;
286
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);
292                 goto out;
293         }
294         if (inode_ref)
295                 del_inode_ref = 1;
296         btrfs_release_path(path);
297
298         dir_item = btrfs_lookup_dir_item(NULL, root, path, parent_ino,
299                                          name, namelen, 0);
300         if (IS_ERR(dir_item)) {
301                 ret = PTR_ERR(dir_item);
302                 goto out;
303         }
304         if (dir_item)
305                 del_dir_item = 1;
306         btrfs_release_path(path);
307
308         dir_item = btrfs_lookup_dir_index(NULL, root, path, parent_ino,
309                                           name, namelen, index, 0);
310         /*
311          * Since lookup_dir_index() will return -ENOENT when not found,
312          * we need to do extra check.
313          */
314         if (IS_ERR(dir_item) && PTR_ERR(dir_item) == -ENOENT)
315                 dir_item = NULL;
316         if (IS_ERR(dir_item)) {
317                 ret = PTR_ERR(dir_item);
318                 goto out;
319         }
320         if (dir_item)
321                 del_dir_index = 1;
322         btrfs_release_path(path);
323
324         if (!del_inode_ref && !del_dir_item && !del_dir_index) {
325                 /* All not found, shouldn't happen */
326                 ret = -ENOENT;
327                 goto out;
328         }
329
330         if (del_inode_ref) {
331                 /* Only decrease nlink when deleting inode_ref */
332                 key.objectid = ino;
333                 key.type = BTRFS_INODE_ITEM_KEY;
334                 key.offset = 0;
335                 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
336                 if (ret) {
337                         if (ret > 0)
338                                 ret = -ENOENT;
339                         goto out;
340                 }
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);
344                 if (nlinks > 0)
345                         nlinks--;
346                 btrfs_set_inode_nlink(path->nodes[0], inode_item, nlinks);
347                 btrfs_mark_buffer_dirty(path->nodes[0]);
348                 btrfs_release_path(path);
349
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);
353                         if (ret < 0)
354                                 goto out;
355                         btrfs_mark_buffer_dirty(path->nodes[0]);
356                         btrfs_release_path(path);
357                 }
358
359                 ret = btrfs_del_inode_ref(trans, root, name, namelen, ino,
360                                           parent_ino, &index);
361                 if (ret < 0)
362                         goto out;
363         }
364
365         if (del_dir_index) {
366                 dir_item = btrfs_lookup_dir_index(trans, root, path,
367                                                   parent_ino, name, namelen,
368                                                   index, -1);
369                 if (IS_ERR(dir_item)) {
370                         ret = PTR_ERR(dir_item);
371                         goto out;
372                 }
373                 if (!dir_item) {
374                         ret = -ENOENT;
375                         goto out;
376                 }
377                 ret = btrfs_delete_one_dir_name(trans, root, path, dir_item);
378                 if (ret)
379                         goto out;
380                 btrfs_release_path(path);
381
382                 /* Update inode size of the parent inode */
383                 key.objectid = parent_ino;
384                 key.type = BTRFS_INODE_ITEM_KEY;
385                 key.offset = 0;
386                 ret = btrfs_search_slot(trans, root, &key, path, 1, 1);
387                 if (ret)
388                         goto out;
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);
397         }
398
399         if (del_dir_item) {
400                 dir_item = btrfs_lookup_dir_item(trans, root, path, parent_ino,
401                                                  name, namelen, -1);
402                 if (IS_ERR(dir_item)) {
403                         ret = PTR_ERR(dir_item);
404                         goto out;
405                 }
406                 if (!dir_item) {
407                         ret = -ENOENT;
408                         goto out;
409                 }
410                 ret = btrfs_delete_one_dir_name(trans, root, path, dir_item);
411                 if (ret < 0)
412                         goto out;
413                 btrfs_release_path(path);
414
415                 /* Update inode size of the parent inode */
416                 key.objectid = parent_ino;
417                 key.type = BTRFS_INODE_ITEM_KEY;
418                 key.offset = 0;
419                 ret = btrfs_search_slot(trans, root, &key, path, 1, 1);
420                 if (ret)
421                         goto out;
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);
430         }
431
432 out:
433         btrfs_free_path(path);
434         return ret;
435 }
436
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,
440                             u32 mode, u32 nlink)
441 {
442         time_t now = time(NULL);
443
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);
456 }
457
458 /*
459  * Unlike kernel btrfs_new_inode(), we only create the INODE_ITEM, without
460  * its backref.
461  * The backref is added by btrfs_add_link().
462  */
463 int btrfs_new_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root,
464                 u64 ino, u32 mode)
465 {
466         struct btrfs_inode_item inode_item = {0};
467         int ret = 0;
468
469         fill_inode_item(trans, &inode_item, mode, 0);
470         ret = btrfs_insert_inode(trans, root, ino, &inode_item);
471         return ret;
472 }
473
474 /*
475  * Make a dir under the parent inode 'parent_ino' with 'name'
476  * and 'mode', The owner will be root/root.
477  */
478 int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
479                 char *name, int namelen, u64 parent_ino, u64 *ino, int mode)
480 {
481         struct btrfs_dir_item *dir_item;
482         struct btrfs_path *path;
483         u64 ret_ino = 0;
484         int ret = 0;
485
486         path = btrfs_alloc_path();
487         if (!path)
488                 return -ENOMEM;
489
490         if (ino && *ino)
491                 ret_ino = *ino;
492
493         dir_item = btrfs_lookup_dir_item(NULL, root, path, parent_ino,
494                                          name, namelen, 0);
495         if (IS_ERR(dir_item)) {
496                 ret = PTR_ERR(dir_item);
497                 goto out;
498         }
499
500         if (dir_item) {
501                 struct btrfs_key found_key;
502
503                 /*
504                  * Already have conflicting name, check if it is a dir.
505                  * Either way, no need to continue.
506                  */
507                 btrfs_dir_item_key_to_cpu(path->nodes[0], dir_item, &found_key);
508                 ret_ino = found_key.objectid;
509                 if (btrfs_dir_type(path->nodes[0], dir_item) != BTRFS_FT_DIR)
510                         ret = -EEXIST;
511                 goto out;
512         }
513
514         if (!ret_ino)
515                 /*
516                  * This is *UNSAFE* if some leaf is corrupted,
517                  * only used as a fallback method. Caller should either
518                  * ensure the fs is OK or pass ino with unused inode number.
519                  */
520                 ret = btrfs_find_free_objectid(NULL, root, parent_ino,
521                                                &ret_ino);
522         if (ret)
523                 goto out;
524         ret = btrfs_new_inode(trans, root, ret_ino, mode | S_IFDIR);
525         if (ret)
526                 goto out;
527         ret = btrfs_add_link(trans, root, ret_ino, parent_ino, name, namelen,
528                              BTRFS_FT_DIR, NULL, 1);
529         if (ret)
530                 goto out;
531 out:
532         btrfs_free_path(path);
533         if (ret == 0 && ino)
534                 *ino = ret_ino;
535         return ret;
536 }