aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/btrfs/disk-io.c118
-rw-r--r--fs/btrfs/disk-io.h1
-rw-r--r--fs/btrfs/volumes.c8
-rw-r--r--fs/btrfs/volumes.h3
4 files changed, 122 insertions, 8 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
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 4fac0ccbf8f8..60b01902db79 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -20,6 +20,7 @@
20#define __DISKIO__ 20#define __DISKIO__
21 21
22#define BTRFS_SUPER_INFO_OFFSET (16 * 1024) 22#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
23#define BTRFS_SUPER_INFO_SIZE 4096
23struct btrfs_device; 24struct btrfs_device;
24struct btrfs_fs_devices; 25struct btrfs_fs_devices;
25 26
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 3b927f698320..07d43553141c 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -125,6 +125,7 @@ static int device_list_add(const char *path,
125 return -ENOMEM; 125 return -ENOMEM;
126 } 126 }
127 device->devid = devid; 127 device->devid = devid;
128 device->barriers = 1;
128 device->name = kstrdup(path, GFP_NOFS); 129 device->name = kstrdup(path, GFP_NOFS);
129 if (!device->name) { 130 if (!device->name) {
130 kfree(device); 131 kfree(device);
@@ -208,6 +209,7 @@ int btrfs_scan_one_device(const char *path, int flags, void *holder,
208 struct buffer_head *bh; 209 struct buffer_head *bh;
209 int ret; 210 int ret;
210 u64 devid; 211 u64 devid;
212 u64 transid;
211 213
212 mutex_lock(&uuid_mutex); 214 mutex_lock(&uuid_mutex);
213 215
@@ -236,14 +238,14 @@ int btrfs_scan_one_device(const char *path, int flags, void *holder,
236 goto error_brelse; 238 goto error_brelse;
237 } 239 }
238 devid = le64_to_cpu(disk_super->dev_item.devid); 240 devid = le64_to_cpu(disk_super->dev_item.devid);
239 printk("found device %Lu on %s\n", devid, path); 241 transid = btrfs_super_generation(disk_super);
242 printk("found device %Lu transid %Lu on %s\n", devid, transid, path);
240 ret = device_list_add(path, disk_super, devid, fs_devices_ret); 243 ret = device_list_add(path, disk_super, devid, fs_devices_ret);
241 244
242error_brelse: 245error_brelse:
243 brelse(bh); 246 brelse(bh);
244error_close: 247error_close:
245 close_bdev_excl(bdev); 248 close_bdev_excl(bdev);
246 printk("scan one closes bdev %s\n", path);
247error: 249error:
248 mutex_unlock(&uuid_mutex); 250 mutex_unlock(&uuid_mutex);
249 return ret; 251 return ret;
@@ -1143,7 +1145,7 @@ static int read_one_dev(struct btrfs_root *root,
1143 device = btrfs_find_device(root, devid); 1145 device = btrfs_find_device(root, devid);
1144 if (!device) { 1146 if (!device) {
1145 printk("warning devid %Lu not found already\n", devid); 1147 printk("warning devid %Lu not found already\n", devid);
1146 device = kmalloc(sizeof(*device), GFP_NOFS); 1148 device = kzalloc(sizeof(*device), GFP_NOFS);
1147 if (!device) 1149 if (!device)
1148 return -ENOMEM; 1150 return -ENOMEM;
1149 list_add(&device->dev_list, 1151 list_add(&device->dev_list,
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 3d5d0a9cb827..89548837a1cc 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -21,9 +21,12 @@
21 21
22#include <linux/bio.h> 22#include <linux/bio.h>
23 23
24struct buffer_head;
24struct btrfs_device { 25struct btrfs_device {
25 struct list_head dev_list; 26 struct list_head dev_list;
26 struct btrfs_root *dev_root; 27 struct btrfs_root *dev_root;
28 struct buffer_head *pending_io;
29 int barriers;
27 spinlock_t io_lock; 30 spinlock_t io_lock;
28 31
29 struct block_device *bdev; 32 struct block_device *bdev;