aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-10 16:19:33 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commitf29844623de29a12358d7fba35d0959465b64adf (patch)
tree0268addb1a152cc1dbfdef1a50e32d6a7e97bdcf /fs/btrfs/disk-io.c
parent16432985920f3c45af82da214e2498f3e2f9066b (diff)
Btrfs: Write out all super blocks on commit, and bring back proper barrier support
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c118
1 files changed, 113 insertions, 5 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 59bdf0474be3..cf1de75f088a 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -382,7 +382,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
382 BUG_ON(ret); 382 BUG_ON(ret);
383 383
384 if (offset == BTRFS_SUPER_INFO_OFFSET) { 384 if (offset == BTRFS_SUPER_INFO_OFFSET) {
385 bio->bi_bdev = root->fs_info->sb->s_bdev; 385 bio->bi_bdev = root->fs_info->fs_devices->latest_bdev;
386 submit_bio(rw, bio); 386 submit_bio(rw, bio);
387 return 0; 387 return 0;
388 } 388 }
@@ -988,7 +988,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
988 spin_lock_init(&fs_info->new_trans_lock); 988 spin_lock_init(&fs_info->new_trans_lock);
989 989
990 init_completion(&fs_info->kobj_unregister); 990 init_completion(&fs_info->kobj_unregister);
991 sb_set_blocksize(sb, 4096); 991 sb_set_blocksize(sb, BTRFS_SUPER_INFO_SIZE);
992 fs_info->tree_root = tree_root; 992 fs_info->tree_root = tree_root;
993 fs_info->extent_root = extent_root; 993 fs_info->extent_root = extent_root;
994 fs_info->chunk_root = chunk_root; 994 fs_info->chunk_root = chunk_root;
@@ -1169,14 +1169,121 @@ fail:
1169 return ERR_PTR(err); 1169 return ERR_PTR(err);
1170} 1170}
1171 1171
1172static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
1173{
1174 char b[BDEVNAME_SIZE];
1175
1176 if (uptodate) {
1177 set_buffer_uptodate(bh);
1178 } else {
1179 if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
1180 printk(KERN_WARNING "lost page write due to "
1181 "I/O error on %s\n",
1182 bdevname(bh->b_bdev, b));
1183 }
1184 set_buffer_write_io_error(bh);
1185 clear_buffer_uptodate(bh);
1186 }
1187 unlock_buffer(bh);
1188 put_bh(bh);
1189}
1190
1191int write_all_supers(struct btrfs_root *root)
1192{
1193 struct list_head *cur;
1194 struct list_head *head = &root->fs_info->fs_devices->devices;
1195 struct btrfs_device *dev;
1196 struct extent_buffer *sb;
1197 struct btrfs_dev_item *dev_item;
1198 struct buffer_head *bh;
1199 int ret;
1200 int do_barriers;
1201
1202 do_barriers = !btrfs_test_opt(root, NOBARRIER);
1203
1204 sb = root->fs_info->sb_buffer;
1205 dev_item = (struct btrfs_dev_item *)offsetof(struct btrfs_super_block,
1206 dev_item);
1207 list_for_each(cur, head) {
1208 dev = list_entry(cur, struct btrfs_device, dev_list);
1209 btrfs_set_device_type(sb, dev_item, dev->type);
1210 btrfs_set_device_id(sb, dev_item, dev->devid);
1211 btrfs_set_device_total_bytes(sb, dev_item, dev->total_bytes);
1212 btrfs_set_device_bytes_used(sb, dev_item, dev->bytes_used);
1213 btrfs_set_device_io_align(sb, dev_item, dev->io_align);
1214 btrfs_set_device_io_width(sb, dev_item, dev->io_width);
1215 btrfs_set_device_sector_size(sb, dev_item, dev->sector_size);
1216 write_extent_buffer(sb, dev->uuid,
1217 (unsigned long)btrfs_device_uuid(dev_item),
1218 BTRFS_DEV_UUID_SIZE);
1219
1220 btrfs_set_header_flag(sb, BTRFS_HEADER_FLAG_WRITTEN);
1221 csum_tree_block(root, sb, 0);
1222
1223 bh = __getblk(dev->bdev, BTRFS_SUPER_INFO_OFFSET /
1224 root->fs_info->sb->s_blocksize,
1225 BTRFS_SUPER_INFO_SIZE);
1226
1227 read_extent_buffer(sb, bh->b_data, 0, BTRFS_SUPER_INFO_SIZE);
1228 dev->pending_io = bh;
1229
1230 get_bh(bh);
1231 set_buffer_uptodate(bh);
1232 lock_buffer(bh);
1233 bh->b_end_io = btrfs_end_buffer_write_sync;
1234
1235 if (do_barriers && dev->barriers) {
1236 ret = submit_bh(WRITE_BARRIER, bh);
1237 if (ret == -EOPNOTSUPP) {
1238 printk("btrfs: disabling barriers on dev %s\n",
1239 dev->name);
1240 set_buffer_uptodate(bh);
1241 dev->barriers = 0;
1242 get_bh(bh);
1243 lock_buffer(bh);
1244 ret = submit_bh(WRITE, bh);
1245 }
1246 } else {
1247 ret = submit_bh(WRITE, bh);
1248 }
1249 BUG_ON(ret);
1250 }
1251
1252 list_for_each(cur, head) {
1253 dev = list_entry(cur, struct btrfs_device, dev_list);
1254 BUG_ON(!dev->pending_io);
1255 bh = dev->pending_io;
1256 wait_on_buffer(bh);
1257 if (!buffer_uptodate(dev->pending_io)) {
1258 if (do_barriers && dev->barriers) {
1259 printk("btrfs: disabling barriers on dev %s\n",
1260 dev->name);
1261 set_buffer_uptodate(bh);
1262 get_bh(bh);
1263 lock_buffer(bh);
1264 dev->barriers = 0;
1265 ret = submit_bh(WRITE, bh);
1266 BUG_ON(ret);
1267 wait_on_buffer(bh);
1268 BUG_ON(!buffer_uptodate(bh));
1269 } else {
1270 BUG();
1271 }
1272
1273 }
1274 dev->pending_io = NULL;
1275 brelse(bh);
1276 }
1277 return 0;
1278}
1279
1172int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 1280int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
1173 *root) 1281 *root)
1174{ 1282{
1175 int ret; 1283 int ret;
1176 struct extent_buffer *super = root->fs_info->sb_buffer;
1177 struct inode *btree_inode = root->fs_info->btree_inode;
1178 struct super_block *sb = root->fs_info->sb;
1179 1284
1285 ret = write_all_supers(root);
1286#if 0
1180 if (!btrfs_test_opt(root, NOBARRIER)) 1287 if (!btrfs_test_opt(root, NOBARRIER))
1181 blkdev_issue_flush(sb->s_bdev, NULL); 1288 blkdev_issue_flush(sb->s_bdev, NULL);
1182 set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, super); 1289 set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, super);
@@ -1184,6 +1291,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
1184 super->start, super->len); 1291 super->start, super->len);
1185 if (!btrfs_test_opt(root, NOBARRIER)) 1292 if (!btrfs_test_opt(root, NOBARRIER))
1186 blkdev_issue_flush(sb->s_bdev, NULL); 1293 blkdev_issue_flush(sb->s_bdev, NULL);
1294#endif
1187 return ret; 1295 return ret;
1188} 1296}
1189 1297