diff options
author | Chris Mason <chris.mason@oracle.com> | 2009-01-28 20:29:43 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-01-28 20:29:43 -0500 |
commit | e4f722fa42537bcb0ff14322a57dc3870d093cab (patch) | |
tree | 315920ade3b68bf20c4080bcd1bf2bc34a5d5ab7 | |
parent | 18e352e4a73465349711a9324767e1b2453383e2 (diff) | |
parent | a717531942f488209dded30f6bc648167bcefa72 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
Fix fs/btrfs/super.c conflict around #includes
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | fs/btrfs/async-thread.c | 1 | ||||
-rw-r--r-- | fs/btrfs/compression.c | 1 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 21 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 23 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 104 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 41 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 93 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 5 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 25 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 1 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.c | 4 | ||||
-rw-r--r-- | fs/btrfs/super.c | 6 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 4 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 350 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 38 | ||||
-rw-r--r-- | fs/btrfs/xattr.c | 14 |
20 files changed, 426 insertions, 318 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d992d407197b..8a7b0b36e8b4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1021,6 +1021,14 @@ M: mb@bu3sch.de | |||
1021 | W: http://bu3sch.de/btgpio.php | 1021 | W: http://bu3sch.de/btgpio.php |
1022 | S: Maintained | 1022 | S: Maintained |
1023 | 1023 | ||
1024 | BTRFS FILE SYSTEM | ||
1025 | P: Chris Mason | ||
1026 | M: chris.mason@oracle.com | ||
1027 | L: linux-btrfs@vger.kernel.org | ||
1028 | W: http://btrfs.wiki.kernel.org/ | ||
1029 | T: git kernel.org:/pub/scm/linux/kernel/git/mason/btrfs-unstable.git | ||
1030 | S: Maintained | ||
1031 | |||
1024 | BTTV VIDEO4LINUX DRIVER | 1032 | BTTV VIDEO4LINUX DRIVER |
1025 | P: Mauro Carvalho Chehab | 1033 | P: Mauro Carvalho Chehab |
1026 | M: mchehab@infradead.org | 1034 | M: mchehab@infradead.org |
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 8e2fec05dbe0..d5f4e94f2ca2 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/version.h> | ||
20 | #include <linux/kthread.h> | 19 | #include <linux/kthread.h> |
21 | #include <linux/list.h> | 20 | #include <linux/list.h> |
22 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index ee848d8585d9..ab07627084f1 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/swap.h> | 32 | #include <linux/swap.h> |
33 | #include <linux/writeback.h> | 33 | #include <linux/writeback.h> |
34 | #include <linux/bit_spinlock.h> | 34 | #include <linux/bit_spinlock.h> |
35 | #include <linux/version.h> | ||
36 | #include <linux/pagevec.h> | 35 | #include <linux/pagevec.h> |
37 | #include "compat.h" | 36 | #include "compat.h" |
38 | #include "ctree.h" | 37 | #include "ctree.h" |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 9e46c0776816..2603ee539b7a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1210,8 +1210,7 @@ static noinline void reada_for_search(struct btrfs_root *root, | |||
1210 | struct btrfs_disk_key disk_key; | 1210 | struct btrfs_disk_key disk_key; |
1211 | u32 nritems; | 1211 | u32 nritems; |
1212 | u64 search; | 1212 | u64 search; |
1213 | u64 lowest_read; | 1213 | u64 target; |
1214 | u64 highest_read; | ||
1215 | u64 nread = 0; | 1214 | u64 nread = 0; |
1216 | int direction = path->reada; | 1215 | int direction = path->reada; |
1217 | struct extent_buffer *eb; | 1216 | struct extent_buffer *eb; |
@@ -1235,8 +1234,7 @@ static noinline void reada_for_search(struct btrfs_root *root, | |||
1235 | return; | 1234 | return; |
1236 | } | 1235 | } |
1237 | 1236 | ||
1238 | highest_read = search; | 1237 | target = search; |
1239 | lowest_read = search; | ||
1240 | 1238 | ||
1241 | nritems = btrfs_header_nritems(node); | 1239 | nritems = btrfs_header_nritems(node); |
1242 | nr = slot; | 1240 | nr = slot; |
@@ -1256,24 +1254,15 @@ static noinline void reada_for_search(struct btrfs_root *root, | |||
1256 | break; | 1254 | break; |
1257 | } | 1255 | } |
1258 | search = btrfs_node_blockptr(node, nr); | 1256 | search = btrfs_node_blockptr(node, nr); |
1259 | if ((search >= lowest_read && search <= highest_read) || | 1257 | if ((search <= target && target - search <= 65536) || |
1260 | (search < lowest_read && lowest_read - search <= 16384) || | 1258 | (search > target && search - target <= 65536)) { |
1261 | (search > highest_read && search - highest_read <= 16384)) { | ||
1262 | readahead_tree_block(root, search, blocksize, | 1259 | readahead_tree_block(root, search, blocksize, |
1263 | btrfs_node_ptr_generation(node, nr)); | 1260 | btrfs_node_ptr_generation(node, nr)); |
1264 | nread += blocksize; | 1261 | nread += blocksize; |
1265 | } | 1262 | } |
1266 | nscan++; | 1263 | nscan++; |
1267 | if (path->reada < 2 && (nread > (64 * 1024) || nscan > 32)) | 1264 | if ((nread > 65536 || nscan > 32)) |
1268 | break; | 1265 | break; |
1269 | |||
1270 | if (nread > (256 * 1024) || nscan > 128) | ||
1271 | break; | ||
1272 | |||
1273 | if (search < lowest_read) | ||
1274 | lowest_read = search; | ||
1275 | if (search > highest_read) | ||
1276 | highest_read = search; | ||
1277 | } | 1266 | } |
1278 | } | 1267 | } |
1279 | 1268 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index eee060f88113..de103a8a815e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -454,17 +454,11 @@ struct btrfs_timespec { | |||
454 | __le32 nsec; | 454 | __le32 nsec; |
455 | } __attribute__ ((__packed__)); | 455 | } __attribute__ ((__packed__)); |
456 | 456 | ||
457 | typedef enum { | 457 | enum btrfs_compression_type { |
458 | BTRFS_COMPRESS_NONE = 0, | 458 | BTRFS_COMPRESS_NONE = 0, |
459 | BTRFS_COMPRESS_ZLIB = 1, | 459 | BTRFS_COMPRESS_ZLIB = 1, |
460 | BTRFS_COMPRESS_LAST = 2, | 460 | BTRFS_COMPRESS_LAST = 2, |
461 | } btrfs_compression_type; | 461 | }; |
462 | |||
463 | /* we don't understand any encryption methods right now */ | ||
464 | typedef enum { | ||
465 | BTRFS_ENCRYPTION_NONE = 0, | ||
466 | BTRFS_ENCRYPTION_LAST = 1, | ||
467 | } btrfs_encryption_type; | ||
468 | 462 | ||
469 | struct btrfs_inode_item { | 463 | struct btrfs_inode_item { |
470 | /* nfs style generation number */ | 464 | /* nfs style generation number */ |
@@ -701,9 +695,7 @@ struct btrfs_fs_info { | |||
701 | struct btrfs_transaction *running_transaction; | 695 | struct btrfs_transaction *running_transaction; |
702 | wait_queue_head_t transaction_throttle; | 696 | wait_queue_head_t transaction_throttle; |
703 | wait_queue_head_t transaction_wait; | 697 | wait_queue_head_t transaction_wait; |
704 | |||
705 | wait_queue_head_t async_submit_wait; | 698 | wait_queue_head_t async_submit_wait; |
706 | wait_queue_head_t tree_log_wait; | ||
707 | 699 | ||
708 | struct btrfs_super_block super_copy; | 700 | struct btrfs_super_block super_copy; |
709 | struct btrfs_super_block super_for_commit; | 701 | struct btrfs_super_block super_for_commit; |
@@ -730,10 +722,6 @@ struct btrfs_fs_info { | |||
730 | atomic_t async_submit_draining; | 722 | atomic_t async_submit_draining; |
731 | atomic_t nr_async_bios; | 723 | atomic_t nr_async_bios; |
732 | atomic_t async_delalloc_pages; | 724 | atomic_t async_delalloc_pages; |
733 | atomic_t tree_log_writers; | ||
734 | atomic_t tree_log_commit; | ||
735 | unsigned long tree_log_batch; | ||
736 | u64 tree_log_transid; | ||
737 | 725 | ||
738 | /* | 726 | /* |
739 | * this is used by the balancing code to wait for all the pending | 727 | * this is used by the balancing code to wait for all the pending |
@@ -833,7 +821,14 @@ struct btrfs_root { | |||
833 | struct kobject root_kobj; | 821 | struct kobject root_kobj; |
834 | struct completion kobj_unregister; | 822 | struct completion kobj_unregister; |
835 | struct mutex objectid_mutex; | 823 | struct mutex objectid_mutex; |
824 | |||
836 | struct mutex log_mutex; | 825 | struct mutex log_mutex; |
826 | wait_queue_head_t log_writer_wait; | ||
827 | wait_queue_head_t log_commit_wait[2]; | ||
828 | atomic_t log_writers; | ||
829 | atomic_t log_commit[2]; | ||
830 | unsigned long log_transid; | ||
831 | unsigned long log_batch; | ||
837 | 832 | ||
838 | u64 objectid; | 833 | u64 objectid; |
839 | u64 last_trans; | 834 | u64 last_trans; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 81a313874ae5..7feac5a475e9 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/version.h> | ||
20 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
21 | #include <linux/blkdev.h> | 20 | #include <linux/blkdev.h> |
22 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
@@ -850,6 +849,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
850 | spin_lock_init(&root->list_lock); | 849 | spin_lock_init(&root->list_lock); |
851 | mutex_init(&root->objectid_mutex); | 850 | mutex_init(&root->objectid_mutex); |
852 | mutex_init(&root->log_mutex); | 851 | mutex_init(&root->log_mutex); |
852 | init_waitqueue_head(&root->log_writer_wait); | ||
853 | init_waitqueue_head(&root->log_commit_wait[0]); | ||
854 | init_waitqueue_head(&root->log_commit_wait[1]); | ||
855 | atomic_set(&root->log_commit[0], 0); | ||
856 | atomic_set(&root->log_commit[1], 0); | ||
857 | atomic_set(&root->log_writers, 0); | ||
858 | root->log_batch = 0; | ||
859 | root->log_transid = 0; | ||
853 | extent_io_tree_init(&root->dirty_log_pages, | 860 | extent_io_tree_init(&root->dirty_log_pages, |
854 | fs_info->btree_inode->i_mapping, GFP_NOFS); | 861 | fs_info->btree_inode->i_mapping, GFP_NOFS); |
855 | 862 | ||
@@ -934,15 +941,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | |||
934 | return 0; | 941 | return 0; |
935 | } | 942 | } |
936 | 943 | ||
937 | int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | 944 | static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, |
938 | struct btrfs_fs_info *fs_info) | 945 | struct btrfs_fs_info *fs_info) |
939 | { | 946 | { |
940 | struct btrfs_root *root; | 947 | struct btrfs_root *root; |
941 | struct btrfs_root *tree_root = fs_info->tree_root; | 948 | struct btrfs_root *tree_root = fs_info->tree_root; |
949 | struct extent_buffer *leaf; | ||
942 | 950 | ||
943 | root = kzalloc(sizeof(*root), GFP_NOFS); | 951 | root = kzalloc(sizeof(*root), GFP_NOFS); |
944 | if (!root) | 952 | if (!root) |
945 | return -ENOMEM; | 953 | return ERR_PTR(-ENOMEM); |
946 | 954 | ||
947 | __setup_root(tree_root->nodesize, tree_root->leafsize, | 955 | __setup_root(tree_root->nodesize, tree_root->leafsize, |
948 | tree_root->sectorsize, tree_root->stripesize, | 956 | tree_root->sectorsize, tree_root->stripesize, |
@@ -951,12 +959,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | |||
951 | root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID; | 959 | root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID; |
952 | root->root_key.type = BTRFS_ROOT_ITEM_KEY; | 960 | root->root_key.type = BTRFS_ROOT_ITEM_KEY; |
953 | root->root_key.offset = BTRFS_TREE_LOG_OBJECTID; | 961 | root->root_key.offset = BTRFS_TREE_LOG_OBJECTID; |
962 | /* | ||
963 | * log trees do not get reference counted because they go away | ||
964 | * before a real commit is actually done. They do store pointers | ||
965 | * to file data extents, and those reference counts still get | ||
966 | * updated (along with back refs to the log tree). | ||
967 | */ | ||
954 | root->ref_cows = 0; | 968 | root->ref_cows = 0; |
955 | 969 | ||
956 | root->node = btrfs_alloc_free_block(trans, root, root->leafsize, | 970 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
957 | 0, BTRFS_TREE_LOG_OBJECTID, | 971 | 0, BTRFS_TREE_LOG_OBJECTID, |
958 | trans->transid, 0, 0, 0); | 972 | trans->transid, 0, 0, 0); |
973 | if (IS_ERR(leaf)) { | ||
974 | kfree(root); | ||
975 | return ERR_CAST(leaf); | ||
976 | } | ||
959 | 977 | ||
978 | root->node = leaf; | ||
960 | btrfs_set_header_nritems(root->node, 0); | 979 | btrfs_set_header_nritems(root->node, 0); |
961 | btrfs_set_header_level(root->node, 0); | 980 | btrfs_set_header_level(root->node, 0); |
962 | btrfs_set_header_bytenr(root->node, root->node->start); | 981 | btrfs_set_header_bytenr(root->node, root->node->start); |
@@ -968,7 +987,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | |||
968 | BTRFS_FSID_SIZE); | 987 | BTRFS_FSID_SIZE); |
969 | btrfs_mark_buffer_dirty(root->node); | 988 | btrfs_mark_buffer_dirty(root->node); |
970 | btrfs_tree_unlock(root->node); | 989 | btrfs_tree_unlock(root->node); |
971 | fs_info->log_root_tree = root; | 990 | return root; |
991 | } | ||
992 | |||
993 | int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | ||
994 | struct btrfs_fs_info *fs_info) | ||
995 | { | ||
996 | struct btrfs_root *log_root; | ||
997 | |||
998 | log_root = alloc_log_tree(trans, fs_info); | ||
999 | if (IS_ERR(log_root)) | ||
1000 | return PTR_ERR(log_root); | ||
1001 | WARN_ON(fs_info->log_root_tree); | ||
1002 | fs_info->log_root_tree = log_root; | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | int btrfs_add_log_tree(struct btrfs_trans_handle *trans, | ||
1007 | struct btrfs_root *root) | ||
1008 | { | ||
1009 | struct btrfs_root *log_root; | ||
1010 | struct btrfs_inode_item *inode_item; | ||
1011 | |||
1012 | log_root = alloc_log_tree(trans, root->fs_info); | ||
1013 | if (IS_ERR(log_root)) | ||
1014 | return PTR_ERR(log_root); | ||
1015 | |||
1016 | log_root->last_trans = trans->transid; | ||
1017 | log_root->root_key.offset = root->root_key.objectid; | ||
1018 | |||
1019 | inode_item = &log_root->root_item.inode; | ||
1020 | inode_item->generation = cpu_to_le64(1); | ||
1021 | inode_item->size = cpu_to_le64(3); | ||
1022 | inode_item->nlink = cpu_to_le32(1); | ||
1023 | inode_item->nbytes = cpu_to_le64(root->leafsize); | ||
1024 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); | ||
1025 | |||
1026 | btrfs_set_root_bytenr(&log_root->root_item, log_root->node->start); | ||
1027 | btrfs_set_root_generation(&log_root->root_item, trans->transid); | ||
1028 | |||
1029 | WARN_ON(root->log_root); | ||
1030 | root->log_root = log_root; | ||
1031 | root->log_transid = 0; | ||
972 | return 0; | 1032 | return 0; |
973 | } | 1033 | } |
974 | 1034 | ||
@@ -1136,7 +1196,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) | |||
1136 | { | 1196 | { |
1137 | struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data; | 1197 | struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data; |
1138 | int ret = 0; | 1198 | int ret = 0; |
1139 | struct list_head *cur; | ||
1140 | struct btrfs_device *device; | 1199 | struct btrfs_device *device; |
1141 | struct backing_dev_info *bdi; | 1200 | struct backing_dev_info *bdi; |
1142 | #if 0 | 1201 | #if 0 |
@@ -1144,8 +1203,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) | |||
1144 | btrfs_congested_async(info, 0)) | 1203 | btrfs_congested_async(info, 0)) |
1145 | return 1; | 1204 | return 1; |
1146 | #endif | 1205 | #endif |
1147 | list_for_each(cur, &info->fs_devices->devices) { | 1206 | list_for_each_entry(device, &info->fs_devices->devices, dev_list) { |
1148 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
1149 | if (!device->bdev) | 1207 | if (!device->bdev) |
1150 | continue; | 1208 | continue; |
1151 | bdi = blk_get_backing_dev_info(device->bdev); | 1209 | bdi = blk_get_backing_dev_info(device->bdev); |
@@ -1163,13 +1221,11 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) | |||
1163 | */ | 1221 | */ |
1164 | static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page) | 1222 | static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page) |
1165 | { | 1223 | { |
1166 | struct list_head *cur; | ||
1167 | struct btrfs_device *device; | 1224 | struct btrfs_device *device; |
1168 | struct btrfs_fs_info *info; | 1225 | struct btrfs_fs_info *info; |
1169 | 1226 | ||
1170 | info = (struct btrfs_fs_info *)bdi->unplug_io_data; | 1227 | info = (struct btrfs_fs_info *)bdi->unplug_io_data; |
1171 | list_for_each(cur, &info->fs_devices->devices) { | 1228 | list_for_each_entry(device, &info->fs_devices->devices, dev_list) { |
1172 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
1173 | if (!device->bdev) | 1229 | if (!device->bdev) |
1174 | continue; | 1230 | continue; |
1175 | 1231 | ||
@@ -1535,10 +1591,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1535 | init_waitqueue_head(&fs_info->transaction_throttle); | 1591 | init_waitqueue_head(&fs_info->transaction_throttle); |
1536 | init_waitqueue_head(&fs_info->transaction_wait); | 1592 | init_waitqueue_head(&fs_info->transaction_wait); |
1537 | init_waitqueue_head(&fs_info->async_submit_wait); | 1593 | init_waitqueue_head(&fs_info->async_submit_wait); |
1538 | init_waitqueue_head(&fs_info->tree_log_wait); | ||
1539 | atomic_set(&fs_info->tree_log_commit, 0); | ||
1540 | atomic_set(&fs_info->tree_log_writers, 0); | ||
1541 | fs_info->tree_log_transid = 0; | ||
1542 | 1594 | ||
1543 | __setup_root(4096, 4096, 4096, 4096, tree_root, | 1595 | __setup_root(4096, 4096, 4096, 4096, tree_root, |
1544 | fs_info, BTRFS_ROOT_TREE_OBJECTID); | 1596 | fs_info, BTRFS_ROOT_TREE_OBJECTID); |
@@ -1740,13 +1792,13 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1740 | fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; | 1792 | fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; |
1741 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, | 1793 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, |
1742 | "btrfs-cleaner"); | 1794 | "btrfs-cleaner"); |
1743 | if (!fs_info->cleaner_kthread) | 1795 | if (IS_ERR(fs_info->cleaner_kthread)) |
1744 | goto fail_csum_root; | 1796 | goto fail_csum_root; |
1745 | 1797 | ||
1746 | fs_info->transaction_kthread = kthread_run(transaction_kthread, | 1798 | fs_info->transaction_kthread = kthread_run(transaction_kthread, |
1747 | tree_root, | 1799 | tree_root, |
1748 | "btrfs-transaction"); | 1800 | "btrfs-transaction"); |
1749 | if (!fs_info->transaction_kthread) | 1801 | if (IS_ERR(fs_info->transaction_kthread)) |
1750 | goto fail_cleaner; | 1802 | goto fail_cleaner; |
1751 | 1803 | ||
1752 | if (btrfs_super_log_root(disk_super) != 0) { | 1804 | if (btrfs_super_log_root(disk_super) != 0) { |
@@ -1828,13 +1880,14 @@ fail_sb_buffer: | |||
1828 | fail_iput: | 1880 | fail_iput: |
1829 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); | 1881 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); |
1830 | iput(fs_info->btree_inode); | 1882 | iput(fs_info->btree_inode); |
1831 | fail: | 1883 | |
1832 | btrfs_close_devices(fs_info->fs_devices); | 1884 | btrfs_close_devices(fs_info->fs_devices); |
1833 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 1885 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |
1886 | bdi_destroy(&fs_info->bdi); | ||
1834 | 1887 | ||
1888 | fail: | ||
1835 | kfree(extent_root); | 1889 | kfree(extent_root); |
1836 | kfree(tree_root); | 1890 | kfree(tree_root); |
1837 | bdi_destroy(&fs_info->bdi); | ||
1838 | kfree(fs_info); | 1891 | kfree(fs_info); |
1839 | kfree(chunk_root); | 1892 | kfree(chunk_root); |
1840 | kfree(dev_root); | 1893 | kfree(dev_root); |
@@ -1995,7 +2048,6 @@ static int write_dev_supers(struct btrfs_device *device, | |||
1995 | 2048 | ||
1996 | int write_all_supers(struct btrfs_root *root, int max_mirrors) | 2049 | int write_all_supers(struct btrfs_root *root, int max_mirrors) |
1997 | { | 2050 | { |
1998 | struct list_head *cur; | ||
1999 | struct list_head *head = &root->fs_info->fs_devices->devices; | 2051 | struct list_head *head = &root->fs_info->fs_devices->devices; |
2000 | struct btrfs_device *dev; | 2052 | struct btrfs_device *dev; |
2001 | struct btrfs_super_block *sb; | 2053 | struct btrfs_super_block *sb; |
@@ -2011,8 +2063,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors) | |||
2011 | 2063 | ||
2012 | sb = &root->fs_info->super_for_commit; | 2064 | sb = &root->fs_info->super_for_commit; |
2013 | dev_item = &sb->dev_item; | 2065 | dev_item = &sb->dev_item; |
2014 | list_for_each(cur, head) { | 2066 | list_for_each_entry(dev, head, dev_list) { |
2015 | dev = list_entry(cur, struct btrfs_device, dev_list); | ||
2016 | if (!dev->bdev) { | 2067 | if (!dev->bdev) { |
2017 | total_errors++; | 2068 | total_errors++; |
2018 | continue; | 2069 | continue; |
@@ -2045,8 +2096,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors) | |||
2045 | } | 2096 | } |
2046 | 2097 | ||
2047 | total_errors = 0; | 2098 | total_errors = 0; |
2048 | list_for_each(cur, head) { | 2099 | list_for_each_entry(dev, head, dev_list) { |
2049 | dev = list_entry(cur, struct btrfs_device, dev_list); | ||
2050 | if (!dev->bdev) | 2100 | if (!dev->bdev) |
2051 | continue; | 2101 | continue; |
2052 | if (!dev->in_fs_metadata || !dev->writeable) | 2102 | if (!dev->in_fs_metadata || !dev->writeable) |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index c0ff404c31b7..494a56eb2986 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -98,5 +98,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | |||
98 | struct btrfs_fs_info *fs_info); | 98 | struct btrfs_fs_info *fs_info); |
99 | int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | 99 | int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, |
100 | struct btrfs_fs_info *fs_info); | 100 | struct btrfs_fs_info *fs_info); |
101 | int btrfs_add_log_tree(struct btrfs_trans_handle *trans, | ||
102 | struct btrfs_root *root); | ||
101 | int btree_lock_page_hook(struct page *page); | 103 | int btree_lock_page_hook(struct page *page); |
102 | #endif | 104 | #endif |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 293da650873f..3b26f0980946 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
20 | #include <linux/writeback.h> | 20 | #include <linux/writeback.h> |
21 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
22 | #include <linux/version.h> | ||
23 | #include "compat.h" | 22 | #include "compat.h" |
24 | #include "hash.h" | 23 | #include "hash.h" |
25 | #include "crc32c.h" | 24 | #include "crc32c.h" |
@@ -30,7 +29,6 @@ | |||
30 | #include "volumes.h" | 29 | #include "volumes.h" |
31 | #include "locking.h" | 30 | #include "locking.h" |
32 | #include "ref-cache.h" | 31 | #include "ref-cache.h" |
33 | #include "compat.h" | ||
34 | 32 | ||
35 | #define PENDING_EXTENT_INSERT 0 | 33 | #define PENDING_EXTENT_INSERT 0 |
36 | #define PENDING_EXTENT_DELETE 1 | 34 | #define PENDING_EXTENT_DELETE 1 |
@@ -326,10 +324,8 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, | |||
326 | u64 flags) | 324 | u64 flags) |
327 | { | 325 | { |
328 | struct list_head *head = &info->space_info; | 326 | struct list_head *head = &info->space_info; |
329 | struct list_head *cur; | ||
330 | struct btrfs_space_info *found; | 327 | struct btrfs_space_info *found; |
331 | list_for_each(cur, head) { | 328 | list_for_each_entry(found, head, list) { |
332 | found = list_entry(cur, struct btrfs_space_info, list); | ||
333 | if (found->flags == flags) | 329 | if (found->flags == flags) |
334 | return found; | 330 | return found; |
335 | } | 331 | } |
@@ -2159,7 +2155,8 @@ again: | |||
2159 | ret = find_first_extent_bit(&info->extent_ins, search, &start, | 2155 | ret = find_first_extent_bit(&info->extent_ins, search, &start, |
2160 | &end, EXTENT_WRITEBACK); | 2156 | &end, EXTENT_WRITEBACK); |
2161 | if (ret) { | 2157 | if (ret) { |
2162 | if (skipped && all && !num_inserts) { | 2158 | if (skipped && all && !num_inserts && |
2159 | list_empty(&update_list)) { | ||
2163 | skipped = 0; | 2160 | skipped = 0; |
2164 | search = 0; | 2161 | search = 0; |
2165 | continue; | 2162 | continue; |
@@ -2547,6 +2544,7 @@ again: | |||
2547 | if (ret) { | 2544 | if (ret) { |
2548 | if (all && skipped && !nr) { | 2545 | if (all && skipped && !nr) { |
2549 | search = 0; | 2546 | search = 0; |
2547 | skipped = 0; | ||
2550 | continue; | 2548 | continue; |
2551 | } | 2549 | } |
2552 | mutex_unlock(&info->extent_ins_mutex); | 2550 | mutex_unlock(&info->extent_ins_mutex); |
@@ -2700,13 +2698,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
2700 | /* if metadata always pin */ | 2698 | /* if metadata always pin */ |
2701 | if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) { | 2699 | if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) { |
2702 | if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { | 2700 | if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { |
2703 | struct btrfs_block_group_cache *cache; | 2701 | mutex_lock(&root->fs_info->pinned_mutex); |
2704 | 2702 | btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); | |
2705 | /* btrfs_free_reserved_extent */ | 2703 | mutex_unlock(&root->fs_info->pinned_mutex); |
2706 | cache = btrfs_lookup_block_group(root->fs_info, bytenr); | ||
2707 | BUG_ON(!cache); | ||
2708 | btrfs_add_free_space(cache, bytenr, num_bytes); | ||
2709 | put_block_group(cache); | ||
2710 | update_reserved_extents(root, bytenr, num_bytes, 0); | 2704 | update_reserved_extents(root, bytenr, num_bytes, 0); |
2711 | return 0; | 2705 | return 0; |
2712 | } | 2706 | } |
@@ -3014,7 +3008,6 @@ loop_check: | |||
3014 | static void dump_space_info(struct btrfs_space_info *info, u64 bytes) | 3008 | static void dump_space_info(struct btrfs_space_info *info, u64 bytes) |
3015 | { | 3009 | { |
3016 | struct btrfs_block_group_cache *cache; | 3010 | struct btrfs_block_group_cache *cache; |
3017 | struct list_head *l; | ||
3018 | 3011 | ||
3019 | printk(KERN_INFO "space_info has %llu free, is %sfull\n", | 3012 | printk(KERN_INFO "space_info has %llu free, is %sfull\n", |
3020 | (unsigned long long)(info->total_bytes - info->bytes_used - | 3013 | (unsigned long long)(info->total_bytes - info->bytes_used - |
@@ -3022,8 +3015,7 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes) | |||
3022 | (info->full) ? "" : "not "); | 3015 | (info->full) ? "" : "not "); |
3023 | 3016 | ||
3024 | down_read(&info->groups_sem); | 3017 | down_read(&info->groups_sem); |
3025 | list_for_each(l, &info->block_groups) { | 3018 | list_for_each_entry(cache, &info->block_groups, list) { |
3026 | cache = list_entry(l, struct btrfs_block_group_cache, list); | ||
3027 | spin_lock(&cache->lock); | 3019 | spin_lock(&cache->lock); |
3028 | printk(KERN_INFO "block group %llu has %llu bytes, %llu used " | 3020 | printk(KERN_INFO "block group %llu has %llu bytes, %llu used " |
3029 | "%llu pinned %llu reserved\n", | 3021 | "%llu pinned %llu reserved\n", |
@@ -4444,7 +4436,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, | |||
4444 | u64 lock_end = 0; | 4436 | u64 lock_end = 0; |
4445 | u64 num_bytes; | 4437 | u64 num_bytes; |
4446 | u64 ext_offset; | 4438 | u64 ext_offset; |
4447 | u64 first_pos; | 4439 | u64 search_end = (u64)-1; |
4448 | u32 nritems; | 4440 | u32 nritems; |
4449 | int nr_scaned = 0; | 4441 | int nr_scaned = 0; |
4450 | int extent_locked = 0; | 4442 | int extent_locked = 0; |
@@ -4452,7 +4444,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, | |||
4452 | int ret; | 4444 | int ret; |
4453 | 4445 | ||
4454 | memcpy(&key, leaf_key, sizeof(key)); | 4446 | memcpy(&key, leaf_key, sizeof(key)); |
4455 | first_pos = INT_LIMIT(loff_t) - extent_key->offset; | ||
4456 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) { | 4447 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) { |
4457 | if (key.objectid < ref_path->owner_objectid || | 4448 | if (key.objectid < ref_path->owner_objectid || |
4458 | (key.objectid == ref_path->owner_objectid && | 4449 | (key.objectid == ref_path->owner_objectid && |
@@ -4501,7 +4492,7 @@ next: | |||
4501 | if ((key.objectid > ref_path->owner_objectid) || | 4492 | if ((key.objectid > ref_path->owner_objectid) || |
4502 | (key.objectid == ref_path->owner_objectid && | 4493 | (key.objectid == ref_path->owner_objectid && |
4503 | key.type > BTRFS_EXTENT_DATA_KEY) || | 4494 | key.type > BTRFS_EXTENT_DATA_KEY) || |
4504 | (key.offset >= first_pos + extent_key->offset)) | 4495 | key.offset >= search_end) |
4505 | break; | 4496 | break; |
4506 | } | 4497 | } |
4507 | 4498 | ||
@@ -4534,8 +4525,10 @@ next: | |||
4534 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); | 4525 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); |
4535 | ext_offset = btrfs_file_extent_offset(leaf, fi); | 4526 | ext_offset = btrfs_file_extent_offset(leaf, fi); |
4536 | 4527 | ||
4537 | if (first_pos > key.offset - ext_offset) | 4528 | if (search_end == (u64)-1) { |
4538 | first_pos = key.offset - ext_offset; | 4529 | search_end = key.offset - ext_offset + |
4530 | btrfs_file_extent_ram_bytes(leaf, fi); | ||
4531 | } | ||
4539 | 4532 | ||
4540 | if (!extent_locked) { | 4533 | if (!extent_locked) { |
4541 | lock_start = key.offset; | 4534 | lock_start = key.offset; |
@@ -4724,7 +4717,7 @@ next: | |||
4724 | } | 4717 | } |
4725 | skip: | 4718 | skip: |
4726 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS && | 4719 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS && |
4727 | key.offset >= first_pos + extent_key->offset) | 4720 | key.offset >= search_end) |
4728 | break; | 4721 | break; |
4729 | 4722 | ||
4730 | cond_resched(); | 4723 | cond_resched(); |
@@ -5957,9 +5950,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5957 | path = btrfs_alloc_path(); | 5950 | path = btrfs_alloc_path(); |
5958 | BUG_ON(!path); | 5951 | BUG_ON(!path); |
5959 | 5952 | ||
5960 | btrfs_remove_free_space_cache(block_group); | 5953 | spin_lock(&root->fs_info->block_group_cache_lock); |
5961 | rb_erase(&block_group->cache_node, | 5954 | rb_erase(&block_group->cache_node, |
5962 | &root->fs_info->block_group_cache_tree); | 5955 | &root->fs_info->block_group_cache_tree); |
5956 | spin_unlock(&root->fs_info->block_group_cache_lock); | ||
5957 | btrfs_remove_free_space_cache(block_group); | ||
5963 | down_write(&block_group->space_info->groups_sem); | 5958 | down_write(&block_group->space_info->groups_sem); |
5964 | list_del(&block_group->list); | 5959 | list_del(&block_group->list); |
5965 | up_write(&block_group->space_info->groups_sem); | 5960 | up_write(&block_group->space_info->groups_sem); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index e086d407f1fa..a3b0676403f7 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/spinlock.h> | 9 | #include <linux/spinlock.h> |
10 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
11 | #include <linux/swap.h> | 11 | #include <linux/swap.h> |
12 | #include <linux/version.h> | ||
13 | #include <linux/writeback.h> | 12 | #include <linux/writeback.h> |
14 | #include <linux/pagevec.h> | 13 | #include <linux/pagevec.h> |
15 | #include "extent_io.h" | 14 | #include "extent_io.h" |
@@ -2855,6 +2854,98 @@ out: | |||
2855 | return sector; | 2854 | return sector; |
2856 | } | 2855 | } |
2857 | 2856 | ||
2857 | int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
2858 | __u64 start, __u64 len, get_extent_t *get_extent) | ||
2859 | { | ||
2860 | int ret; | ||
2861 | u64 off = start; | ||
2862 | u64 max = start + len; | ||
2863 | u32 flags = 0; | ||
2864 | u64 disko = 0; | ||
2865 | struct extent_map *em = NULL; | ||
2866 | int end = 0; | ||
2867 | u64 em_start = 0, em_len = 0; | ||
2868 | unsigned long emflags; | ||
2869 | ret = 0; | ||
2870 | |||
2871 | if (len == 0) | ||
2872 | return -EINVAL; | ||
2873 | |||
2874 | lock_extent(&BTRFS_I(inode)->io_tree, start, start + len, | ||
2875 | GFP_NOFS); | ||
2876 | em = get_extent(inode, NULL, 0, off, max - off, 0); | ||
2877 | if (!em) | ||
2878 | goto out; | ||
2879 | if (IS_ERR(em)) { | ||
2880 | ret = PTR_ERR(em); | ||
2881 | goto out; | ||
2882 | } | ||
2883 | while (!end) { | ||
2884 | off = em->start + em->len; | ||
2885 | if (off >= max) | ||
2886 | end = 1; | ||
2887 | |||
2888 | em_start = em->start; | ||
2889 | em_len = em->len; | ||
2890 | |||
2891 | disko = 0; | ||
2892 | flags = 0; | ||
2893 | |||
2894 | switch (em->block_start) { | ||
2895 | case EXTENT_MAP_LAST_BYTE: | ||
2896 | end = 1; | ||
2897 | flags |= FIEMAP_EXTENT_LAST; | ||
2898 | break; | ||
2899 | case EXTENT_MAP_HOLE: | ||
2900 | flags |= FIEMAP_EXTENT_UNWRITTEN; | ||
2901 | break; | ||
2902 | case EXTENT_MAP_INLINE: | ||
2903 | flags |= (FIEMAP_EXTENT_DATA_INLINE | | ||
2904 | FIEMAP_EXTENT_NOT_ALIGNED); | ||
2905 | break; | ||
2906 | case EXTENT_MAP_DELALLOC: | ||
2907 | flags |= (FIEMAP_EXTENT_DELALLOC | | ||
2908 | FIEMAP_EXTENT_UNKNOWN); | ||
2909 | break; | ||
2910 | default: | ||
2911 | disko = em->block_start; | ||
2912 | break; | ||
2913 | } | ||
2914 | if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) | ||
2915 | flags |= FIEMAP_EXTENT_ENCODED; | ||
2916 | |||
2917 | emflags = em->flags; | ||
2918 | free_extent_map(em); | ||
2919 | em = NULL; | ||
2920 | |||
2921 | if (!end) { | ||
2922 | em = get_extent(inode, NULL, 0, off, max - off, 0); | ||
2923 | if (!em) | ||
2924 | goto out; | ||
2925 | if (IS_ERR(em)) { | ||
2926 | ret = PTR_ERR(em); | ||
2927 | goto out; | ||
2928 | } | ||
2929 | emflags = em->flags; | ||
2930 | } | ||
2931 | if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) { | ||
2932 | flags |= FIEMAP_EXTENT_LAST; | ||
2933 | end = 1; | ||
2934 | } | ||
2935 | |||
2936 | ret = fiemap_fill_next_extent(fieinfo, em_start, disko, | ||
2937 | em_len, flags); | ||
2938 | if (ret) | ||
2939 | goto out_free; | ||
2940 | } | ||
2941 | out_free: | ||
2942 | free_extent_map(em); | ||
2943 | out: | ||
2944 | unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len, | ||
2945 | GFP_NOFS); | ||
2946 | return ret; | ||
2947 | } | ||
2948 | |||
2858 | static inline struct page *extent_buffer_page(struct extent_buffer *eb, | 2949 | static inline struct page *extent_buffer_page(struct extent_buffer *eb, |
2859 | unsigned long i) | 2950 | unsigned long i) |
2860 | { | 2951 | { |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index c5b483a79137..e80c6d96b318 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -193,6 +193,8 @@ int extent_commit_write(struct extent_io_tree *tree, | |||
193 | unsigned from, unsigned to); | 193 | unsigned from, unsigned to); |
194 | sector_t extent_bmap(struct address_space *mapping, sector_t iblock, | 194 | sector_t extent_bmap(struct address_space *mapping, sector_t iblock, |
195 | get_extent_t *get_extent); | 195 | get_extent_t *get_extent); |
196 | int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
197 | __u64 start, __u64 len, get_extent_t *get_extent); | ||
196 | int set_range_dirty(struct extent_io_tree *tree, u64 start, u64 end); | 198 | int set_range_dirty(struct extent_io_tree *tree, u64 start, u64 end); |
197 | int set_state_private(struct extent_io_tree *tree, u64 start, u64 private); | 199 | int set_state_private(struct extent_io_tree *tree, u64 start, u64 private); |
198 | int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private); | 200 | int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private); |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 4a83e33ada32..50da69da20ce 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
6 | #include <linux/version.h> | ||
7 | #include <linux/hardirq.h> | 6 | #include <linux/hardirq.h> |
8 | #include "extent_map.h" | 7 | #include "extent_map.h" |
9 | 8 | ||
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 90268334145e..3e8023efaff7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/writeback.h> | 29 | #include <linux/writeback.h> |
30 | #include <linux/statfs.h> | 30 | #include <linux/statfs.h> |
31 | #include <linux/compat.h> | 31 | #include <linux/compat.h> |
32 | #include <linux/version.h> | ||
33 | #include "ctree.h" | 32 | #include "ctree.h" |
34 | #include "disk-io.h" | 33 | #include "disk-io.h" |
35 | #include "transaction.h" | 34 | #include "transaction.h" |
@@ -1215,10 +1214,10 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1215 | } | 1214 | } |
1216 | mutex_unlock(&root->fs_info->trans_mutex); | 1215 | mutex_unlock(&root->fs_info->trans_mutex); |
1217 | 1216 | ||
1218 | root->fs_info->tree_log_batch++; | 1217 | root->log_batch++; |
1219 | filemap_fdatawrite(inode->i_mapping); | 1218 | filemap_fdatawrite(inode->i_mapping); |
1220 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 1219 | btrfs_wait_ordered_range(inode, 0, (u64)-1); |
1221 | root->fs_info->tree_log_batch++; | 1220 | root->log_batch++; |
1222 | 1221 | ||
1223 | /* | 1222 | /* |
1224 | * ok we haven't committed the transaction yet, lets do a commit | 1223 | * ok we haven't committed the transaction yet, lets do a commit |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8adfe059ab41..288c2cdc7543 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/statfs.h> | 34 | #include <linux/statfs.h> |
35 | #include <linux/compat.h> | 35 | #include <linux/compat.h> |
36 | #include <linux/bit_spinlock.h> | 36 | #include <linux/bit_spinlock.h> |
37 | #include <linux/version.h> | ||
38 | #include <linux/xattr.h> | 37 | #include <linux/xattr.h> |
39 | #include <linux/posix_acl.h> | 38 | #include <linux/posix_acl.h> |
40 | #include <linux/falloc.h> | 39 | #include <linux/falloc.h> |
@@ -1324,12 +1323,11 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans, | |||
1324 | struct inode *inode, u64 file_offset, | 1323 | struct inode *inode, u64 file_offset, |
1325 | struct list_head *list) | 1324 | struct list_head *list) |
1326 | { | 1325 | { |
1327 | struct list_head *cur; | ||
1328 | struct btrfs_ordered_sum *sum; | 1326 | struct btrfs_ordered_sum *sum; |
1329 | 1327 | ||
1330 | btrfs_set_trans_block_group(trans, inode); | 1328 | btrfs_set_trans_block_group(trans, inode); |
1331 | list_for_each(cur, list) { | 1329 | |
1332 | sum = list_entry(cur, struct btrfs_ordered_sum, list); | 1330 | list_for_each_entry(sum, list, list) { |
1333 | btrfs_csum_file_blocks(trans, | 1331 | btrfs_csum_file_blocks(trans, |
1334 | BTRFS_I(inode)->root->fs_info->csum_root, sum); | 1332 | BTRFS_I(inode)->root->fs_info->csum_root, sum); |
1335 | } | 1333 | } |
@@ -4158,9 +4156,10 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
4158 | return -EINVAL; | 4156 | return -EINVAL; |
4159 | } | 4157 | } |
4160 | 4158 | ||
4161 | static sector_t btrfs_bmap(struct address_space *mapping, sector_t iblock) | 4159 | static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
4160 | __u64 start, __u64 len) | ||
4162 | { | 4161 | { |
4163 | return extent_bmap(mapping, iblock, btrfs_get_extent); | 4162 | return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent); |
4164 | } | 4163 | } |
4165 | 4164 | ||
4166 | int btrfs_readpage(struct file *file, struct page *page) | 4165 | int btrfs_readpage(struct file *file, struct page *page) |
@@ -4987,13 +4986,24 @@ static struct extent_io_ops btrfs_extent_io_ops = { | |||
4987 | .clear_bit_hook = btrfs_clear_bit_hook, | 4986 | .clear_bit_hook = btrfs_clear_bit_hook, |
4988 | }; | 4987 | }; |
4989 | 4988 | ||
4989 | /* | ||
4990 | * btrfs doesn't support the bmap operation because swapfiles | ||
4991 | * use bmap to make a mapping of extents in the file. They assume | ||
4992 | * these extents won't change over the life of the file and they | ||
4993 | * use the bmap result to do IO directly to the drive. | ||
4994 | * | ||
4995 | * the btrfs bmap call would return logical addresses that aren't | ||
4996 | * suitable for IO and they also will change frequently as COW | ||
4997 | * operations happen. So, swapfile + btrfs == corruption. | ||
4998 | * | ||
4999 | * For now we're avoiding this by dropping bmap. | ||
5000 | */ | ||
4990 | static struct address_space_operations btrfs_aops = { | 5001 | static struct address_space_operations btrfs_aops = { |
4991 | .readpage = btrfs_readpage, | 5002 | .readpage = btrfs_readpage, |
4992 | .writepage = btrfs_writepage, | 5003 | .writepage = btrfs_writepage, |
4993 | .writepages = btrfs_writepages, | 5004 | .writepages = btrfs_writepages, |
4994 | .readpages = btrfs_readpages, | 5005 | .readpages = btrfs_readpages, |
4995 | .sync_page = block_sync_page, | 5006 | .sync_page = block_sync_page, |
4996 | .bmap = btrfs_bmap, | ||
4997 | .direct_IO = btrfs_direct_IO, | 5007 | .direct_IO = btrfs_direct_IO, |
4998 | .invalidatepage = btrfs_invalidatepage, | 5008 | .invalidatepage = btrfs_invalidatepage, |
4999 | .releasepage = btrfs_releasepage, | 5009 | .releasepage = btrfs_releasepage, |
@@ -5017,6 +5027,7 @@ static struct inode_operations btrfs_file_inode_operations = { | |||
5017 | .removexattr = btrfs_removexattr, | 5027 | .removexattr = btrfs_removexattr, |
5018 | .permission = btrfs_permission, | 5028 | .permission = btrfs_permission, |
5019 | .fallocate = btrfs_fallocate, | 5029 | .fallocate = btrfs_fallocate, |
5030 | .fiemap = btrfs_fiemap, | ||
5020 | }; | 5031 | }; |
5021 | static struct inode_operations btrfs_special_inode_operations = { | 5032 | static struct inode_operations btrfs_special_inode_operations = { |
5022 | .getattr = btrfs_getattr, | 5033 | .getattr = btrfs_getattr, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c2aa33e3feb5..988fdc8b49eb 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/compat.h> | 38 | #include <linux/compat.h> |
39 | #include <linux/bit_spinlock.h> | 39 | #include <linux/bit_spinlock.h> |
40 | #include <linux/security.h> | 40 | #include <linux/security.h> |
41 | #include <linux/version.h> | ||
42 | #include <linux/xattr.h> | 41 | #include <linux/xattr.h> |
43 | #include <linux/vmalloc.h> | 42 | #include <linux/vmalloc.h> |
44 | #include "compat.h" | 43 | #include "compat.h" |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index a20940170274..77c2411a5f0f 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -613,7 +613,6 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, | |||
613 | struct btrfs_sector_sum *sector_sums; | 613 | struct btrfs_sector_sum *sector_sums; |
614 | struct btrfs_ordered_extent *ordered; | 614 | struct btrfs_ordered_extent *ordered; |
615 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; | 615 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
616 | struct list_head *cur; | ||
617 | unsigned long num_sectors; | 616 | unsigned long num_sectors; |
618 | unsigned long i; | 617 | unsigned long i; |
619 | u32 sectorsize = BTRFS_I(inode)->root->sectorsize; | 618 | u32 sectorsize = BTRFS_I(inode)->root->sectorsize; |
@@ -624,8 +623,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, | |||
624 | return 1; | 623 | return 1; |
625 | 624 | ||
626 | mutex_lock(&tree->mutex); | 625 | mutex_lock(&tree->mutex); |
627 | list_for_each_prev(cur, &ordered->list) { | 626 | list_for_each_entry_reverse(ordered_sum, &ordered->list, list) { |
628 | ordered_sum = list_entry(cur, struct btrfs_ordered_sum, list); | ||
629 | if (disk_bytenr >= ordered_sum->bytenr) { | 627 | if (disk_bytenr >= ordered_sum->bytenr) { |
630 | num_sectors = ordered_sum->len / sectorsize; | 628 | num_sectors = ordered_sum->len / sectorsize; |
631 | sector_sums = ordered_sum->sums; | 629 | sector_sums = ordered_sum->sums; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index db9fb3bc1e33..f3fd7e2cbc38 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/ctype.h> | 37 | #include <linux/ctype.h> |
38 | #include <linux/namei.h> | 38 | #include <linux/namei.h> |
39 | #include <linux/miscdevice.h> | 39 | #include <linux/miscdevice.h> |
40 | #include <linux/version.h> | ||
41 | #include <linux/magic.h> | 40 | #include <linux/magic.h> |
42 | #include "compat.h" | 41 | #include "compat.h" |
43 | #include "ctree.h" | 42 | #include "ctree.h" |
@@ -583,17 +582,18 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, | |||
583 | struct btrfs_ioctl_vol_args *vol; | 582 | struct btrfs_ioctl_vol_args *vol; |
584 | struct btrfs_fs_devices *fs_devices; | 583 | struct btrfs_fs_devices *fs_devices; |
585 | int ret = -ENOTTY; | 584 | int ret = -ENOTTY; |
586 | int len; | ||
587 | 585 | ||
588 | if (!capable(CAP_SYS_ADMIN)) | 586 | if (!capable(CAP_SYS_ADMIN)) |
589 | return -EPERM; | 587 | return -EPERM; |
590 | 588 | ||
591 | vol = kmalloc(sizeof(*vol), GFP_KERNEL); | 589 | vol = kmalloc(sizeof(*vol), GFP_KERNEL); |
590 | if (!vol) | ||
591 | return -ENOMEM; | ||
592 | |||
592 | if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) { | 593 | if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) { |
593 | ret = -EFAULT; | 594 | ret = -EFAULT; |
594 | goto out; | 595 | goto out; |
595 | } | 596 | } |
596 | len = strnlen(vol->name, BTRFS_PATH_NAME_MAX); | ||
597 | 597 | ||
598 | switch (cmd) { | 598 | switch (cmd) { |
599 | case BTRFS_IOC_SCAN_DEV: | 599 | case BTRFS_IOC_SCAN_DEV: |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 8a08f9443340..919172de5c9a 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -852,11 +852,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | |||
852 | { | 852 | { |
853 | struct btrfs_pending_snapshot *pending; | 853 | struct btrfs_pending_snapshot *pending; |
854 | struct list_head *head = &trans->transaction->pending_snapshots; | 854 | struct list_head *head = &trans->transaction->pending_snapshots; |
855 | struct list_head *cur; | ||
856 | int ret; | 855 | int ret; |
857 | 856 | ||
858 | list_for_each(cur, head) { | 857 | list_for_each_entry(pending, head, list) { |
859 | pending = list_entry(cur, struct btrfs_pending_snapshot, list); | ||
860 | ret = create_pending_snapshot(trans, fs_info, pending); | 858 | ret = create_pending_snapshot(trans, fs_info, pending); |
861 | BUG_ON(ret); | 859 | BUG_ON(ret); |
862 | } | 860 | } |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index d81cda2e077c..4f26f3ed0c87 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -78,104 +78,6 @@ static int link_to_fixup_dir(struct btrfs_trans_handle *trans, | |||
78 | */ | 78 | */ |
79 | 79 | ||
80 | /* | 80 | /* |
81 | * btrfs_add_log_tree adds a new per-subvolume log tree into the | ||
82 | * tree of log tree roots. This must be called with a tree log transaction | ||
83 | * running (see start_log_trans). | ||
84 | */ | ||
85 | static int btrfs_add_log_tree(struct btrfs_trans_handle *trans, | ||
86 | struct btrfs_root *root) | ||
87 | { | ||
88 | struct btrfs_key key; | ||
89 | struct btrfs_root_item root_item; | ||
90 | struct btrfs_inode_item *inode_item; | ||
91 | struct extent_buffer *leaf; | ||
92 | struct btrfs_root *new_root = root; | ||
93 | int ret; | ||
94 | u64 objectid = root->root_key.objectid; | ||
95 | |||
96 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0, | ||
97 | BTRFS_TREE_LOG_OBJECTID, | ||
98 | trans->transid, 0, 0, 0); | ||
99 | if (IS_ERR(leaf)) { | ||
100 | ret = PTR_ERR(leaf); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | btrfs_set_header_nritems(leaf, 0); | ||
105 | btrfs_set_header_level(leaf, 0); | ||
106 | btrfs_set_header_bytenr(leaf, leaf->start); | ||
107 | btrfs_set_header_generation(leaf, trans->transid); | ||
108 | btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID); | ||
109 | |||
110 | write_extent_buffer(leaf, root->fs_info->fsid, | ||
111 | (unsigned long)btrfs_header_fsid(leaf), | ||
112 | BTRFS_FSID_SIZE); | ||
113 | btrfs_mark_buffer_dirty(leaf); | ||
114 | |||
115 | inode_item = &root_item.inode; | ||
116 | memset(inode_item, 0, sizeof(*inode_item)); | ||
117 | inode_item->generation = cpu_to_le64(1); | ||
118 | inode_item->size = cpu_to_le64(3); | ||
119 | inode_item->nlink = cpu_to_le32(1); | ||
120 | inode_item->nbytes = cpu_to_le64(root->leafsize); | ||
121 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); | ||
122 | |||
123 | btrfs_set_root_bytenr(&root_item, leaf->start); | ||
124 | btrfs_set_root_generation(&root_item, trans->transid); | ||
125 | btrfs_set_root_level(&root_item, 0); | ||
126 | btrfs_set_root_refs(&root_item, 0); | ||
127 | btrfs_set_root_used(&root_item, 0); | ||
128 | |||
129 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); | ||
130 | root_item.drop_level = 0; | ||
131 | |||
132 | btrfs_tree_unlock(leaf); | ||
133 | free_extent_buffer(leaf); | ||
134 | leaf = NULL; | ||
135 | |||
136 | btrfs_set_root_dirid(&root_item, 0); | ||
137 | |||
138 | key.objectid = BTRFS_TREE_LOG_OBJECTID; | ||
139 | key.offset = objectid; | ||
140 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | ||
141 | ret = btrfs_insert_root(trans, root->fs_info->log_root_tree, &key, | ||
142 | &root_item); | ||
143 | if (ret) | ||
144 | goto fail; | ||
145 | |||
146 | new_root = btrfs_read_fs_root_no_radix(root->fs_info->log_root_tree, | ||
147 | &key); | ||
148 | BUG_ON(!new_root); | ||
149 | |||
150 | WARN_ON(root->log_root); | ||
151 | root->log_root = new_root; | ||
152 | |||
153 | /* | ||
154 | * log trees do not get reference counted because they go away | ||
155 | * before a real commit is actually done. They do store pointers | ||
156 | * to file data extents, and those reference counts still get | ||
157 | * updated (along with back refs to the log tree). | ||
158 | */ | ||
159 | new_root->ref_cows = 0; | ||
160 | new_root->last_trans = trans->transid; | ||
161 | |||
162 | /* | ||
163 | * we need to make sure the root block for this new tree | ||
164 | * is marked as dirty in the dirty_log_pages tree. This | ||
165 | * is how it gets flushed down to disk at tree log commit time. | ||
166 | * | ||
167 | * the tree logging mutex keeps others from coming in and changing | ||
168 | * the new_root->node, so we can safely access it here | ||
169 | */ | ||
170 | set_extent_dirty(&new_root->dirty_log_pages, new_root->node->start, | ||
171 | new_root->node->start + new_root->node->len - 1, | ||
172 | GFP_NOFS); | ||
173 | |||
174 | fail: | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * start a sub transaction and setup the log tree | 81 | * start a sub transaction and setup the log tree |
180 | * this increments the log tree writer count to make the people | 82 | * this increments the log tree writer count to make the people |
181 | * syncing the tree wait for us to finish | 83 | * syncing the tree wait for us to finish |
@@ -184,6 +86,14 @@ static int start_log_trans(struct btrfs_trans_handle *trans, | |||
184 | struct btrfs_root *root) | 86 | struct btrfs_root *root) |
185 | { | 87 | { |
186 | int ret; | 88 | int ret; |
89 | |||
90 | mutex_lock(&root->log_mutex); | ||
91 | if (root->log_root) { | ||
92 | root->log_batch++; | ||
93 | atomic_inc(&root->log_writers); | ||
94 | mutex_unlock(&root->log_mutex); | ||
95 | return 0; | ||
96 | } | ||
187 | mutex_lock(&root->fs_info->tree_log_mutex); | 97 | mutex_lock(&root->fs_info->tree_log_mutex); |
188 | if (!root->fs_info->log_root_tree) { | 98 | if (!root->fs_info->log_root_tree) { |
189 | ret = btrfs_init_log_root_tree(trans, root->fs_info); | 99 | ret = btrfs_init_log_root_tree(trans, root->fs_info); |
@@ -193,9 +103,10 @@ static int start_log_trans(struct btrfs_trans_handle *trans, | |||
193 | ret = btrfs_add_log_tree(trans, root); | 103 | ret = btrfs_add_log_tree(trans, root); |
194 | BUG_ON(ret); | 104 | BUG_ON(ret); |
195 | } | 105 | } |
196 | atomic_inc(&root->fs_info->tree_log_writers); | ||
197 | root->fs_info->tree_log_batch++; | ||
198 | mutex_unlock(&root->fs_info->tree_log_mutex); | 106 | mutex_unlock(&root->fs_info->tree_log_mutex); |
107 | root->log_batch++; | ||
108 | atomic_inc(&root->log_writers); | ||
109 | mutex_unlock(&root->log_mutex); | ||
199 | return 0; | 110 | return 0; |
200 | } | 111 | } |
201 | 112 | ||
@@ -212,13 +123,12 @@ static int join_running_log_trans(struct btrfs_root *root) | |||
212 | if (!root->log_root) | 123 | if (!root->log_root) |
213 | return -ENOENT; | 124 | return -ENOENT; |
214 | 125 | ||
215 | mutex_lock(&root->fs_info->tree_log_mutex); | 126 | mutex_lock(&root->log_mutex); |
216 | if (root->log_root) { | 127 | if (root->log_root) { |
217 | ret = 0; | 128 | ret = 0; |
218 | atomic_inc(&root->fs_info->tree_log_writers); | 129 | atomic_inc(&root->log_writers); |
219 | root->fs_info->tree_log_batch++; | ||
220 | } | 130 | } |
221 | mutex_unlock(&root->fs_info->tree_log_mutex); | 131 | mutex_unlock(&root->log_mutex); |
222 | return ret; | 132 | return ret; |
223 | } | 133 | } |
224 | 134 | ||
@@ -228,10 +138,11 @@ static int join_running_log_trans(struct btrfs_root *root) | |||
228 | */ | 138 | */ |
229 | static int end_log_trans(struct btrfs_root *root) | 139 | static int end_log_trans(struct btrfs_root *root) |
230 | { | 140 | { |
231 | atomic_dec(&root->fs_info->tree_log_writers); | 141 | if (atomic_dec_and_test(&root->log_writers)) { |
232 | smp_mb(); | 142 | smp_mb(); |
233 | if (waitqueue_active(&root->fs_info->tree_log_wait)) | 143 | if (waitqueue_active(&root->log_writer_wait)) |
234 | wake_up(&root->fs_info->tree_log_wait); | 144 | wake_up(&root->log_writer_wait); |
145 | } | ||
235 | return 0; | 146 | return 0; |
236 | } | 147 | } |
237 | 148 | ||
@@ -1902,26 +1813,65 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, | |||
1902 | } | 1813 | } |
1903 | } | 1814 | } |
1904 | btrfs_free_path(path); | 1815 | btrfs_free_path(path); |
1905 | if (wc->free) | ||
1906 | free_extent_buffer(log->node); | ||
1907 | return ret; | 1816 | return ret; |
1908 | } | 1817 | } |
1909 | 1818 | ||
1910 | static int wait_log_commit(struct btrfs_root *log) | 1819 | /* |
1820 | * helper function to update the item for a given subvolumes log root | ||
1821 | * in the tree of log roots | ||
1822 | */ | ||
1823 | static int update_log_root(struct btrfs_trans_handle *trans, | ||
1824 | struct btrfs_root *log) | ||
1825 | { | ||
1826 | int ret; | ||
1827 | |||
1828 | if (log->log_transid == 1) { | ||
1829 | /* insert root item on the first sync */ | ||
1830 | ret = btrfs_insert_root(trans, log->fs_info->log_root_tree, | ||
1831 | &log->root_key, &log->root_item); | ||
1832 | } else { | ||
1833 | ret = btrfs_update_root(trans, log->fs_info->log_root_tree, | ||
1834 | &log->root_key, &log->root_item); | ||
1835 | } | ||
1836 | return ret; | ||
1837 | } | ||
1838 | |||
1839 | static int wait_log_commit(struct btrfs_root *root, unsigned long transid) | ||
1911 | { | 1840 | { |
1912 | DEFINE_WAIT(wait); | 1841 | DEFINE_WAIT(wait); |
1913 | u64 transid = log->fs_info->tree_log_transid; | 1842 | int index = transid % 2; |
1914 | 1843 | ||
1844 | /* | ||
1845 | * we only allow two pending log transactions at a time, | ||
1846 | * so we know that if ours is more than 2 older than the | ||
1847 | * current transaction, we're done | ||
1848 | */ | ||
1915 | do { | 1849 | do { |
1916 | prepare_to_wait(&log->fs_info->tree_log_wait, &wait, | 1850 | prepare_to_wait(&root->log_commit_wait[index], |
1917 | TASK_UNINTERRUPTIBLE); | 1851 | &wait, TASK_UNINTERRUPTIBLE); |
1918 | mutex_unlock(&log->fs_info->tree_log_mutex); | 1852 | mutex_unlock(&root->log_mutex); |
1919 | if (atomic_read(&log->fs_info->tree_log_commit)) | 1853 | if (root->log_transid < transid + 2 && |
1854 | atomic_read(&root->log_commit[index])) | ||
1920 | schedule(); | 1855 | schedule(); |
1921 | finish_wait(&log->fs_info->tree_log_wait, &wait); | 1856 | finish_wait(&root->log_commit_wait[index], &wait); |
1922 | mutex_lock(&log->fs_info->tree_log_mutex); | 1857 | mutex_lock(&root->log_mutex); |
1923 | } while (transid == log->fs_info->tree_log_transid && | 1858 | } while (root->log_transid < transid + 2 && |
1924 | atomic_read(&log->fs_info->tree_log_commit)); | 1859 | atomic_read(&root->log_commit[index])); |
1860 | return 0; | ||
1861 | } | ||
1862 | |||
1863 | static int wait_for_writer(struct btrfs_root *root) | ||
1864 | { | ||
1865 | DEFINE_WAIT(wait); | ||
1866 | while (atomic_read(&root->log_writers)) { | ||
1867 | prepare_to_wait(&root->log_writer_wait, | ||
1868 | &wait, TASK_UNINTERRUPTIBLE); | ||
1869 | mutex_unlock(&root->log_mutex); | ||
1870 | if (atomic_read(&root->log_writers)) | ||
1871 | schedule(); | ||
1872 | mutex_lock(&root->log_mutex); | ||
1873 | finish_wait(&root->log_writer_wait, &wait); | ||
1874 | } | ||
1925 | return 0; | 1875 | return 0; |
1926 | } | 1876 | } |
1927 | 1877 | ||
@@ -1933,57 +1883,114 @@ static int wait_log_commit(struct btrfs_root *log) | |||
1933 | int btrfs_sync_log(struct btrfs_trans_handle *trans, | 1883 | int btrfs_sync_log(struct btrfs_trans_handle *trans, |
1934 | struct btrfs_root *root) | 1884 | struct btrfs_root *root) |
1935 | { | 1885 | { |
1886 | int index1; | ||
1887 | int index2; | ||
1936 | int ret; | 1888 | int ret; |
1937 | unsigned long batch; | ||
1938 | struct btrfs_root *log = root->log_root; | 1889 | struct btrfs_root *log = root->log_root; |
1890 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; | ||
1939 | 1891 | ||
1940 | mutex_lock(&log->fs_info->tree_log_mutex); | 1892 | mutex_lock(&root->log_mutex); |
1941 | if (atomic_read(&log->fs_info->tree_log_commit)) { | 1893 | index1 = root->log_transid % 2; |
1942 | wait_log_commit(log); | 1894 | if (atomic_read(&root->log_commit[index1])) { |
1943 | goto out; | 1895 | wait_log_commit(root, root->log_transid); |
1896 | mutex_unlock(&root->log_mutex); | ||
1897 | return 0; | ||
1944 | } | 1898 | } |
1945 | atomic_set(&log->fs_info->tree_log_commit, 1); | 1899 | atomic_set(&root->log_commit[index1], 1); |
1900 | |||
1901 | /* wait for previous tree log sync to complete */ | ||
1902 | if (atomic_read(&root->log_commit[(index1 + 1) % 2])) | ||
1903 | wait_log_commit(root, root->log_transid - 1); | ||
1946 | 1904 | ||
1947 | while (1) { | 1905 | while (1) { |
1948 | batch = log->fs_info->tree_log_batch; | 1906 | unsigned long batch = root->log_batch; |
1949 | mutex_unlock(&log->fs_info->tree_log_mutex); | 1907 | mutex_unlock(&root->log_mutex); |
1950 | schedule_timeout_uninterruptible(1); | 1908 | schedule_timeout_uninterruptible(1); |
1951 | mutex_lock(&log->fs_info->tree_log_mutex); | 1909 | mutex_lock(&root->log_mutex); |
1952 | 1910 | wait_for_writer(root); | |
1953 | while (atomic_read(&log->fs_info->tree_log_writers)) { | 1911 | if (batch == root->log_batch) |
1954 | DEFINE_WAIT(wait); | ||
1955 | prepare_to_wait(&log->fs_info->tree_log_wait, &wait, | ||
1956 | TASK_UNINTERRUPTIBLE); | ||
1957 | mutex_unlock(&log->fs_info->tree_log_mutex); | ||
1958 | if (atomic_read(&log->fs_info->tree_log_writers)) | ||
1959 | schedule(); | ||
1960 | mutex_lock(&log->fs_info->tree_log_mutex); | ||
1961 | finish_wait(&log->fs_info->tree_log_wait, &wait); | ||
1962 | } | ||
1963 | if (batch == log->fs_info->tree_log_batch) | ||
1964 | break; | 1912 | break; |
1965 | } | 1913 | } |
1966 | 1914 | ||
1967 | ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); | 1915 | ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); |
1968 | BUG_ON(ret); | 1916 | BUG_ON(ret); |
1969 | ret = btrfs_write_and_wait_marked_extents(root->fs_info->log_root_tree, | 1917 | |
1970 | &root->fs_info->log_root_tree->dirty_log_pages); | 1918 | btrfs_set_root_bytenr(&log->root_item, log->node->start); |
1919 | btrfs_set_root_generation(&log->root_item, trans->transid); | ||
1920 | btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node)); | ||
1921 | |||
1922 | root->log_batch = 0; | ||
1923 | root->log_transid++; | ||
1924 | log->log_transid = root->log_transid; | ||
1925 | smp_mb(); | ||
1926 | /* | ||
1927 | * log tree has been flushed to disk, new modifications of | ||
1928 | * the log will be written to new positions. so it's safe to | ||
1929 | * allow log writers to go in. | ||
1930 | */ | ||
1931 | mutex_unlock(&root->log_mutex); | ||
1932 | |||
1933 | mutex_lock(&log_root_tree->log_mutex); | ||
1934 | log_root_tree->log_batch++; | ||
1935 | atomic_inc(&log_root_tree->log_writers); | ||
1936 | mutex_unlock(&log_root_tree->log_mutex); | ||
1937 | |||
1938 | ret = update_log_root(trans, log); | ||
1939 | BUG_ON(ret); | ||
1940 | |||
1941 | mutex_lock(&log_root_tree->log_mutex); | ||
1942 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { | ||
1943 | smp_mb(); | ||
1944 | if (waitqueue_active(&log_root_tree->log_writer_wait)) | ||
1945 | wake_up(&log_root_tree->log_writer_wait); | ||
1946 | } | ||
1947 | |||
1948 | index2 = log_root_tree->log_transid % 2; | ||
1949 | if (atomic_read(&log_root_tree->log_commit[index2])) { | ||
1950 | wait_log_commit(log_root_tree, log_root_tree->log_transid); | ||
1951 | mutex_unlock(&log_root_tree->log_mutex); | ||
1952 | goto out; | ||
1953 | } | ||
1954 | atomic_set(&log_root_tree->log_commit[index2], 1); | ||
1955 | |||
1956 | if (atomic_read(&log_root_tree->log_commit[(index2 + 1) % 2])) | ||
1957 | wait_log_commit(log_root_tree, log_root_tree->log_transid - 1); | ||
1958 | |||
1959 | wait_for_writer(log_root_tree); | ||
1960 | |||
1961 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, | ||
1962 | &log_root_tree->dirty_log_pages); | ||
1971 | BUG_ON(ret); | 1963 | BUG_ON(ret); |
1972 | 1964 | ||
1973 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, | 1965 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, |
1974 | log->fs_info->log_root_tree->node->start); | 1966 | log_root_tree->node->start); |
1975 | btrfs_set_super_log_root_level(&root->fs_info->super_for_commit, | 1967 | btrfs_set_super_log_root_level(&root->fs_info->super_for_commit, |
1976 | btrfs_header_level(log->fs_info->log_root_tree->node)); | 1968 | btrfs_header_level(log_root_tree->node)); |
1969 | |||
1970 | log_root_tree->log_batch = 0; | ||
1971 | log_root_tree->log_transid++; | ||
1972 | smp_mb(); | ||
1973 | |||
1974 | mutex_unlock(&log_root_tree->log_mutex); | ||
1975 | |||
1976 | /* | ||
1977 | * nobody else is going to jump in and write the the ctree | ||
1978 | * super here because the log_commit atomic below is protecting | ||
1979 | * us. We must be called with a transaction handle pinning | ||
1980 | * the running transaction open, so a full commit can't hop | ||
1981 | * in and cause problems either. | ||
1982 | */ | ||
1983 | write_ctree_super(trans, root->fs_info->tree_root, 2); | ||
1977 | 1984 | ||
1978 | write_ctree_super(trans, log->fs_info->tree_root, 2); | 1985 | atomic_set(&log_root_tree->log_commit[index2], 0); |
1979 | log->fs_info->tree_log_transid++; | ||
1980 | log->fs_info->tree_log_batch = 0; | ||
1981 | atomic_set(&log->fs_info->tree_log_commit, 0); | ||
1982 | smp_mb(); | 1986 | smp_mb(); |
1983 | if (waitqueue_active(&log->fs_info->tree_log_wait)) | 1987 | if (waitqueue_active(&log_root_tree->log_commit_wait[index2])) |
1984 | wake_up(&log->fs_info->tree_log_wait); | 1988 | wake_up(&log_root_tree->log_commit_wait[index2]); |
1985 | out: | 1989 | out: |
1986 | mutex_unlock(&log->fs_info->tree_log_mutex); | 1990 | atomic_set(&root->log_commit[index1], 0); |
1991 | smp_mb(); | ||
1992 | if (waitqueue_active(&root->log_commit_wait[index1])) | ||
1993 | wake_up(&root->log_commit_wait[index1]); | ||
1987 | return 0; | 1994 | return 0; |
1988 | } | 1995 | } |
1989 | 1996 | ||
@@ -2019,38 +2026,18 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
2019 | start, end, GFP_NOFS); | 2026 | start, end, GFP_NOFS); |
2020 | } | 2027 | } |
2021 | 2028 | ||
2022 | log = root->log_root; | 2029 | if (log->log_transid > 0) { |
2023 | ret = btrfs_del_root(trans, root->fs_info->log_root_tree, | 2030 | ret = btrfs_del_root(trans, root->fs_info->log_root_tree, |
2024 | &log->root_key); | 2031 | &log->root_key); |
2025 | BUG_ON(ret); | 2032 | BUG_ON(ret); |
2033 | } | ||
2026 | root->log_root = NULL; | 2034 | root->log_root = NULL; |
2027 | kfree(root->log_root); | 2035 | free_extent_buffer(log->node); |
2036 | kfree(log); | ||
2028 | return 0; | 2037 | return 0; |
2029 | } | 2038 | } |
2030 | 2039 | ||
2031 | /* | 2040 | /* |
2032 | * helper function to update the item for a given subvolumes log root | ||
2033 | * in the tree of log roots | ||
2034 | */ | ||
2035 | static int update_log_root(struct btrfs_trans_handle *trans, | ||
2036 | struct btrfs_root *log) | ||
2037 | { | ||
2038 | u64 bytenr = btrfs_root_bytenr(&log->root_item); | ||
2039 | int ret; | ||
2040 | |||
2041 | if (log->node->start == bytenr) | ||
2042 | return 0; | ||
2043 | |||
2044 | btrfs_set_root_bytenr(&log->root_item, log->node->start); | ||
2045 | btrfs_set_root_generation(&log->root_item, trans->transid); | ||
2046 | btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node)); | ||
2047 | ret = btrfs_update_root(trans, log->fs_info->log_root_tree, | ||
2048 | &log->root_key, &log->root_item); | ||
2049 | BUG_ON(ret); | ||
2050 | return ret; | ||
2051 | } | ||
2052 | |||
2053 | /* | ||
2054 | * If both a file and directory are logged, and unlinks or renames are | 2041 | * If both a file and directory are logged, and unlinks or renames are |
2055 | * mixed in, we have a few interesting corners: | 2042 | * mixed in, we have a few interesting corners: |
2056 | * | 2043 | * |
@@ -2711,11 +2698,6 @@ next_slot: | |||
2711 | 2698 | ||
2712 | btrfs_free_path(path); | 2699 | btrfs_free_path(path); |
2713 | btrfs_free_path(dst_path); | 2700 | btrfs_free_path(dst_path); |
2714 | |||
2715 | mutex_lock(&root->fs_info->tree_log_mutex); | ||
2716 | ret = update_log_root(trans, log); | ||
2717 | BUG_ON(ret); | ||
2718 | mutex_unlock(&root->fs_info->tree_log_mutex); | ||
2719 | out: | 2701 | out: |
2720 | return 0; | 2702 | return 0; |
2721 | } | 2703 | } |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 3451e1cca2b5..fd0bedb07a64 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
22 | #include <linux/random.h> | 22 | #include <linux/random.h> |
23 | #include <linux/version.h> | ||
24 | #include <asm/div64.h> | 23 | #include <asm/div64.h> |
25 | #include "compat.h" | 24 | #include "compat.h" |
26 | #include "ctree.h" | 25 | #include "ctree.h" |
@@ -104,10 +103,8 @@ static noinline struct btrfs_device *__find_device(struct list_head *head, | |||
104 | u64 devid, u8 *uuid) | 103 | u64 devid, u8 *uuid) |
105 | { | 104 | { |
106 | struct btrfs_device *dev; | 105 | struct btrfs_device *dev; |
107 | struct list_head *cur; | ||
108 | 106 | ||
109 | list_for_each(cur, head) { | 107 | list_for_each_entry(dev, head, dev_list) { |
110 | dev = list_entry(cur, struct btrfs_device, dev_list); | ||
111 | if (dev->devid == devid && | 108 | if (dev->devid == devid && |
112 | (!uuid || !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE))) { | 109 | (!uuid || !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE))) { |
113 | return dev; | 110 | return dev; |
@@ -118,11 +115,9 @@ static noinline struct btrfs_device *__find_device(struct list_head *head, | |||
118 | 115 | ||
119 | static noinline struct btrfs_fs_devices *find_fsid(u8 *fsid) | 116 | static noinline struct btrfs_fs_devices *find_fsid(u8 *fsid) |
120 | { | 117 | { |
121 | struct list_head *cur; | ||
122 | struct btrfs_fs_devices *fs_devices; | 118 | struct btrfs_fs_devices *fs_devices; |
123 | 119 | ||
124 | list_for_each(cur, &fs_uuids) { | 120 | list_for_each_entry(fs_devices, &fs_uuids, list) { |
125 | fs_devices = list_entry(cur, struct btrfs_fs_devices, list); | ||
126 | if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0) | 121 | if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0) |
127 | return fs_devices; | 122 | return fs_devices; |
128 | } | 123 | } |
@@ -345,14 +340,11 @@ error: | |||
345 | 340 | ||
346 | int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices) | 341 | int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices) |
347 | { | 342 | { |
348 | struct list_head *tmp; | 343 | struct btrfs_device *device, *next; |
349 | struct list_head *cur; | ||
350 | struct btrfs_device *device; | ||
351 | 344 | ||
352 | mutex_lock(&uuid_mutex); | 345 | mutex_lock(&uuid_mutex); |
353 | again: | 346 | again: |
354 | list_for_each_safe(cur, tmp, &fs_devices->devices) { | 347 | list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) { |
355 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
356 | if (device->in_fs_metadata) | 348 | if (device->in_fs_metadata) |
357 | continue; | 349 | continue; |
358 | 350 | ||
@@ -383,14 +375,12 @@ again: | |||
383 | 375 | ||
384 | static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) | 376 | static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) |
385 | { | 377 | { |
386 | struct list_head *cur; | ||
387 | struct btrfs_device *device; | 378 | struct btrfs_device *device; |
388 | 379 | ||
389 | if (--fs_devices->opened > 0) | 380 | if (--fs_devices->opened > 0) |
390 | return 0; | 381 | return 0; |
391 | 382 | ||
392 | list_for_each(cur, &fs_devices->devices) { | 383 | list_for_each_entry(device, &fs_devices->devices, dev_list) { |
393 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
394 | if (device->bdev) { | 384 | if (device->bdev) { |
395 | close_bdev_exclusive(device->bdev, device->mode); | 385 | close_bdev_exclusive(device->bdev, device->mode); |
396 | fs_devices->open_devices--; | 386 | fs_devices->open_devices--; |
@@ -439,7 +429,6 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
439 | { | 429 | { |
440 | struct block_device *bdev; | 430 | struct block_device *bdev; |
441 | struct list_head *head = &fs_devices->devices; | 431 | struct list_head *head = &fs_devices->devices; |
442 | struct list_head *cur; | ||
443 | struct btrfs_device *device; | 432 | struct btrfs_device *device; |
444 | struct block_device *latest_bdev = NULL; | 433 | struct block_device *latest_bdev = NULL; |
445 | struct buffer_head *bh; | 434 | struct buffer_head *bh; |
@@ -450,8 +439,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
450 | int seeding = 1; | 439 | int seeding = 1; |
451 | int ret = 0; | 440 | int ret = 0; |
452 | 441 | ||
453 | list_for_each(cur, head) { | 442 | list_for_each_entry(device, head, dev_list) { |
454 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
455 | if (device->bdev) | 443 | if (device->bdev) |
456 | continue; | 444 | continue; |
457 | if (!device->name) | 445 | if (!device->name) |
@@ -578,7 +566,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
578 | *(unsigned long long *)disk_super->fsid, | 566 | *(unsigned long long *)disk_super->fsid, |
579 | *(unsigned long long *)(disk_super->fsid + 8)); | 567 | *(unsigned long long *)(disk_super->fsid + 8)); |
580 | } | 568 | } |
581 | printk(KERN_INFO "devid %llu transid %llu %s\n", | 569 | printk(KERN_CONT "devid %llu transid %llu %s\n", |
582 | (unsigned long long)devid, (unsigned long long)transid, path); | 570 | (unsigned long long)devid, (unsigned long long)transid, path); |
583 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); | 571 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); |
584 | 572 | ||
@@ -1017,14 +1005,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1017 | } | 1005 | } |
1018 | 1006 | ||
1019 | if (strcmp(device_path, "missing") == 0) { | 1007 | if (strcmp(device_path, "missing") == 0) { |
1020 | struct list_head *cur; | ||
1021 | struct list_head *devices; | 1008 | struct list_head *devices; |
1022 | struct btrfs_device *tmp; | 1009 | struct btrfs_device *tmp; |
1023 | 1010 | ||
1024 | device = NULL; | 1011 | device = NULL; |
1025 | devices = &root->fs_info->fs_devices->devices; | 1012 | devices = &root->fs_info->fs_devices->devices; |
1026 | list_for_each(cur, devices) { | 1013 | list_for_each_entry(tmp, devices, dev_list) { |
1027 | tmp = list_entry(cur, struct btrfs_device, dev_list); | ||
1028 | if (tmp->in_fs_metadata && !tmp->bdev) { | 1014 | if (tmp->in_fs_metadata && !tmp->bdev) { |
1029 | device = tmp; | 1015 | device = tmp; |
1030 | break; | 1016 | break; |
@@ -1280,7 +1266,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1280 | struct btrfs_trans_handle *trans; | 1266 | struct btrfs_trans_handle *trans; |
1281 | struct btrfs_device *device; | 1267 | struct btrfs_device *device; |
1282 | struct block_device *bdev; | 1268 | struct block_device *bdev; |
1283 | struct list_head *cur; | ||
1284 | struct list_head *devices; | 1269 | struct list_head *devices; |
1285 | struct super_block *sb = root->fs_info->sb; | 1270 | struct super_block *sb = root->fs_info->sb; |
1286 | u64 total_bytes; | 1271 | u64 total_bytes; |
@@ -1304,8 +1289,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1304 | mutex_lock(&root->fs_info->volume_mutex); | 1289 | mutex_lock(&root->fs_info->volume_mutex); |
1305 | 1290 | ||
1306 | devices = &root->fs_info->fs_devices->devices; | 1291 | devices = &root->fs_info->fs_devices->devices; |
1307 | list_for_each(cur, devices) { | 1292 | list_for_each_entry(device, devices, dev_list) { |
1308 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
1309 | if (device->bdev == bdev) { | 1293 | if (device->bdev == bdev) { |
1310 | ret = -EEXIST; | 1294 | ret = -EEXIST; |
1311 | goto error; | 1295 | goto error; |
@@ -1704,7 +1688,6 @@ static u64 div_factor(u64 num, int factor) | |||
1704 | int btrfs_balance(struct btrfs_root *dev_root) | 1688 | int btrfs_balance(struct btrfs_root *dev_root) |
1705 | { | 1689 | { |
1706 | int ret; | 1690 | int ret; |
1707 | struct list_head *cur; | ||
1708 | struct list_head *devices = &dev_root->fs_info->fs_devices->devices; | 1691 | struct list_head *devices = &dev_root->fs_info->fs_devices->devices; |
1709 | struct btrfs_device *device; | 1692 | struct btrfs_device *device; |
1710 | u64 old_size; | 1693 | u64 old_size; |
@@ -1723,8 +1706,7 @@ int btrfs_balance(struct btrfs_root *dev_root) | |||
1723 | dev_root = dev_root->fs_info->dev_root; | 1706 | dev_root = dev_root->fs_info->dev_root; |
1724 | 1707 | ||
1725 | /* step one make some room on all the devices */ | 1708 | /* step one make some room on all the devices */ |
1726 | list_for_each(cur, devices) { | 1709 | list_for_each_entry(device, devices, dev_list) { |
1727 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
1728 | old_size = device->total_bytes; | 1710 | old_size = device->total_bytes; |
1729 | size_to_free = div_factor(old_size, 1); | 1711 | size_to_free = div_factor(old_size, 1); |
1730 | size_to_free = min(size_to_free, (u64)1 * 1024 * 1024); | 1712 | size_to_free = min(size_to_free, (u64)1 * 1024 * 1024); |
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 7f332e270894..b4fa5f4b6ad1 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -45,9 +45,12 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name, | |||
45 | /* lookup the xattr by name */ | 45 | /* lookup the xattr by name */ |
46 | di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, | 46 | di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, |
47 | strlen(name), 0); | 47 | strlen(name), 0); |
48 | if (!di || IS_ERR(di)) { | 48 | if (!di) { |
49 | ret = -ENODATA; | 49 | ret = -ENODATA; |
50 | goto out; | 50 | goto out; |
51 | } else if (IS_ERR(di)) { | ||
52 | ret = PTR_ERR(di); | ||
53 | goto out; | ||
51 | } | 54 | } |
52 | 55 | ||
53 | leaf = path->nodes[0]; | 56 | leaf = path->nodes[0]; |
@@ -62,6 +65,14 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name, | |||
62 | ret = -ERANGE; | 65 | ret = -ERANGE; |
63 | goto out; | 66 | goto out; |
64 | } | 67 | } |
68 | |||
69 | /* | ||
70 | * The way things are packed into the leaf is like this | ||
71 | * |struct btrfs_dir_item|name|data| | ||
72 | * where name is the xattr name, so security.foo, and data is the | ||
73 | * content of the xattr. data_ptr points to the location in memory | ||
74 | * where the data starts in the in memory leaf | ||
75 | */ | ||
65 | data_ptr = (unsigned long)((char *)(di + 1) + | 76 | data_ptr = (unsigned long)((char *)(di + 1) + |
66 | btrfs_dir_name_len(leaf, di)); | 77 | btrfs_dir_name_len(leaf, di)); |
67 | read_extent_buffer(leaf, buffer, data_ptr, | 78 | read_extent_buffer(leaf, buffer, data_ptr, |
@@ -176,7 +187,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
176 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 187 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
177 | if (ret < 0) | 188 | if (ret < 0) |
178 | goto err; | 189 | goto err; |
179 | ret = 0; | ||
180 | advance = 0; | 190 | advance = 0; |
181 | while (1) { | 191 | while (1) { |
182 | leaf = path->nodes[0]; | 192 | leaf = path->nodes[0]; |