aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAlexander Block <ablock84@googlemail.com>2012-07-25 11:35:53 -0400
committerAlexander Block <ablock84@googlemail.com>2012-07-25 17:28:38 -0400
commit8ea05e3a4262b9e6871c349fa3486bcfc72ffd1a (patch)
tree893a8ff635b31caf920aaa97948e612640cbac6a /fs
parent91cb916ca26feb99c78c131a1643af3d10fefd96 (diff)
Btrfs: introduce subvol uuids and times
This patch introduces uuids for subvolumes. Each subvolume has it's own uuid. In case it was snapshotted, it also contains parent_uuid. In case it was received, it also contains received_uuid. It also introduces subvolume ctime/otime/stime/rtime. The first two are comparable to the times found in inodes. otime is the origin/creation time and ctime is the change time. stime/rtime are only valid on received subvolumes. stime is the time of the subvolume when it was sent. rtime is the time of the subvolume when it was received. Additionally to the times, we have a transid for each time. They are updated at the same place as the times. btrfs receive uses stransid and rtransid to find out if a received subvolume changed in the meantime. If an older kernel mounts a filesystem with the extented fields, all fields become invalid. The next mount with a new kernel will detect this and reset the fields. Signed-off-by: Alexander Block <ablock84@googlemail.com> Reviewed-by: David Sterba <dave@jikos.cz> Reviewed-by: Arne Jansen <sensille@gmx.net> Reviewed-by: Jan Schmidt <list.btrfs@jan-o-sch.net> Reviewed-by: Alex Lyakas <alex.bolshoy.btrfs@gmail.com>
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) {