aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/check-integrity.c7
-rw-r--r--fs/btrfs/ctree.h47
-rw-r--r--fs/btrfs/disk-io.c8
-rw-r--r--fs/btrfs/inode.c4
-rw-r--r--fs/btrfs/ioctl.c100
-rw-r--r--fs/btrfs/ioctl.h17
-rw-r--r--fs/btrfs/root-tree.c107
-rw-r--r--fs/btrfs/transaction.c17
8 files changed, 292 insertions, 15 deletions
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index da6e9364a5e..9197e2e3340 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -1032,6 +1032,7 @@ continue_with_current_leaf_stack_frame:
1032 struct btrfs_disk_key *disk_key; 1032 struct btrfs_disk_key *disk_key;
1033 u8 type; 1033 u8 type;
1034 u32 item_offset; 1034 u32 item_offset;
1035 u32 item_size;
1035 1036
1036 if (disk_item_offset + sizeof(struct btrfs_item) > 1037 if (disk_item_offset + sizeof(struct btrfs_item) >
1037 sf->block_ctx->len) { 1038 sf->block_ctx->len) {
@@ -1047,6 +1048,7 @@ leaf_item_out_of_bounce_error:
1047 disk_item_offset, 1048 disk_item_offset,
1048 sizeof(struct btrfs_item)); 1049 sizeof(struct btrfs_item));
1049 item_offset = le32_to_cpu(disk_item.offset); 1050 item_offset = le32_to_cpu(disk_item.offset);
1051 item_size = le32_to_cpu(disk_item.size);
1050 disk_key = &disk_item.key; 1052 disk_key = &disk_item.key;
1051 type = disk_key->type; 1053 type = disk_key->type;
1052 1054
@@ -1057,14 +1059,13 @@ leaf_item_out_of_bounce_error:
1057 1059
1058 root_item_offset = item_offset + 1060 root_item_offset = item_offset +
1059 offsetof(struct btrfs_leaf, items); 1061 offsetof(struct btrfs_leaf, items);
1060 if (root_item_offset + 1062 if (root_item_offset + item_size >
1061 sizeof(struct btrfs_root_item) >
1062 sf->block_ctx->len) 1063 sf->block_ctx->len)
1063 goto leaf_item_out_of_bounce_error; 1064 goto leaf_item_out_of_bounce_error;
1064 btrfsic_read_from_block_data( 1065 btrfsic_read_from_block_data(
1065 sf->block_ctx, &root_item, 1066 sf->block_ctx, &root_item,
1066 root_item_offset, 1067 root_item_offset,
1067 sizeof(struct btrfs_root_item)); 1068 item_size);
1068 next_bytenr = le64_to_cpu(root_item.bytenr); 1069 next_bytenr = le64_to_cpu(root_item.bytenr);
1069 1070
1070 sf->error = 1071 sf->error =
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 8cfde9326dd..d5f6d745867 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -709,6 +709,36 @@ struct btrfs_root_item {
709 struct btrfs_disk_key drop_progress; 709 struct btrfs_disk_key drop_progress;
710 u8 drop_level; 710 u8 drop_level;
711 u8 level; 711 u8 level;
712
713 /*
714 * The following fields appear after subvol_uuids+subvol_times
715 * were introduced.
716 */
717
718 /*
719 * This generation number is used to test if the new fields are valid
720 * and up to date while reading the root item. Everytime the root item
721 * is written out, the "generation" field is copied into this field. If
722 * anyone ever mounted the fs with an older kernel, we will have
723 * mismatching generation values here and thus must invalidate the
724 * new fields. See btrfs_update_root and btrfs_find_last_root for
725 * details.
726 * the offset of generation_v2 is also used as the start for the memset
727 * when invalidating the fields.
728 */
729 __le64 generation_v2;
730 u8 uuid[BTRFS_UUID_SIZE];
731 u8 parent_uuid[BTRFS_UUID_SIZE];
732 u8 received_uuid[BTRFS_UUID_SIZE];
733 __le64 ctransid; /* updated when an inode changes */
734 __le64 otransid; /* trans when created */
735 __le64 stransid; /* trans when sent. non-zero for received subvol */
736 __le64 rtransid; /* trans when received. non-zero for received subvol */
737 struct btrfs_timespec ctime;
738 struct btrfs_timespec otime;
739 struct btrfs_timespec stime;
740 struct btrfs_timespec rtime;
741 __le64 reserved[8]; /* for future */
712} __attribute__ ((__packed__)); 742} __attribute__ ((__packed__));
713 743
714/* 744/*
@@ -1416,6 +1446,8 @@ struct btrfs_root {
1416 dev_t anon_dev; 1446 dev_t anon_dev;
1417 1447
1418 int force_cow; 1448 int force_cow;
1449
1450 spinlock_t root_times_lock;
1419}; 1451};
1420 1452
1421struct btrfs_ioctl_defrag_range_args { 1453struct btrfs_ioctl_defrag_range_args {
@@ -2189,6 +2221,16 @@ BTRFS_SETGET_STACK_FUNCS(root_used, struct btrfs_root_item, bytes_used, 64);
2189BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64); 2221BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64);
2190BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item, 2222BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
2191 last_snapshot, 64); 2223 last_snapshot, 64);
2224BTRFS_SETGET_STACK_FUNCS(root_generation_v2, struct btrfs_root_item,
2225 generation_v2, 64);
2226BTRFS_SETGET_STACK_FUNCS(root_ctransid, struct btrfs_root_item,
2227 ctransid, 64);
2228BTRFS_SETGET_STACK_FUNCS(root_otransid, struct btrfs_root_item,
2229 otransid, 64);
2230BTRFS_SETGET_STACK_FUNCS(root_stransid, struct btrfs_root_item,
2231 stransid, 64);
2232BTRFS_SETGET_STACK_FUNCS(root_rtransid, struct btrfs_root_item,
2233 rtransid, 64);
2192 2234
2193static inline bool btrfs_root_readonly(struct btrfs_root *root) 2235static inline bool btrfs_root_readonly(struct btrfs_root *root)
2194{ 2236{
@@ -2822,6 +2864,9 @@ int __must_check btrfs_update_root(struct btrfs_trans_handle *trans,
2822 struct btrfs_root *root, 2864 struct btrfs_root *root,
2823 struct btrfs_key *key, 2865 struct btrfs_key *key,
2824 struct btrfs_root_item *item); 2866 struct btrfs_root_item *item);
2867void btrfs_read_root_item(struct btrfs_root *root,
2868 struct extent_buffer *eb, int slot,
2869 struct btrfs_root_item *item);
2825int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct 2870int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
2826 btrfs_root_item *item, struct btrfs_key *key); 2871 btrfs_root_item *item, struct btrfs_key *key);
2827int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); 2872int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid);
@@ -2829,6 +2874,8 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
2829void btrfs_set_root_node(struct btrfs_root_item *item, 2874void btrfs_set_root_node(struct btrfs_root_item *item,
2830 struct extent_buffer *node); 2875 struct extent_buffer *node);
2831void btrfs_check_and_init_root_item(struct btrfs_root_item *item); 2876void btrfs_check_and_init_root_item(struct btrfs_root_item *item);
2877void btrfs_update_root_times(struct btrfs_trans_handle *trans,
2878 struct btrfs_root *root);
2832 2879
2833/* dir-item.c */ 2880/* dir-item.c */
2834int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, 2881int btrfs_insert_dir_item(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 2936ca49b3b..c39eb71fae3 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1182,6 +1182,8 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
1182 root->defrag_running = 0; 1182 root->defrag_running = 0;
1183 root->root_key.objectid = objectid; 1183 root->root_key.objectid = objectid;
1184 root->anon_dev = 0; 1184 root->anon_dev = 0;
1185
1186 spin_lock_init(&root->root_times_lock);
1185} 1187}
1186 1188
1187static int __must_check find_and_setup_root(struct btrfs_root *tree_root, 1189static int __must_check find_and_setup_root(struct btrfs_root *tree_root,
@@ -1326,6 +1328,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
1326 u64 generation; 1328 u64 generation;
1327 u32 blocksize; 1329 u32 blocksize;
1328 int ret = 0; 1330 int ret = 0;
1331 int slot;
1329 1332
1330 root = btrfs_alloc_root(fs_info); 1333 root = btrfs_alloc_root(fs_info);
1331 if (!root) 1334 if (!root)
@@ -1352,9 +1355,8 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
1352 ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); 1355 ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0);
1353 if (ret == 0) { 1356 if (ret == 0) {
1354 l = path->nodes[0]; 1357 l = path->nodes[0];
1355 read_extent_buffer(l, &root->root_item, 1358 slot = path->slots[0];
1356 btrfs_item_ptr_offset(l, path->slots[0]), 1359 btrfs_read_root_item(tree_root, l, slot, &root->root_item);
1357 sizeof(root->root_item));
1358 memcpy(&root->root_key, location, sizeof(*location)); 1360 memcpy(&root->root_key, location, sizeof(*location));
1359 } 1361 }
1360 btrfs_free_path(path); 1362 btrfs_free_path(path);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a7d1921ac76..4ffc8738954 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2734,6 +2734,8 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
2734 */ 2734 */
2735 if (!btrfs_is_free_space_inode(root, inode) 2735 if (!btrfs_is_free_space_inode(root, inode)
2736 && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { 2736 && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
2737 btrfs_update_root_times(trans, root);
2738
2737 ret = btrfs_delayed_update_inode(trans, root, inode); 2739 ret = btrfs_delayed_update_inode(trans, root, inode);
2738 if (!ret) 2740 if (!ret)
2739 btrfs_set_inode_last_trans(trans, inode); 2741 btrfs_set_inode_last_trans(trans, inode);
@@ -4723,6 +4725,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
4723 trace_btrfs_inode_new(inode); 4725 trace_btrfs_inode_new(inode);
4724 btrfs_set_inode_last_trans(trans, inode); 4726 btrfs_set_inode_last_trans(trans, inode);
4725 4727
4728 btrfs_update_root_times(trans, root);
4729
4726 return inode; 4730 return inode;
4727fail: 4731fail:
4728 if (dir) 4732 if (dir)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 7011871c45b..99fe2ce7f72 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -41,6 +41,7 @@
41#include <linux/vmalloc.h> 41#include <linux/vmalloc.h>
42#include <linux/slab.h> 42#include <linux/slab.h>
43#include <linux/blkdev.h> 43#include <linux/blkdev.h>
44#include <linux/uuid.h>
44#include "compat.h" 45#include "compat.h"
45#include "ctree.h" 46#include "ctree.h"
46#include "disk-io.h" 47#include "disk-io.h"
@@ -346,11 +347,13 @@ static noinline int create_subvol(struct btrfs_root *root,
346 struct btrfs_root *new_root; 347 struct btrfs_root *new_root;
347 struct dentry *parent = dentry->d_parent; 348 struct dentry *parent = dentry->d_parent;
348 struct inode *dir; 349 struct inode *dir;
350 struct timespec cur_time = CURRENT_TIME;
349 int ret; 351 int ret;
350 int err; 352 int err;
351 u64 objectid; 353 u64 objectid;
352 u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; 354 u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
353 u64 index = 0; 355 u64 index = 0;
356 uuid_le new_uuid;
354 357
355 ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); 358 ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
356 if (ret) 359 if (ret)
@@ -389,8 +392,9 @@ static noinline int create_subvol(struct btrfs_root *root,
389 BTRFS_UUID_SIZE); 392 BTRFS_UUID_SIZE);
390 btrfs_mark_buffer_dirty(leaf); 393 btrfs_mark_buffer_dirty(leaf);
391 394
395 memset(&root_item, 0, sizeof(root_item));
396
392 inode_item = &root_item.inode; 397 inode_item = &root_item.inode;
393 memset(inode_item, 0, sizeof(*inode_item));
394 inode_item->generation = cpu_to_le64(1); 398 inode_item->generation = cpu_to_le64(1);
395 inode_item->size = cpu_to_le64(3); 399 inode_item->size = cpu_to_le64(3);
396 inode_item->nlink = cpu_to_le32(1); 400 inode_item->nlink = cpu_to_le32(1);
@@ -408,8 +412,15 @@ static noinline int create_subvol(struct btrfs_root *root,
408 btrfs_set_root_used(&root_item, leaf->len); 412 btrfs_set_root_used(&root_item, leaf->len);
409 btrfs_set_root_last_snapshot(&root_item, 0); 413 btrfs_set_root_last_snapshot(&root_item, 0);
410 414
411 memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); 415 btrfs_set_root_generation_v2(&root_item,
412 root_item.drop_level = 0; 416 btrfs_root_generation(&root_item));
417 uuid_le_gen(&new_uuid);
418 memcpy(root_item.uuid, new_uuid.b, BTRFS_UUID_SIZE);
419 root_item.otime.sec = cpu_to_le64(cur_time.tv_sec);
420 root_item.otime.nsec = cpu_to_le64(cur_time.tv_nsec);
421 root_item.ctime = root_item.otime;
422 btrfs_set_root_ctransid(&root_item, trans->transid);
423 btrfs_set_root_otransid(&root_item, trans->transid);
413 424
414 btrfs_tree_unlock(leaf); 425 btrfs_tree_unlock(leaf);
415 free_extent_buffer(leaf); 426 free_extent_buffer(leaf);
@@ -3395,6 +3406,87 @@ out:
3395 return ret; 3406 return ret;
3396} 3407}
3397 3408
3409static long btrfs_ioctl_set_received_subvol(struct file *file,
3410 void __user *arg)
3411{
3412 struct btrfs_ioctl_received_subvol_args *sa = NULL;
3413 struct inode *inode = fdentry(file)->d_inode;
3414 struct btrfs_root *root = BTRFS_I(inode)->root;
3415 struct btrfs_root_item *root_item = &root->root_item;
3416 struct btrfs_trans_handle *trans;
3417 struct timespec ct = CURRENT_TIME;
3418 int ret = 0;
3419
3420 ret = mnt_want_write_file(file);
3421 if (ret < 0)
3422 return ret;
3423
3424 down_write(&root->fs_info->subvol_sem);
3425
3426 if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
3427 ret = -EINVAL;
3428 goto out;
3429 }
3430
3431 if (btrfs_root_readonly(root)) {
3432 ret = -EROFS;
3433 goto out;
3434 }
3435
3436 if (!inode_owner_or_capable(inode)) {
3437 ret = -EACCES;
3438 goto out;
3439 }
3440
3441 sa = memdup_user(arg, sizeof(*sa));
3442 if (IS_ERR(sa)) {
3443 ret = PTR_ERR(sa);
3444 sa = NULL;
3445 goto out;
3446 }
3447
3448 trans = btrfs_start_transaction(root, 1);
3449 if (IS_ERR(trans)) {
3450 ret = PTR_ERR(trans);
3451 trans = NULL;
3452 goto out;
3453 }
3454
3455 sa->rtransid = trans->transid;
3456 sa->rtime.sec = ct.tv_sec;
3457 sa->rtime.nsec = ct.tv_nsec;
3458
3459 memcpy(root_item->received_uuid, sa->uuid, BTRFS_UUID_SIZE);
3460 btrfs_set_root_stransid(root_item, sa->stransid);
3461 btrfs_set_root_rtransid(root_item, sa->rtransid);
3462 root_item->stime.sec = cpu_to_le64(sa->stime.sec);
3463 root_item->stime.nsec = cpu_to_le32(sa->stime.nsec);
3464 root_item->rtime.sec = cpu_to_le64(sa->rtime.sec);
3465 root_item->rtime.nsec = cpu_to_le32(sa->rtime.nsec);
3466
3467 ret = btrfs_update_root(trans, root->fs_info->tree_root,
3468 &root->root_key, &root->root_item);
3469 if (ret < 0) {
3470 btrfs_end_transaction(trans, root);
3471 trans = NULL;
3472 goto out;
3473 } else {
3474 ret = btrfs_commit_transaction(trans, root);
3475 if (ret < 0)
3476 goto out;
3477 }
3478
3479 ret = copy_to_user(arg, sa, sizeof(*sa));
3480 if (ret)
3481 ret = -EFAULT;
3482
3483out:
3484 kfree(sa);
3485 up_write(&root->fs_info->subvol_sem);
3486 mnt_drop_write_file(file);
3487 return ret;
3488}
3489
3398long btrfs_ioctl(struct file *file, unsigned int 3490long btrfs_ioctl(struct file *file, unsigned int
3399 cmd, unsigned long arg) 3491 cmd, unsigned long arg)
3400{ 3492{
@@ -3477,6 +3569,8 @@ long btrfs_ioctl(struct file *file, unsigned int
3477 return btrfs_ioctl_balance_ctl(root, arg); 3569 return btrfs_ioctl_balance_ctl(root, arg);
3478 case BTRFS_IOC_BALANCE_PROGRESS: 3570 case BTRFS_IOC_BALANCE_PROGRESS:
3479 return btrfs_ioctl_balance_progress(root, argp); 3571 return btrfs_ioctl_balance_progress(root, argp);
3572 case BTRFS_IOC_SET_RECEIVED_SUBVOL:
3573 return btrfs_ioctl_set_received_subvol(file, argp);
3480 case BTRFS_IOC_GET_DEV_STATS: 3574 case BTRFS_IOC_GET_DEV_STATS:
3481 return btrfs_ioctl_get_dev_stats(root, argp, 0); 3575 return btrfs_ioctl_get_dev_stats(root, argp, 0);
3482 case BTRFS_IOC_GET_AND_RESET_DEV_STATS: 3576 case BTRFS_IOC_GET_AND_RESET_DEV_STATS:
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index e440aa653c3..0c505d7ff8e 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -295,6 +295,21 @@ struct btrfs_ioctl_get_dev_stats {
295 __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */ 295 __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
296}; 296};
297 297
298struct btrfs_ioctl_timespec {
299 __u64 sec;
300 __u32 nsec;
301};
302
303struct btrfs_ioctl_received_subvol_args {
304 char uuid[BTRFS_UUID_SIZE]; /* in */
305 __u64 stransid; /* in */
306 __u64 rtransid; /* out */
307 struct btrfs_ioctl_timespec stime; /* in */
308 struct btrfs_ioctl_timespec rtime; /* out */
309 __u64 flags; /* in */
310 __u64 reserved[16]; /* in */
311};
312
298#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ 313#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
299 struct btrfs_ioctl_vol_args) 314 struct btrfs_ioctl_vol_args)
300#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ 315#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -359,6 +374,8 @@ struct btrfs_ioctl_get_dev_stats {
359 struct btrfs_ioctl_ino_path_args) 374 struct btrfs_ioctl_ino_path_args)
360#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ 375#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
361 struct btrfs_ioctl_ino_path_args) 376 struct btrfs_ioctl_ino_path_args)
377#define BTRFS_IOC_SET_RECEIVED_SUBVOL _IOWR(BTRFS_IOCTL_MAGIC, 37, \
378 struct btrfs_ioctl_received_subvol_args)
362#define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \ 379#define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
363 struct btrfs_ioctl_get_dev_stats) 380 struct btrfs_ioctl_get_dev_stats)
364#define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \ 381#define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 24fb8ce4e07..6bb465cca20 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -16,12 +16,55 @@
16 * Boston, MA 021110-1307, USA. 16 * Boston, MA 021110-1307, USA.
17 */ 17 */
18 18
19#include <linux/uuid.h>
19#include "ctree.h" 20#include "ctree.h"
20#include "transaction.h" 21#include "transaction.h"
21#include "disk-io.h" 22#include "disk-io.h"
22#include "print-tree.h" 23#include "print-tree.h"
23 24
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/*
25 * lookup the root with the highest offset for a given objectid. The key we do 68 * lookup the root with the highest offset for a given objectid. The key we do
26 * find is copied into 'key'. If we find something return 0, otherwise 1, < 0 69 * find is copied into 'key'. If we find something return 0, otherwise 1, < 0
27 * on error. 70 * on error.
@@ -61,10 +104,10 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
61 goto out; 104 goto out;
62 } 105 }
63 if (item) 106 if (item)
64 read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), 107 btrfs_read_root_item(root, l, slot, item);
65 sizeof(*item));
66 if (key) 108 if (key)
67 memcpy(key, &found_key, sizeof(found_key)); 109 memcpy(key, &found_key, sizeof(found_key));
110
68 ret = 0; 111 ret = 0;
69out: 112out:
70 btrfs_free_path(path); 113 btrfs_free_path(path);
@@ -91,16 +134,15 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
91 int ret; 134 int ret;
92 int slot; 135 int slot;
93 unsigned long ptr; 136 unsigned long ptr;
137 int old_len;
94 138
95 path = btrfs_alloc_path(); 139 path = btrfs_alloc_path();
96 if (!path) 140 if (!path)
97 return -ENOMEM; 141 return -ENOMEM;
98 142
99 ret = btrfs_search_slot(trans, root, key, path, 0, 1); 143 ret = btrfs_search_slot(trans, root, key, path, 0, 1);
100 if (ret < 0) { 144 if (ret < 0)
101 btrfs_abort_transaction(trans, root, ret); 145 goto out_abort;
102 goto out;
103 }
104 146
105 if (ret != 0) { 147 if (ret != 0) {
106 btrfs_print_leaf(root, path->nodes[0]); 148 btrfs_print_leaf(root, path->nodes[0]);
@@ -113,16 +155,56 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
113 l = path->nodes[0]; 155 l = path->nodes[0];
114 slot = path->slots[0]; 156 slot = path->slots[0];
115 ptr = btrfs_item_ptr_offset(l, slot); 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
116 write_extent_buffer(l, item, ptr, sizeof(*item)); 190 write_extent_buffer(l, item, ptr, sizeof(*item));
117 btrfs_mark_buffer_dirty(path->nodes[0]); 191 btrfs_mark_buffer_dirty(path->nodes[0]);
118out: 192out:
119 btrfs_free_path(path); 193 btrfs_free_path(path);
120 return ret; 194 return ret;
195
196out_abort:
197 btrfs_abort_transaction(trans, root, ret);
198 goto out;
121} 199}
122 200
123int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 201int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
124 struct btrfs_key *key, struct btrfs_root_item *item) 202 struct btrfs_key *key, struct btrfs_root_item *item)
125{ 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));
126 return btrfs_insert_item(trans, root, key, item, sizeof(*item)); 208 return btrfs_insert_item(trans, root, key, item, sizeof(*item));
127} 209}
128 210
@@ -454,3 +536,16 @@ void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
454 root_item->byte_limit = 0; 536 root_item->byte_limit = 0;
455 } 537 }
456} 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 = trans->transid;
548 item->ctime.sec = cpu_to_le64(ct.tv_sec);
549 item->ctime.nsec = cpu_to_le64(ct.tv_nsec);
550 spin_unlock(&root->root_times_lock);
551}
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index b72b068183e..a21f3085a33 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -22,6 +22,7 @@
22#include <linux/writeback.h> 22#include <linux/writeback.h>
23#include <linux/pagemap.h> 23#include <linux/pagemap.h>
24#include <linux/blkdev.h> 24#include <linux/blkdev.h>
25#include <linux/uuid.h>
25#include "ctree.h" 26#include "ctree.h"
26#include "disk-io.h" 27#include "disk-io.h"
27#include "transaction.h" 28#include "transaction.h"
@@ -926,11 +927,13 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
926 struct dentry *dentry; 927 struct dentry *dentry;
927 struct extent_buffer *tmp; 928 struct extent_buffer *tmp;
928 struct extent_buffer *old; 929 struct extent_buffer *old;
930 struct timespec cur_time = CURRENT_TIME;
929 int ret; 931 int ret;
930 u64 to_reserve = 0; 932 u64 to_reserve = 0;
931 u64 index = 0; 933 u64 index = 0;
932 u64 objectid; 934 u64 objectid;
933 u64 root_flags; 935 u64 root_flags;
936 uuid_le new_uuid;
934 937
935 rsv = trans->block_rsv; 938 rsv = trans->block_rsv;
936 939
@@ -1016,6 +1019,20 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
1016 root_flags &= ~BTRFS_ROOT_SUBVOL_RDONLY; 1019 root_flags &= ~BTRFS_ROOT_SUBVOL_RDONLY;
1017 btrfs_set_root_flags(new_root_item, root_flags); 1020 btrfs_set_root_flags(new_root_item, root_flags);
1018 1021
1022 btrfs_set_root_generation_v2(new_root_item,
1023 trans->transid);
1024 uuid_le_gen(&new_uuid);
1025 memcpy(new_root_item->uuid, new_uuid.b, BTRFS_UUID_SIZE);
1026 memcpy(new_root_item->parent_uuid, root->root_item.uuid,
1027 BTRFS_UUID_SIZE);
1028 new_root_item->otime.sec = cpu_to_le64(cur_time.tv_sec);
1029 new_root_item->otime.nsec = cpu_to_le64(cur_time.tv_nsec);
1030 btrfs_set_root_otransid(new_root_item, trans->transid);
1031 memset(&new_root_item->stime, 0, sizeof(new_root_item->stime));
1032 memset(&new_root_item->rtime, 0, sizeof(new_root_item->rtime));
1033 btrfs_set_root_stransid(new_root_item, 0);
1034 btrfs_set_root_rtransid(new_root_item, 0);
1035
1019 old = btrfs_lock_root_node(root); 1036 old = btrfs_lock_root_node(root);
1020 ret = btrfs_cow_block(trans, root, old, NULL, 0, &old); 1037 ret = btrfs_cow_block(trans, root, old, NULL, 0, &old);
1021 if (ret) { 1038 if (ret) {