linux/fs/btrfs/root-tree.c
<<
>>
Prefs
   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 <linux/uuid.h>
  20#include "ctree.h"
  21#include "transaction.h"
  22#include "disk-io.h"
  23#include "print-tree.h"
  24
  25/*
  26 * Read a root item from the tree. In case we detect a root item smaller then
  27 * sizeof(root_item), we know it's an old version of the root structure and
  28 * initialize all new fields to zero. The same happens if we detect mismatching
  29 * generation numbers as then we know the root was once mounted with an older
  30 * kernel that was not aware of the root item structure change.
  31 */
  32void btrfs_read_root_item(struct btrfs_root *root,
  33                         struct extent_buffer *eb, int slot,
  34                         struct btrfs_root_item *item)
  35{
  36        uuid_le uuid;
  37        int len;
  38        int need_reset = 0;
  39
  40        len = btrfs_item_size_nr(eb, slot);
  41        read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot),
  42                        min_t(int, len, (int)sizeof(*item)));
  43        if (len < sizeof(*item))
  44                need_reset = 1;
  45        if (!need_reset && btrfs_root_generation(item)
  46                != btrfs_root_generation_v2(item)) {
  47                if (btrfs_root_generation_v2(item) != 0) {
  48                        printk(KERN_WARNING "btrfs: mismatching "
  49                                        "generation and generation_v2 "
  50                                        "found in root item. This root "
  51                                        "was probably mounted with an "
  52                                        "older kernel. Resetting all "
  53                                        "new fields.\n");
  54                }
  55                need_reset = 1;
  56        }
  57        if (need_reset) {
  58                memset(&item->generation_v2, 0,
  59                        sizeof(*item) - offsetof(struct btrfs_root_item,
  60                                        generation_v2));
  61
  62                uuid_le_gen(&uuid);
  63                memcpy(item->uuid, uuid.b, BTRFS_UUID_SIZE);
  64        }
  65}
  66
  67/*
  68 * lookup the root with the highest offset for a given objectid.  The key we do
  69 * find is copied into 'key'.  If we find something return 0, otherwise 1, < 0
  70 * on error.
  71 */
  72int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
  73                        struct btrfs_root_item *item, struct btrfs_key *key)
  74{
  75        struct btrfs_path *path;
  76        struct btrfs_key search_key;
  77        struct btrfs_key found_key;
  78        struct extent_buffer *l;
  79        int ret;
  80        int slot;
  81
  82        search_key.objectid = objectid;
  83        search_key.type = BTRFS_ROOT_ITEM_KEY;
  84        search_key.offset = (u64)-1;
  85
  86        path = btrfs_alloc_path();
  87        if (!path)
  88                return -ENOMEM;
  89        ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
  90        if (ret < 0)
  91                goto out;
  92
  93        BUG_ON(ret == 0);
  94        if (path->slots[0] == 0) {
  95                ret = 1;
  96                goto out;
  97        }
  98        l = path->nodes[0];
  99        slot = path->slots[0] - 1;
 100        btrfs_item_key_to_cpu(l, &found_key, slot);
 101        if (found_key.objectid != objectid ||
 102            found_key.type != BTRFS_ROOT_ITEM_KEY) {
 103                ret = 1;
 104                goto out;
 105        }
 106        if (item)
 107                btrfs_read_root_item(root, l, slot, item);
 108        if (key)
 109                memcpy(key, &found_key, sizeof(found_key));
 110
 111        ret = 0;
 112out:
 113        btrfs_free_path(path);
 114        return ret;
 115}
 116
 117void btrfs_set_root_node(struct btrfs_root_item *item,
 118                         struct extent_buffer *node)
 119{
 120        btrfs_set_root_bytenr(item, node->start);
 121        btrfs_set_root_level(item, btrfs_header_level(node));
 122        btrfs_set_root_generation(item, btrfs_header_generation(node));
 123}
 124
 125/*
 126 * copy the data in 'item' into the btree
 127 */
 128int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
 129                      *root, struct btrfs_key *key, struct btrfs_root_item
 130                      *item)
 131{
 132        struct btrfs_path *path;
 133        struct extent_buffer *l;
 134        int ret;
 135        int slot;
 136        unsigned long ptr;
 137        int old_len;
 138
 139        path = btrfs_alloc_path();
 140        if (!path)
 141                return -ENOMEM;
 142
 143        ret = btrfs_search_slot(trans, root, key, path, 0, 1);
 144        if (ret < 0)
 145                goto out_abort;
 146
 147        if (ret != 0) {
 148                btrfs_print_leaf(root, path->nodes[0]);
 149                printk(KERN_CRIT "unable to update root key %llu %u %llu\n",
 150                       (unsigned long long)key->objectid, key->type,
 151                       (unsigned long long)key->offset);
 152                BUG_ON(1);
 153        }
 154
 155        l = path->nodes[0];
 156        slot = path->slots[0];
 157        ptr = btrfs_item_ptr_offset(l, slot);
 158        old_len = btrfs_item_size_nr(l, slot);
 159
 160        /*
 161         * If this is the first time we update the root item which originated
 162         * from an older kernel, we need to enlarge the item size to make room
 163         * for the added fields.
 164         */
 165        if (old_len < sizeof(*item)) {
 166                btrfs_release_path(path);
 167                ret = btrfs_search_slot(trans, root, key, path,
 168                                -1, 1);
 169                if (ret < 0)
 170                        goto out_abort;
 171                ret = btrfs_del_item(trans, root, path);
 172                if (ret < 0)
 173                        goto out_abort;
 174                btrfs_release_path(path);
 175                ret = btrfs_insert_empty_item(trans, root, path,
 176                                key, sizeof(*item));
 177                if (ret < 0)
 178                        goto out_abort;
 179                l = path->nodes[0];
 180                slot = path->slots[0];
 181                ptr = btrfs_item_ptr_offset(l, slot);
 182        }
 183
 184        /*
 185         * Update generation_v2 so at the next mount we know the new root
 186         * fields are valid.
 187         */
 188        btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
 189
 190        write_extent_buffer(l, item, ptr, sizeof(*item));
 191        btrfs_mark_buffer_dirty(path->nodes[0]);
 192out:
 193        btrfs_free_path(path);
 194        return ret;
 195
 196out_abort:
 197        btrfs_abort_transaction(trans, root, ret);
 198        goto out;
 199}
 200
 201int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 202                      struct btrfs_key *key, struct btrfs_root_item *item)
 203{
 204        /*
 205         * Make sure generation v1 and v2 match. See update_root for details.
 206         */
 207        btrfs_set_root_generation_v2(item, btrfs_root_generation(item));
 208        return btrfs_insert_item(trans, root, key, item, sizeof(*item));
 209}
 210
 211/*
 212 * at mount time we want to find all the old transaction snapshots that were in
 213 * the process of being deleted if we crashed.  This is any root item with an
 214 * offset lower than the latest root.  They need to be queued for deletion to
 215 * finish what was happening when we crashed.
 216 */
 217int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid)
 218{
 219        struct btrfs_root *dead_root;
 220        struct btrfs_root_item *ri;
 221        struct btrfs_key key;
 222        struct btrfs_key found_key;
 223        struct btrfs_path *path;
 224        int ret;
 225        u32 nritems;
 226        struct extent_buffer *leaf;
 227        int slot;
 228
 229        key.objectid = objectid;
 230        btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
 231        key.offset = 0;
 232        path = btrfs_alloc_path();
 233        if (!path)
 234                return -ENOMEM;
 235
 236again:
 237        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 238        if (ret < 0)
 239                goto err;
 240        while (1) {
 241                leaf = path->nodes[0];
 242                nritems = btrfs_header_nritems(leaf);
 243                slot = path->slots[0];
 244                if (slot >= nritems) {
 245                        ret = btrfs_next_leaf(root, path);
 246                        if (ret)
 247                                break;
 248                        leaf = path->nodes[0];
 249                        nritems = btrfs_header_nritems(leaf);
 250                        slot = path->slots[0];
 251                }
 252                btrfs_item_key_to_cpu(leaf, &key, slot);
 253                if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
 254                        goto next;
 255
 256                if (key.objectid < objectid)
 257                        goto next;
 258
 259                if (key.objectid > objectid)
 260                        break;
 261
 262                ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
 263                if (btrfs_disk_root_refs(leaf, ri) != 0)
 264                        goto next;
 265
 266                memcpy(&found_key, &key, sizeof(key));
 267                key.offset++;
 268                btrfs_release_path(path);
 269                dead_root =
 270                        btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
 271                                                    &found_key);
 272                if (IS_ERR(dead_root)) {
 273                        ret = PTR_ERR(dead_root);
 274                        goto err;
 275                }
 276
 277                ret = btrfs_add_dead_root(dead_root);
 278                if (ret)
 279                        goto err;
 280                goto again;
 281next:
 282                slot++;
 283                path->slots[0]++;
 284        }
 285        ret = 0;
 286err:
 287        btrfs_free_path(path);
 288        return ret;
 289}
 290
 291int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
 292{
 293        struct extent_buffer *leaf;
 294        struct btrfs_path *path;
 295        struct btrfs_key key;
 296        struct btrfs_key root_key;
 297        struct btrfs_root *root;
 298        int err = 0;
 299        int ret;
 300
 301        path = btrfs_alloc_path();
 302        if (!path)
 303                return -ENOMEM;
 304
 305        key.objectid = BTRFS_ORPHAN_OBJECTID;
 306        key.type = BTRFS_ORPHAN_ITEM_KEY;
 307        key.offset = 0;
 308
 309        root_key.type = BTRFS_ROOT_ITEM_KEY;
 310        root_key.offset = (u64)-1;
 311
 312        while (1) {
 313                ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
 314                if (ret < 0) {
 315                        err = ret;
 316                        break;
 317                }
 318
 319                leaf = path->nodes[0];
 320                if (path->slots[0] >= btrfs_header_nritems(leaf)) {
 321                        ret = btrfs_next_leaf(tree_root, path);
 322                        if (ret < 0)
 323                                err = ret;
 324                        if (ret != 0)
 325                                break;
 326                        leaf = path->nodes[0];
 327                }
 328
 329                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
 330                btrfs_release_path(path);
 331
 332                if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
 333                    key.type != BTRFS_ORPHAN_ITEM_KEY)
 334                        break;
 335
 336                root_key.objectid = key.offset;
 337                key.offset++;
 338
 339                root = btrfs_read_fs_root_no_name(tree_root->fs_info,
 340                                                  &root_key);
 341                if (!IS_ERR(root))
 342                        continue;
 343
 344                ret = PTR_ERR(root);
 345                if (ret != -ENOENT) {
 346                        err = ret;
 347                        break;
 348                }
 349
 350                ret = btrfs_find_dead_roots(tree_root, root_key.objectid);
 351                if (ret) {
 352                        err = ret;
 353                        break;
 354                }
 355        }
 356
 357        btrfs_free_path(path);
 358        return err;
 359}
 360
 361/* drop the root item for 'key' from 'root' */
 362int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 363                   struct btrfs_key *key)
 364{
 365        struct btrfs_path *path;
 366        int ret;
 367        struct btrfs_root_item *ri;
 368        struct extent_buffer *leaf;
 369
 370        path = btrfs_alloc_path();
 371        if (!path)
 372                return -ENOMEM;
 373        ret = btrfs_search_slot(trans, root, key, path, -1, 1);
 374        if (ret < 0)
 375                goto out;
 376
 377        BUG_ON(ret != 0);
 378        leaf = path->nodes[0];
 379        ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item);
 380
 381        ret = btrfs_del_item(trans, root, path);
 382out:
 383        btrfs_free_path(path);
 384        return ret;
 385}
 386
 387int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
 388                       struct btrfs_root *tree_root,
 389                       u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
 390                       const char *name, int name_len)
 391
 392{
 393        struct btrfs_path *path;
 394        struct btrfs_root_ref *ref;
 395        struct extent_buffer *leaf;
 396        struct btrfs_key key;
 397        unsigned long ptr;
 398        int err = 0;
 399        int ret;
 400
 401        path = btrfs_alloc_path();
 402        if (!path)
 403                return -ENOMEM;
 404
 405        key.objectid = root_id;
 406        key.type = BTRFS_ROOT_BACKREF_KEY;
 407        key.offset = ref_id;
 408again:
 409        ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
 410        BUG_ON(ret < 0);
 411        if (ret == 0) {
 412                leaf = path->nodes[0];
 413                ref = btrfs_item_ptr(leaf, path->slots[0],
 414                                     struct btrfs_root_ref);
 415
 416                WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
 417                WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
 418                ptr = (unsigned long)(ref + 1);
 419                WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
 420                *sequence = btrfs_root_ref_sequence(leaf, ref);
 421
 422                ret = btrfs_del_item(trans, tree_root, path);
 423                if (ret) {
 424                        err = ret;
 425                        goto out;
 426                }
 427        } else
 428                err = -ENOENT;
 429
 430        if (key.type == BTRFS_ROOT_BACKREF_KEY) {
 431                btrfs_release_path(path);
 432                key.objectid = ref_id;
 433                key.type = BTRFS_ROOT_REF_KEY;
 434                key.offset = root_id;
 435                goto again;
 436        }
 437
 438out:
 439        btrfs_free_path(path);
 440        return err;
 441}
 442
 443int btrfs_find_root_ref(struct btrfs_root *tree_root,
 444                   struct btrfs_path *path,
 445                   u64 root_id, u64 ref_id)
 446{
 447        struct btrfs_key key;
 448        int ret;
 449
 450        key.objectid = root_id;
 451        key.type = BTRFS_ROOT_REF_KEY;
 452        key.offset = ref_id;
 453
 454        ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
 455        return ret;
 456}
 457
 458/*
 459 * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
 460 * or BTRFS_ROOT_BACKREF_KEY.
 461 *
 462 * The dirid, sequence, name and name_len refer to the directory entry
 463 * that is referencing the root.
 464 *
 465 * For a forward ref, the root_id is the id of the tree referencing
 466 * the root and ref_id is the id of the subvol  or snapshot.
 467 *
 468 * For a back ref the root_id is the id of the subvol or snapshot and
 469 * ref_id is the id of the tree referencing it.
 470 *
 471 * Will return 0, -ENOMEM, or anything from the CoW path
 472 */
 473int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
 474                       struct btrfs_root *tree_root,
 475                       u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
 476                       const char *name, int name_len)
 477{
 478        struct btrfs_key key;
 479        int ret;
 480        struct btrfs_path *path;
 481        struct btrfs_root_ref *ref;
 482        struct extent_buffer *leaf;
 483        unsigned long ptr;
 484
 485        path = btrfs_alloc_path();
 486        if (!path)
 487                return -ENOMEM;
 488
 489        key.objectid = root_id;
 490        key.type = BTRFS_ROOT_BACKREF_KEY;
 491        key.offset = ref_id;
 492again:
 493        ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
 494                                      sizeof(*ref) + name_len);
 495        if (ret) {
 496                btrfs_abort_transaction(trans, tree_root, ret);
 497                btrfs_free_path(path);
 498                return ret;
 499        }
 500
 501        leaf = path->nodes[0];
 502        ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
 503        btrfs_set_root_ref_dirid(leaf, ref, dirid);
 504        btrfs_set_root_ref_sequence(leaf, ref, sequence);
 505        btrfs_set_root_ref_name_len(leaf, ref, name_len);
 506        ptr = (unsigned long)(ref + 1);
 507        write_extent_buffer(leaf, name, ptr, name_len);
 508        btrfs_mark_buffer_dirty(leaf);
 509
 510        if (key.type == BTRFS_ROOT_BACKREF_KEY) {
 511                btrfs_release_path(path);
 512                key.objectid = ref_id;
 513                key.type = BTRFS_ROOT_REF_KEY;
 514                key.offset = root_id;
 515                goto again;
 516        }
 517
 518        btrfs_free_path(path);
 519        return 0;
 520}
 521
 522/*
 523 * Old btrfs forgets to init root_item->flags and root_item->byte_limit
 524 * for subvolumes. To work around this problem, we steal a bit from
 525 * root_item->inode_item->flags, and use it to indicate if those fields
 526 * have been properly initialized.
 527 */
 528void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
 529{
 530        u64 inode_flags = le64_to_cpu(root_item->inode.flags);
 531
 532        if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
 533                inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
 534                root_item->inode.flags = cpu_to_le64(inode_flags);
 535                root_item->flags = 0;
 536                root_item->byte_limit = 0;
 537        }
 538}
 539
 540void btrfs_update_root_times(struct btrfs_trans_handle *trans,
 541                             struct btrfs_root *root)
 542{
 543        struct btrfs_root_item *item = &root->root_item;
 544        struct timespec ct = CURRENT_TIME;
 545
 546        spin_lock(&root->root_times_lock);
 547        item->ctransid = cpu_to_le64(trans->transid);
 548        item->ctime.sec = cpu_to_le64(ct.tv_sec);
 549        item->ctime.nsec = cpu_to_le32(ct.tv_nsec);
 550        spin_unlock(&root->root_times_lock);
 551}
 552
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.