Btrfs: Fix uninitialized root flags for subvolumes

root_item->flags and root_item->byte_limit are not initialized when
a subvolume is created. This bug is not revealed until we added
readonly snapshot support - now you mount a btrfs filesystem and you
may find the subvolumes in it are readonly.

To work around this problem, we steal a bit from root_item->inode_item->flags,
and use it to indicate if those fields have been properly initialized.
When we read a tree root from disk, we check if the bit is set, and if
not we'll set the flag and initialize the two fields of the root item.

Reported-by: Andreas Philipp <philipp.andreas@gmail.com>
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Tested-by: Andreas Philipp <philipp.andreas@gmail.com>
cc: stable@kernel.org
Signed-off-by: Chris Mason <chris.mason@oracle.com>

authored by Li Zefan and committed by Chris Mason 08fe4db1 adae52b9

+30 -1
+4
fs/btrfs/ctree.h
··· 1284 1284 #define BTRFS_INODE_DIRSYNC (1 << 10) 1285 1285 #define BTRFS_INODE_COMPRESS (1 << 11) 1286 1286 1287 + #define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31) 1288 + 1287 1289 /* some macros to generate set/get funcs for the struct fields. This 1288 1290 * assumes there is a lefoo_to_cpu for every type, so lets make a simple 1289 1291 * one for u8: ··· 2361 2359 int btrfs_find_orphan_roots(struct btrfs_root *tree_root); 2362 2360 int btrfs_set_root_node(struct btrfs_root_item *item, 2363 2361 struct extent_buffer *node); 2362 + void btrfs_check_and_init_root_item(struct btrfs_root_item *item); 2363 + 2364 2364 /* dir-item.c */ 2365 2365 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, 2366 2366 struct btrfs_root *root, const char *name,
+3 -1
fs/btrfs/disk-io.c
··· 1276 1276 root->commit_root = btrfs_root_node(root); 1277 1277 BUG_ON(!root->node); 1278 1278 out: 1279 - if (location->objectid != BTRFS_TREE_LOG_OBJECTID) 1279 + if (location->objectid != BTRFS_TREE_LOG_OBJECTID) { 1280 1280 root->ref_cows = 1; 1281 + btrfs_check_and_init_root_item(&root->root_item); 1282 + } 1281 1283 1282 1284 return root; 1283 1285 }
+4
fs/btrfs/ioctl.c
··· 373 373 inode_item->nbytes = cpu_to_le64(root->leafsize); 374 374 inode_item->mode = cpu_to_le32(S_IFDIR | 0755); 375 375 376 + root_item.flags = 0; 377 + root_item.byte_limit = 0; 378 + inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT); 379 + 376 380 btrfs_set_root_bytenr(&root_item, leaf->start); 377 381 btrfs_set_root_generation(&root_item, trans->transid); 378 382 btrfs_set_root_level(&root_item, 0);
+18
fs/btrfs/root-tree.c
··· 473 473 btrfs_free_path(path); 474 474 return 0; 475 475 } 476 + 477 + /* 478 + * Old btrfs forgets to init root_item->flags and root_item->byte_limit 479 + * for subvolumes. To work around this problem, we steal a bit from 480 + * root_item->inode_item->flags, and use it to indicate if those fields 481 + * have been properly initialized. 482 + */ 483 + void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item) 484 + { 485 + u64 inode_flags = le64_to_cpu(root_item->inode.flags); 486 + 487 + if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) { 488 + inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT; 489 + root_item->inode.flags = cpu_to_le64(inode_flags); 490 + root_item->flags = 0; 491 + root_item->byte_limit = 0; 492 + } 493 + }
+1
fs/btrfs/transaction.c
··· 976 976 record_root_in_trans(trans, root); 977 977 btrfs_set_root_last_snapshot(&root->root_item, trans->transid); 978 978 memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); 979 + btrfs_check_and_init_root_item(new_root_item); 979 980 980 981 root_flags = btrfs_root_flags(new_root_item); 981 982 if (pending->readonly)