Accepting request 205320 from home:dsterba:branches:filesystems

SR: a few fixes, aimed for 13.1 RC2

- fsck updates
- more mkfs sanity checks
- qgroup rescan wait

OBS-URL: https://build.opensuse.org/request/show/205320
OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=144
This commit is contained in:
Tomáš Chvátal 2013-10-31 09:12:04 +00:00 committed by Git OBS Bridge
parent 3ba375bc14
commit 5be20c4ea7
16 changed files with 1342 additions and 1 deletions

View File

@ -0,0 +1,36 @@
From bdccfd46b1f2ff668351790db42e8831ca4ec4b4 Mon Sep 17 00:00:00 2001
From: Josef Bacik <jbacik@fusionio.com>
Date: Fri, 14 Jun 2013 14:25:54 -0400
Subject: [PATCH 50/62] Btrfs-progs: commit the csum_root if we do
--init-csum-tree
This is just an oddity with the commit stuff in btrfs-progs. It will just
update the generation of the root you call with, which in btrfsck case would
have been the fs_root. But because we didn't actually update the fs_root we
wouldn't have cow'ed the fs root and therefore the generation will not match the
node which will make the file system unmountable. Fix this by calling with the
csum_root which is the one we're messing with. Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
cmds-check.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmds-check.c b/cmds-check.c
index 8015288318a2..dbb41e5a4d5b 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -5800,7 +5800,7 @@ int cmd_check(int argc, char **argv)
return -EIO;
}
- ret = btrfs_commit_transaction(trans, root);
+ ret = btrfs_commit_transaction(trans, info->csum_root);
if (ret)
exit(1);
goto out;
--
1.8.3.1

View File

@ -0,0 +1,45 @@
From 892bfedb24519d95dbe3d5cdc44d26adbc1c93dc Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Tue, 9 Jul 2013 18:38:29 +0200
Subject: [PATCH 51/62] btrfs-progs: Fix getopt on arm/ppc platforms
(same as commit bb0eabc383e9a3fde7cdb02591ca88243f3e31fb)
There, 'char' is unsigned, so once assigned '-1' from getopt, it gets
the value 255. Then, it compared to '-1' gives false.
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
btrfs-crc.c | 2 +-
cmds-device.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/btrfs-crc.c b/btrfs-crc.c
index e4cda4312700..1990534ad4d2 100644
--- a/btrfs-crc.c
+++ b/btrfs-crc.c
@@ -34,7 +34,7 @@ void usage(void)
int main(int argc, char **argv)
{
- char c;
+ int c;
unsigned long checksum = 0;
char *str;
char *buf;
diff --git a/cmds-device.c b/cmds-device.c
index 41e79d375ce4..9e7328b20a55 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -294,7 +294,7 @@ static int cmd_dev_stats(int argc, char **argv)
int ret;
int fdmnt;
int i;
- char c;
+ int c;
int err = 0;
__u64 flags = 0;
--
1.8.3.1

View File

@ -0,0 +1,38 @@
From 2fdbfac178348ec229db866bccec8dd0f23738ab Mon Sep 17 00:00:00 2001
From: Michal Marek <mmarek@suse.cz>
Date: Tue, 9 Jul 2013 18:38:46 +0200
Subject: [PATCH 52/62] btrfs-progs: fix duplicate __[su]* typedefs on ppc64
The <ext2fs/ext2_types.h> header does attempt to avoid conflicts with
<linux/types.h>, but on ppc64, <asm-generic/int-ll64.h> gets somehow
included by other headers.
Include <linux/types.h> explicitly, so that <ext2fs/ext2_types.h>
notices it. The proper fix would be to fix <ext2fs/ext2_types.h> to not
use its own typedefs.
Originally observed in btrfs-convert, put the include into kerncompat.h
to avoid future problems.
Signed-off-by: Michal Marek <mmarek@suse.cz>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
kerncompat.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/kerncompat.h b/kerncompat.h
index 9c116b4fe841..6584818d0af3 100644
--- a/kerncompat.h
+++ b/kerncompat.h
@@ -26,6 +26,7 @@
#include <endian.h>
#include <byteswap.h>
#include <assert.h>
+#include <linux/types.h>
#ifndef READ
#define READ 0
--
1.8.3.1

View File

@ -0,0 +1,61 @@
From 2fac6f99128560c5993a02d2de0cc3d8238f3b51 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Tue, 9 Jul 2013 18:39:24 +0200
Subject: [PATCH 53/62] btrfs-progs: use reentrant localtime
localtime may return NULL (when an error is detected eg. after setting
tzname), followed by a segfault when the values is about to be used.
localtime_r works, does not set tzname and does not return NULL.
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
btrfs-list.c | 10 ++++++----
cmds-subvolume.c | 10 ++++++----
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/btrfs-list.c b/btrfs-list.c
index 4fab85882165..ea80bfeef2f1 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -1337,10 +1337,12 @@ static void print_subvolume_column(struct root_info *subv,
printf("%llu", subv->top_id);
break;
case BTRFS_LIST_OTIME:
- if (subv->otime)
- strftime(tstr, 256, "%Y-%m-%d %X",
- localtime(&subv->otime));
- else
+ if (subv->otime) {
+ struct tm tm;
+
+ localtime_r(&subv->otime, &tm);
+ strftime(tstr, 256, "%Y-%m-%d %X", &tm);
+ } else
strcpy(tstr, "-");
printf("%s", tstr);
break;
diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index ccb476274240..faf05cab2ad9 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -898,10 +898,12 @@ static int cmd_subvol_show(int argc, char **argv)
uuid_unparse(get_ri.puuid, uuidparse);
printf("\tParent uuid: \t\t%s\n", uuidparse);
- if (get_ri.otime)
- strftime(tstr, 256, "%Y-%m-%d %X",
- localtime(&get_ri.otime));
- else
+ if (get_ri.otime) {
+ struct tm tm;
+
+ localtime_r(&get_ri.otime, &tm);
+ strftime(tstr, 256, "%Y-%m-%d %X", &tm);
+ } else
strcpy(tstr, "-");
printf("\tCreation time: \t\t%s\n", tstr);
--
1.8.3.1

View File

@ -0,0 +1,36 @@
From 3b167f3ea4e8b8ea292326924653d8862114626e Mon Sep 17 00:00:00 2001
From: Anand Jain <anand.jain@oracle.com>
Date: Fri, 26 Jul 2013 01:35:30 +0800
Subject: [PATCH 54/62] btrfs-progs: don't have to report ENOMEDIUM error
during open
when we scan /proc/partitions the cdrom is scanned
as well, and we don't have to report ENOMEDIUM errors
against it.
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
utils.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/utils.c b/utils.c
index be0bfd5ecac2..6c1a96f2032f 100644
--- a/utils.c
+++ b/utils.c
@@ -1414,8 +1414,9 @@ scan_again:
fd = open(fullpath, O_RDONLY);
if (fd < 0) {
- fprintf(stderr, "failed to open %s: %s\n",
- fullpath, strerror(errno));
+ if (errno != ENOMEDIUM)
+ fprintf(stderr, "failed to open %s: %s\n",
+ fullpath, strerror(errno));
continue;
}
ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
--
1.8.3.1

View File

@ -0,0 +1,94 @@
From d74078b9e01ad6eab5ba4d951917c29a70e7be18 Mon Sep 17 00:00:00 2001
From: Jan Schmidt <list.btrfs@jan-o-sch.net>
Date: Mon, 6 May 2013 21:15:18 +0200
Subject: [PATCH 55/62] Btrfs-progs: added "btrfs quota rescan" -w switch
(wait)
With -w one can wait for a rescan operation to finish. It can be used when
starting a rescan operation or later to wait for the currently running
rescan operation to finish. Waiting is interruptible.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
cmds-quota.c | 19 +++++++++++++++++--
ioctl.h | 1 +
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/cmds-quota.c b/cmds-quota.c
index 2e2971a41df7..af98d6e71570 100644
--- a/cmds-quota.c
+++ b/cmds-quota.c
@@ -93,10 +93,11 @@ static int cmd_quota_disable(int argc, char **argv)
}
static const char * const cmd_quota_rescan_usage[] = {
- "btrfs quota rescan [-s] <path>",
+ "btrfs quota rescan [-sw] <path>",
"Trash all qgroup numbers and scan the metadata again with the current config.",
"",
"-s show status of a running rescan operation",
+ "-w wait for rescan operation to finish (can be already in progress)",
NULL
};
@@ -108,21 +109,30 @@ static int cmd_quota_rescan(int argc, char **argv)
char *path = NULL;
struct btrfs_ioctl_quota_rescan_args args;
int ioctlnum = BTRFS_IOC_QUOTA_RESCAN;
+ int wait_for_completion = 0;
optind = 1;
while (1) {
- int c = getopt(argc, argv, "s");
+ int c = getopt(argc, argv, "sw");
if (c < 0)
break;
switch (c) {
case 's':
ioctlnum = BTRFS_IOC_QUOTA_RESCAN_STATUS;
break;
+ case 'w':
+ wait_for_completion = 1;
+ break;
default:
usage(cmd_quota_rescan_usage);
}
}
+ if (ioctlnum != BTRFS_IOC_QUOTA_RESCAN && wait_for_completion) {
+ fprintf(stderr, "ERROR: -w cannot be used with -s\n");
+ return 12;
+ }
+
if (check_argc_exact(argc - optind, 1))
usage(cmd_quota_rescan_usage);
@@ -137,6 +147,11 @@ static int cmd_quota_rescan(int argc, char **argv)
ret = ioctl(fd, ioctlnum, &args);
e = errno;
+
+ if (wait_for_completion && (ret == 0 || e == EINPROGRESS)) {
+ ret = ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_WAIT, &args);
+ e = errno;
+ }
close(fd);
if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN) {
diff --git a/ioctl.h b/ioctl.h
index abe6dd4234d9..c260bbf6b4bb 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -529,6 +529,7 @@ struct btrfs_ioctl_clone_range_args {
struct btrfs_ioctl_quota_rescan_args)
#define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \
struct btrfs_ioctl_quota_rescan_args)
+#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
#define BTRFS_IOC_GET_FSLABEL _IOR(BTRFS_IOCTL_MAGIC, 49, \
char[BTRFS_LABEL_SIZE])
#define BTRFS_IOC_SET_FSLABEL _IOW(BTRFS_IOCTL_MAGIC, 50, \
--
1.8.3.1

View File

@ -0,0 +1,36 @@
From 85a8cc9ecfb9b61c5feaaf3ba861f27a2501691d Mon Sep 17 00:00:00 2001
From: Zach Brown <zab@redhat.com>
Date: Wed, 14 Aug 2013 16:16:40 -0700
Subject: [PATCH 56/62] btrfs-progs: fix qgroup realloc inheritance
qgroup.c:82:23: warning: memcpy with byte count of 0
qgroup.c:83:23: warning: memcpy with byte count of 0
The inheritance wasn't copying qgroups[] because a confused sizeof()
gave 0 byte memcpy()s. It's been like this for the year since it was
merged, so I guess this isn't a very important thing to do :).
Signed-off-by: Zach Brown <zab@redhat.com>
Reviewed-by: Arne Jansen <sensille@gmx.net>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
qgroup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qgroup.c b/qgroup.c
index dafde12becf6..e860b309e77c 100644
--- a/qgroup.c
+++ b/qgroup.c
@@ -74,7 +74,7 @@ int qgroup_inherit_realloc(struct btrfs_qgroup_inherit **inherit, int n,
if (*inherit) {
struct btrfs_qgroup_inherit *i = *inherit;
- int s = sizeof(out->qgroups);
+ int s = sizeof(out->qgroups[0]);
out->num_qgroups = i->num_qgroups;
out->num_ref_copies = i->num_ref_copies;
--
1.8.3.1

View File

@ -0,0 +1,111 @@
From 18d8ff57c3cd9ee31829b19fcd6ca57ed201720a Mon Sep 17 00:00:00 2001
From: Filipe David Borba Manana <fdmanana@gmail.com>
Date: Tue, 3 Sep 2013 12:19:58 +0100
Subject: [PATCH 57/62] Btrfs-progs: fix restore command leaving corrupted
files
When there are files that have parts shared with snapshots, the
restore command was incorrectly restoring them, as it was not
taking into account the offset and number of bytes fields from
the file extent item. Besides leaving the recovered file corrupt,
it was also inneficient as it read and wrote more data than needed
(with each extent copy overwriting portions of the one previously
written).
The following steps show how to reproduce this corruption issue:
$ mkfs.btrfs -f /dev/sdb3
$ mount /dev/sdb3 /mnt/btrfs
$ perl -e '$d = "\x41" . ("\x00" x (1024*1024+349)); open($f,">","/mnt/btrfs/foobar"); print $f $d; close($f);'
$ du -b /mnt/btrfs/foobar
1048926 /mnt/btrfs/foobar
$ md5sum /mnt/btrfs/foobar
f9f778f3a7410c40e4ed104a3a63c3c4 /mnt/btrfs/foobar
$ btrfs subvolume snapshot /mnt/btrfs /mnt/btrfs/my_snap
$ perl -e 'open($f, "+<", "/mnt/btrfs/foobar"); seek($f, 4096, 0); print $f "\xff"; close($f);'
$ md5sum /mnt/btrfs/foobar
b983fcefd4622a03a78936484c40272b /mnt/btrfs/foobar
$ umount /mnt/btrfs
$ btrfs restore /dev/sdb3 /tmp/copy
$ du -b /tmp/copy/foobar
1048926 /tmp/copy/foobar
$ md5sum /tmp/copy/foobar
88db338cbc1c44dfabae083f1ce642d5 /tmp/copy/foobar
$ od -t x1 -j 8192 -N 4 /tmp/copy/foobar
0020000 41 00 00 00
0020004
$ mount /dev/sdb3 /mnt/btrfs
$ od -t x1 -j 8192 -N 4 /mnt/btrfs/foobar
0020000 00 00 00 00
0020004
$ md5sum /mnt/btrfs/foobar
b983fcefd4622a03a78936484c40272b /mnt/btrfs/foobar
Tested this change with zlib, lzo compression and file sizes larger
than 1GiB, and found no regression or other corruption issues (so far
at least).
Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
cmds-restore.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/cmds-restore.c b/cmds-restore.c
index e48df40320f6..9688599742d9 100644
--- a/cmds-restore.c
+++ b/cmds-restore.c
@@ -272,6 +272,7 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
u64 bytenr;
u64 ram_size;
u64 disk_size;
+ u64 num_bytes;
u64 length;
u64 size_left;
u64 dev_bytenr;
@@ -288,7 +289,9 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
disk_size = btrfs_file_extent_disk_num_bytes(leaf, fi);
ram_size = btrfs_file_extent_ram_bytes(leaf, fi);
offset = btrfs_file_extent_offset(leaf, fi);
- size_left = disk_size;
+ num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
+ size_left = num_bytes;
+ bytenr += offset;
if (offset)
printf("offset is %Lu\n", offset);
@@ -296,7 +299,7 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
if (disk_size == 0)
return 0;
- inbuf = malloc(disk_size);
+ inbuf = malloc(size_left);
if (!inbuf) {
fprintf(stderr, "No memory\n");
return -1;
@@ -351,8 +354,8 @@ again:
goto again;
if (compress == BTRFS_COMPRESS_NONE) {
- while (total < ram_size) {
- done = pwrite(fd, inbuf+total, ram_size-total,
+ while (total < num_bytes) {
+ done = pwrite(fd, inbuf+total, num_bytes-total,
pos+total);
if (done < 0) {
ret = -1;
@@ -365,7 +368,7 @@ again:
goto out;
}
- ret = decompress(inbuf, outbuf, disk_size, &ram_size, compress);
+ ret = decompress(inbuf, outbuf, num_bytes, &ram_size, compress);
if (ret) {
num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
bytenr, length);
--
1.8.3.1

View File

@ -0,0 +1,253 @@
From 6620f2caf5b50c28737eff1b522c22c153f9b1fa Mon Sep 17 00:00:00 2001
From: Anand Jain <anand.jain@oracle.com>
Date: Wed, 7 Aug 2013 20:11:25 +0800
Subject: [PATCH 58/62] btrfs-progs: avoid write to the disk before sure to
create fs
This patch provides fix for the following bug,
When mkfs.btrfs fails the disks shouldn't be written.
------------
btrfs fi show /dev/sdb
Label: none uuid: 60fb76f4-3b4d-4632-a7da-6a44dea5573d
Total devices 1 FS bytes used 24.00KiB
devid 1 size 2.00GiB used 20.00MiB path /dev/sdb
mkfs.btrfs -dsingle -mraid1 /dev/sdb -f
::
unable to create FS with metadata profile 16 (have 1 devices)
btrfs fi show /dev/sdb
Label: none uuid: 2da2179d-ecb1-4a4e-a44d-e7613a08c18d
Total devices 1 FS bytes used 24.00KiB
devid 1 size 2.00GiB used 20.00MiB path /dev/sdb
-------------
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
mkfs.c | 104 +++++++++++++++++++++++++---------------------------------------
utils.c | 41 +++++++++++++++++++++++++
utils.h | 2 ++
3 files changed, 84 insertions(+), 63 deletions(-)
diff --git a/mkfs.c b/mkfs.c
index 26be20df90d9..8a68f8a9f762 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -195,83 +195,28 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
int metadata_profile_opt, int mixed, int ssd)
{
u64 num_devices = btrfs_super_num_devices(root->fs_info->super_copy);
- u64 allowed = 0;
- u64 devices_for_raid = num_devices;
int ret;
- /*
- * Set default profiles according to number of added devices.
- * For mixed groups defaults are single/single.
- */
- if (!metadata_profile_opt && !mixed) {
- if (num_devices == 1 && ssd)
- printf("Detected a SSD, turning off metadata "
- "duplication. Mkfs with -m dup if you want to "
- "force metadata duplication.\n");
- metadata_profile = (num_devices > 1) ?
- BTRFS_BLOCK_GROUP_RAID1 : (ssd) ? 0: BTRFS_BLOCK_GROUP_DUP;
- }
- if (!data_profile_opt && !mixed) {
- data_profile = (num_devices > 1) ?
- BTRFS_BLOCK_GROUP_RAID0 : 0; /* raid0 or single */
- }
-
- if (devices_for_raid > 4)
- devices_for_raid = 4;
-
- switch (devices_for_raid) {
- default:
- case 4:
- allowed |= BTRFS_BLOCK_GROUP_RAID10;
- case 3:
- allowed |= BTRFS_BLOCK_GROUP_RAID6;
- case 2:
- allowed |= BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
- BTRFS_BLOCK_GROUP_RAID5;
- break;
- case 1:
- allowed |= BTRFS_BLOCK_GROUP_DUP;
- }
-
- if (metadata_profile & ~allowed) {
- fprintf(stderr, "unable to create FS with metadata "
- "profile %llu (have %llu devices)\n", metadata_profile,
- num_devices);
- exit(1);
- }
- if (data_profile & ~allowed) {
- fprintf(stderr, "unable to create FS with data "
- "profile %llu (have %llu devices)\n", data_profile,
- num_devices);
- exit(1);
- }
-
- /* allow dup'ed data chunks only in mixed mode */
- if (!mixed && (data_profile & BTRFS_BLOCK_GROUP_DUP)) {
- fprintf(stderr, "dup for data is allowed only in mixed mode\n");
- exit(1);
- }
-
- if (allowed & metadata_profile) {
+ if (metadata_profile) {
u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA;
ret = create_one_raid_group(trans, root,
BTRFS_BLOCK_GROUP_SYSTEM |
- (allowed & metadata_profile));
+ metadata_profile);
BUG_ON(ret);
if (mixed)
meta_flags |= BTRFS_BLOCK_GROUP_DATA;
ret = create_one_raid_group(trans, root, meta_flags |
- (allowed & metadata_profile));
+ metadata_profile);
BUG_ON(ret);
}
- if (!mixed && num_devices > 1 && (allowed & data_profile)) {
+ if (!mixed && num_devices > 1 && data_profile) {
ret = create_one_raid_group(trans, root,
BTRFS_BLOCK_GROUP_DATA |
- (allowed & data_profile));
+ data_profile);
BUG_ON(ret);
}
recow_roots(trans, root);
@@ -1362,14 +1307,48 @@ int main(int ac, char **av)
}
}
- /* if we are here that means all devs are good to btrfsify */
optind = saved_optind;
dev_cnt = ac - optind;
+ file = av[optind++];
+ ssd = is_ssd(file);
+
+ /*
+ * Set default profiles according to number of added devices.
+ * For mixed groups defaults are single/single.
+ */
+ if (!mixed) {
+ if (!metadata_profile_opt) {
+ if (dev_cnt == 1 && ssd)
+ printf("Detected a SSD, turning off metadata "
+ "duplication. Mkfs with -m dup if you want to "
+ "force metadata duplication.\n");
+
+ metadata_profile = (dev_cnt > 1) ?
+ BTRFS_BLOCK_GROUP_RAID1 : (ssd) ?
+ 0: BTRFS_BLOCK_GROUP_DUP;
+ }
+ if (!data_profile_opt) {
+ data_profile = (dev_cnt > 1) ?
+ BTRFS_BLOCK_GROUP_RAID0 : 0; /* raid0 or single */
+ }
+ } else {
+ /* this is not needed but just for completeness */
+ metadata_profile = 0;
+ data_profile = 0;
+ }
+
+ ret = test_num_disk_vs_raid(metadata_profile, data_profile,
+ dev_cnt, mixed, estr);
+ if (ret) {
+ fprintf(stderr, "Error: %s\n", estr);
+ exit(1);
+ }
+
+ /* if we are here that means all devs are good to btrfsify */
printf("\nWARNING! - %s IS EXPERIMENTAL\n", BTRFS_BUILD_VERSION);
printf("WARNING! - see http://btrfs.wiki.kernel.org before using\n\n");
- file = av[optind++];
dev_cnt--;
if (!source_dir_set) {
@@ -1412,7 +1391,6 @@ int main(int ac, char **av)
dev_block_count = block_count;
}
- ssd = is_ssd(file);
if (mixed) {
if (metadata_profile != data_profile) {
diff --git a/utils.c b/utils.c
index 6c1a96f2032f..b2c6a06ffaa5 100644
--- a/utils.c
+++ b/utils.c
@@ -1766,6 +1766,47 @@ out:
return ret;
}
+int test_num_disk_vs_raid(u64 metadata_profile, u64 data_profile,
+ u64 dev_cnt, int mixed, char *estr)
+{
+ size_t sz = 100;
+ u64 allowed = 0;
+
+ switch (dev_cnt) {
+ default:
+ case 4:
+ allowed |= BTRFS_BLOCK_GROUP_RAID10;
+ case 3:
+ allowed |= BTRFS_BLOCK_GROUP_RAID6;
+ case 2:
+ allowed |= BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
+ BTRFS_BLOCK_GROUP_RAID5;
+ break;
+ case 1:
+ allowed |= BTRFS_BLOCK_GROUP_DUP;
+ }
+
+ if (metadata_profile & ~allowed) {
+ snprintf(estr, sz, "unable to create FS with metadata "
+ "profile %llu (have %llu devices)\n",
+ metadata_profile, dev_cnt);
+ return 1;
+ }
+ if (data_profile & ~allowed) {
+ snprintf(estr, sz, "unable to create FS with data "
+ "profile %llu (have %llu devices)\n",
+ metadata_profile, dev_cnt);
+ return 1;
+ }
+
+ if (!mixed && (data_profile & BTRFS_BLOCK_GROUP_DUP)) {
+ snprintf(estr, sz,
+ "dup for data is allowed only in mixed mode");
+ return 1;
+ }
+ return 0;
+}
+
/* Check if disk is suitable for btrfs
* returns:
* 1: something is wrong, estr provides the error
diff --git a/utils.h b/utils.h
index 3c17e14b79cd..720601723413 100644
--- a/utils.h
+++ b/utils.h
@@ -65,5 +65,7 @@ u64 btrfs_device_size(int fd, struct stat *st);
/* Helper to always get proper size of the destination string */
#define strncpy_null(dest, src) __strncpy__null(dest, src, sizeof(dest))
int test_dev_for_mkfs(char *file, int force_overwrite, char *estr);
+int test_num_disk_vs_raid(u64 metadata_profile, u64 data_profile,
+ u64 dev_cnt, int mixed, char *estr);
#endif
--
1.8.3.1

View File

@ -0,0 +1,46 @@
From 684d9a33f77967a9b50b597cece1b2b2e29d2b8d Mon Sep 17 00:00:00 2001
From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Date: Thu, 5 Sep 2013 15:53:34 +0900
Subject: [PATCH 59/62] btrfs-progs: error if device for mkfs is too small
Eric pointed out that mkfs abort if specified volume is too small:
# truncate --size=2m testfile
# ./mkfs.btrfs testfile
:
SMALL VOLUME: forcing mixed metadata/data groups
mkfs.btrfs: volumes.c:852: btrfs_alloc_chunk: Assertion `!(ret)' failed.
Aborted (core dumped)
As the first step to fix problems around there, let mkfs to report
error if the size of target volume is less than the size of the first
system block group, BTRFS_MKFS_SYSTEM_GROUP_SIZE (= 4MB).
Reported-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
mkfs.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/mkfs.c b/mkfs.c
index 8a68f8a9f762..9a017c1dc95b 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -1400,6 +1400,12 @@ int main(int ac, char **av)
}
}
+ /* To create the first block group and chunk 0 in make_btrfs */
+ if (dev_block_count < BTRFS_MKFS_SYSTEM_GROUP_SIZE) {
+ fprintf(stderr, "device is too small to make filesystem\n");
+ exit(1);
+ }
+
blocks[0] = BTRFS_SUPER_INFO_OFFSET;
for (i = 1; i < 7; i++) {
blocks[i] = BTRFS_SUPER_INFO_OFFSET + 1024 * 1024 +
--
1.8.3.1

View File

@ -0,0 +1,91 @@
From b11f9613e3b0be7e4b560419a4fec7d7d7264664 Mon Sep 17 00:00:00 2001
From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Date: Thu, 5 Sep 2013 15:55:08 +0900
Subject: [PATCH 60/62] btrfs-progs: error if device have no space to make
primary chunks
The previous patch works fine if the size of specified volume to mkfs
is less than 4MB. However usually btrfs requires more than 4MB to work,
and the minimum preferred size is depending on the raid setting etc.
This patch let mkfs print error message if it cannot allocate one of
chunks should be there at first.
[before]
# truncate --size=4500K testfile
# ./mkfs.btrfs -f testfile
:
SMALL VOLUME: forcing mixed metadata/data groups
mkfs.btrfs: mkfs.c:84: make_root_dir: Assertion `!(ret)' failed.
Aborted (core dumped)
[After]
# truncate --size=4500K testfile
# ./mkfs.btrfs -f testfile
:
SMALL VOLUME: forcing mixed metadata/data groups
no space to alloc data/metadata chunk
failed to setup the root directory
TBD is calculate minimum size for setting and put it in the error
message to let user know how large amount of volume is required.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
mkfs.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/mkfs.c b/mkfs.c
index 9a017c1dc95b..f7105073a173 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -81,6 +81,11 @@ static int make_root_dir(struct btrfs_root *root, int mixed)
&chunk_start, &chunk_size,
BTRFS_BLOCK_GROUP_METADATA |
BTRFS_BLOCK_GROUP_DATA);
+ if (ret == -ENOSPC) {
+ fprintf(stderr,
+ "no space to alloc data/metadata chunk\n");
+ goto err;
+ }
BUG_ON(ret);
ret = btrfs_make_block_group(trans, root, 0,
BTRFS_BLOCK_GROUP_METADATA |
@@ -93,6 +98,10 @@ static int make_root_dir(struct btrfs_root *root, int mixed)
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
&chunk_start, &chunk_size,
BTRFS_BLOCK_GROUP_METADATA);
+ if (ret == -ENOSPC) {
+ fprintf(stderr, "no space to alloc metadata chunk\n");
+ goto err;
+ }
BUG_ON(ret);
ret = btrfs_make_block_group(trans, root, 0,
BTRFS_BLOCK_GROUP_METADATA,
@@ -110,6 +119,10 @@ static int make_root_dir(struct btrfs_root *root, int mixed)
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
&chunk_start, &chunk_size,
BTRFS_BLOCK_GROUP_DATA);
+ if (ret == -ENOSPC) {
+ fprintf(stderr, "no space to alloc data chunk\n");
+ goto err;
+ }
BUG_ON(ret);
ret = btrfs_make_block_group(trans, root, 0,
BTRFS_BLOCK_GROUP_DATA,
@@ -181,6 +194,10 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,
ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
&chunk_start, &chunk_size, type);
+ if (ret == -ENOSPC) {
+ fprintf(stderr, "not enough free space\n");
+ exit(1);
+ }
BUG_ON(ret);
ret = btrfs_make_block_group(trans, root->fs_info->extent_root, 0,
type, BTRFS_FIRST_CHUNK_TREE_OBJECTID,
--
1.8.3.1

View File

@ -0,0 +1,233 @@
From db3c0b4f365acb5ee9fa7e37d440b2ef6ff5636c Mon Sep 17 00:00:00 2001
From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Date: Thu, 5 Sep 2013 15:57:19 +0900
Subject: [PATCH 61/62] btrfs-progs: calculate available blocks on device
properly
I found that mkfs.btrfs aborts when assigned multi volumes contain
a small volume:
# parted /dev/sdf p
Model: LSI MegaRAID SAS RMB (scsi)
Disk /dev/sdf: 72.8GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 32.3kB 72.4GB 72.4GB primary
2 72.4GB 72.8GB 461MB primary
# ./mkfs.btrfs -f /dev/sdf1 /dev/sdf2
:
SMALL VOLUME: forcing mixed metadata/data groups
adding device /dev/sdf2 id 2
mkfs.btrfs: volumes.c:852: btrfs_alloc_chunk: Assertion `!(ret)' failed.
Aborted (core dumped)
This failure of btrfs_alloc_chunk was caused by following steps:
1) since there is only small space in the small device, mkfs was
going to allocate a chunk from free space as much as available.
So mkfs called btrfs_alloc_chunk with
size = device->total_bytes - device->used_bytes.
2) (According to the comment in source code, to avoid overwriting
superblock,) btrfs_alloc_chunk starts taking chunks at an offset
of 1MB. It means that the layout of a disk will be like:
[[1MB at beginning for sb][allocated chunks]* ... free space ... ]
and you can see that the available free space for allocation is:
avail = device->total_bytes - device->used_bytes - 1MB.
3) Therefore there is only free space 1MB less than requested. damn.
>From further investigations I also found that this issue is easily
reproduced by using -A, --alloc-start option:
# truncate --size=1G testfile
# ./mkfs.btrfs -A900M -f testfile
:
mkfs.btrfs: volumes.c:852: btrfs_alloc_chunk: Assertion `!(ret)' failed.
Aborted (core dumped)
In this case there is only 100MB for allocation but btrfs_alloc_chunk
was going to allocate more than the 100MB.
The root cause of both of above troubles is a same simple bug:
btrfs_chunk_alloc does not calculate available bytes properly even
though it researches how many devices have enough room to have a
chunk to be allocated.
So this patch introduces new function btrfs_device_avail_bytes()
which returns available bytes for allocation in specified device.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
ctree.h | 8 +++++
volumes.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 106 insertions(+), 6 deletions(-)
diff --git a/ctree.h b/ctree.h
index 0b0d701fe679..90be7abe9ebf 100644
--- a/ctree.h
+++ b/ctree.h
@@ -811,6 +811,14 @@ struct btrfs_csum_item {
u8 csum;
} __attribute__ ((__packed__));
+/*
+ * We don't want to overwrite 1M at the beginning of device, even though
+ * there is our 1st superblock at 64k. Some possible reasons:
+ * - the first 64k blank is useful for some boot loader/manager
+ * - the first 1M could be scratched by buggy partitioner or somesuch
+ */
+#define BTRFS_BLOCK_RESERVED_1M_FOR_SUPER ((u64)1024 * 1024)
+
/* tag for the radix tree of block groups in ram */
#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0)
#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1)
diff --git a/volumes.c b/volumes.c
index 0ff22833d6be..e8d7f258dddb 100644
--- a/volumes.c
+++ b/volumes.c
@@ -268,7 +268,7 @@ static int find_free_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_dev_extent *dev_extent = NULL;
u64 hole_size = 0;
u64 last_byte = 0;
- u64 search_start = 0;
+ u64 search_start = root->fs_info->alloc_start;
u64 search_end = device->total_bytes;
int ret;
int slot = 0;
@@ -283,10 +283,12 @@ static int find_free_dev_extent(struct btrfs_trans_handle *trans,
/* we don't want to overwrite the superblock on the drive,
* so we make sure to start at an offset of at least 1MB
*/
- search_start = max((u64)1024 * 1024, search_start);
+ search_start = max(BTRFS_BLOCK_RESERVED_1M_FOR_SUPER, search_start);
- if (root->fs_info->alloc_start + num_bytes <= device->total_bytes)
- search_start = max(root->fs_info->alloc_start, search_start);
+ if (search_start >= search_end) {
+ ret = -ENOSPC;
+ goto error;
+ }
key.objectid = device->devid;
key.offset = search_start;
@@ -660,6 +662,94 @@ static u32 find_raid56_stripe_len(u32 data_devices, u32 dev_stripe_target)
return 64 * 1024;
}
+/*
+ * btrfs_device_avail_bytes - count bytes available for alloc_chunk
+ *
+ * It is not equal to "device->total_bytes - device->bytes_used".
+ * We do not allocate any chunk in 1M at beginning of device, and not
+ * allowed to allocate any chunk before alloc_start if it is specified.
+ * So search holes from max(1M, alloc_start) to device->total_bytes.
+ */
+static int btrfs_device_avail_bytes(struct btrfs_trans_handle *trans,
+ struct btrfs_device *device,
+ u64 *avail_bytes)
+{
+ struct btrfs_path *path;
+ struct btrfs_root *root = device->dev_root;
+ struct btrfs_key key;
+ struct btrfs_dev_extent *dev_extent = NULL;
+ struct extent_buffer *l;
+ u64 search_start = root->fs_info->alloc_start;
+ u64 search_end = device->total_bytes;
+ u64 extent_end = 0;
+ u64 free_bytes = 0;
+ int ret;
+ int slot = 0;
+
+ search_start = max(BTRFS_BLOCK_RESERVED_1M_FOR_SUPER, search_start);
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+
+ key.objectid = device->devid;
+ key.offset = root->fs_info->alloc_start;
+ key.type = BTRFS_DEV_EXTENT_KEY;
+
+ path->reada = 2;
+ ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
+ if (ret < 0)
+ goto error;
+ ret = btrfs_previous_item(root, path, 0, key.type);
+ if (ret < 0)
+ goto error;
+
+ while (1) {
+ l = path->nodes[0];
+ slot = path->slots[0];
+ if (slot >= btrfs_header_nritems(l)) {
+ ret = btrfs_next_leaf(root, path);
+ if (ret == 0)
+ continue;
+ if (ret < 0)
+ goto error;
+ break;
+ }
+ btrfs_item_key_to_cpu(l, &key, slot);
+
+ if (key.objectid < device->devid)
+ goto next;
+ if (key.objectid > device->devid)
+ break;
+ if (btrfs_key_type(&key) != BTRFS_DEV_EXTENT_KEY)
+ goto next;
+ if (key.offset > search_end)
+ break;
+ if (key.offset > search_start)
+ free_bytes += key.offset - search_start;
+
+ dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent);
+ extent_end = key.offset + btrfs_dev_extent_length(l,
+ dev_extent);
+ if (extent_end > search_start)
+ search_start = extent_end;
+ if (search_start > search_end)
+ break;
+next:
+ path->slots[0]++;
+ cond_resched();
+ }
+
+ if (search_start < search_end)
+ free_bytes += search_end - search_start;
+
+ *avail_bytes = free_bytes;
+ ret = 0;
+error:
+ btrfs_free_path(path);
+ return ret;
+}
+
int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
struct btrfs_root *extent_root, u64 *start,
u64 *num_bytes, u64 type)
@@ -678,7 +768,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
u64 calc_size = 8 * 1024 * 1024;
u64 min_free;
u64 max_chunk_size = 4 * calc_size;
- u64 avail;
+ u64 avail = 0;
u64 max_avail = 0;
u64 percent_max;
int num_stripes = 1;
@@ -782,7 +872,9 @@ again:
/* build a private list of devices we will allocate from */
while(index < num_stripes) {
device = list_entry(cur, struct btrfs_device, dev_list);
- avail = device->total_bytes - device->bytes_used;
+ ret = btrfs_device_avail_bytes(trans, device, &avail);
+ if (ret)
+ return ret;
cur = cur->next;
if (avail >= min_free) {
list_move_tail(&device->dev_list, &private_devs);
--
1.8.3.1

View File

@ -0,0 +1,228 @@
From 174273941f266c5ba71da02cc4d71a95ca41bc20 Mon Sep 17 00:00:00 2001
From: Josef Bacik <jbacik@fusionio.com>
Date: Tue, 1 Oct 2013 09:00:19 -0400
Subject: [PATCH 62/62] Btrfs-progs: keep track of transid failures and fix
them if possible
A user was reporting an issue with bad transid errors on his blocks. The thing
is that btrfs-progs will ignore transid failures for things like restore and
fsck so we can do a best effort to fix a users file system. So fsck can put
together a coherent view of the file system with stale blocks. So if everything
else is ok in the mind of fsck then we can recow these blocks to fix the
generation and the user can get their file system back. Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
---
cmds-check.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ctree.c | 7 ++++++-
ctree.h | 1 +
disk-io.c | 15 +++++++++++++++
extent_io.c | 2 ++
extent_io.h | 2 ++
6 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/cmds-check.c b/cmds-check.c
index dbb41e5a4d5b..924aac08f350 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -5675,6 +5675,47 @@ static int reinit_extent_tree(struct btrfs_fs_info *fs_info)
return btrfs_commit_transaction(trans, fs_info->extent_root);
}
+static int recow_extent_buffer(struct btrfs_root *root, struct extent_buffer *eb)
+{
+ struct btrfs_path *path;
+ struct btrfs_trans_handle *trans;
+ struct btrfs_key key;
+ int ret;
+
+ printf("Recowing metadata block %llu\n", eb->start);
+ key.objectid = btrfs_header_owner(eb);
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = (u64)-1;
+
+ root = btrfs_read_fs_root(root->fs_info, &key);
+ if (IS_ERR(root)) {
+ fprintf(stderr, "Couldn't find owner root %llu\n",
+ key.objectid);
+ return PTR_ERR(root);
+ }
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+
+ trans = btrfs_start_transaction(root, 1);
+ if (IS_ERR(trans)) {
+ btrfs_free_path(path);
+ return PTR_ERR(trans);
+ }
+
+ path->lowest_level = btrfs_header_level(eb);
+ if (path->lowest_level)
+ btrfs_node_key_to_cpu(eb, &key, 0);
+ else
+ btrfs_item_key_to_cpu(eb, &key, 0);
+
+ ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
+ btrfs_commit_transaction(trans, root);
+ btrfs_free_path(path);
+ return ret;
+}
+
static struct option long_options[] = {
{ "super", 1, NULL, 's' },
{ "repair", 0, NULL, 0 },
@@ -5826,6 +5867,23 @@ int cmd_check(int argc, char **argv)
fprintf(stderr, "checking root refs\n");
ret = check_root_refs(root, &root_cache);
+ if (ret)
+ goto out;
+
+ while (repair && !list_empty(&root->fs_info->recow_ebs)) {
+ struct extent_buffer *eb;
+
+ eb = list_first_entry(&root->fs_info->recow_ebs,
+ struct extent_buffer, recow);
+ ret = recow_extent_buffer(root, eb);
+ if (ret)
+ break;
+ }
+
+ if (!list_empty(&root->fs_info->recow_ebs)) {
+ fprintf(stderr, "Transid errors in file system\n");
+ ret = 1;
+ }
out:
free_root_recs_tree(&root_cache);
close_ctree(root);
diff --git a/ctree.c b/ctree.c
index 1a4f3f06f38a..e7ccfa03fb0e 100644
--- a/ctree.c
+++ b/ctree.c
@@ -346,7 +346,8 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
(unsigned long)btrfs_header_fsid(cow),
BTRFS_FSID_SIZE);
- WARN_ON(btrfs_header_generation(buf) > trans->transid);
+ WARN_ON(!(buf->flags & EXTENT_BAD_TRANSID) &&
+ btrfs_header_generation(buf) > trans->transid);
update_ref_for_cow(trans, root, buf, cow);
@@ -370,6 +371,10 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
btrfs_free_extent(trans, root, buf->start, buf->len,
0, root->root_key.objectid, level, 1);
}
+ if (!list_empty(&buf->recow)) {
+ list_del_init(&buf->recow);
+ free_extent_buffer(buf);
+ }
free_extent_buffer(buf);
btrfs_mark_buffer_dirty(cow);
*cow_ret = cow;
diff --git a/ctree.h b/ctree.h
index 90be7abe9ebf..61cd93b91937 100644
--- a/ctree.h
+++ b/ctree.h
@@ -952,6 +952,7 @@ struct btrfs_fs_info {
struct btrfs_extent_ops *extent_ops;
struct list_head dirty_cowonly_roots;
+ struct list_head recow_ebs;
struct btrfs_fs_devices *fs_devices;
struct list_head space_info;
diff --git a/disk-io.c b/disk-io.c
index 1b91de6fc90d..d97ff8c706c9 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -180,6 +180,7 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
(unsigned long long)parent_transid,
(unsigned long long)btrfs_header_generation(eb));
if (ignore) {
+ eb->flags |= EXTENT_BAD_TRANSID;
printk("Ignoring transid failure\n");
return 0;
}
@@ -274,6 +275,12 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
csum_tree_block(root, eb, 1) == 0 &&
verify_parent_transid(eb->tree, eb, parent_transid, ignore)
== 0) {
+ if (eb->flags & EXTENT_BAD_TRANSID &&
+ list_empty(&eb->recow)) {
+ list_add_tail(&eb->recow,
+ &root->fs_info->recow_ebs);
+ eb->refs++;
+ }
btrfs_set_buffer_uptodate(eb);
return eb;
}
@@ -748,6 +755,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
mutex_init(&fs_info->fs_mutex);
INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
INIT_LIST_HEAD(&fs_info->space_info);
+ INIT_LIST_HEAD(&fs_info->recow_ebs);
if (!writable)
fs_info->readonly = 1;
@@ -899,6 +907,13 @@ FREE_EXTENT_CACHE_BASED_TREE(mapping_cache, free_map_lookup);
void btrfs_cleanup_all_caches(struct btrfs_fs_info *fs_info)
{
+ while (!list_empty(&fs_info->recow_ebs)) {
+ struct extent_buffer *eb;
+ eb = list_first_entry(&fs_info->recow_ebs,
+ struct extent_buffer, recow);
+ list_del_init(&eb->recow);
+ free_extent_buffer(eb);
+ }
free_mapping_cache_tree(&fs_info->mapping_tree.cache_tree);
extent_io_tree_cleanup(&fs_info->extent_cache);
extent_io_tree_cleanup(&fs_info->free_space_cache);
diff --git a/extent_io.c b/extent_io.c
index 464bd07e8d1a..398ee26b4a79 100644
--- a/extent_io.c
+++ b/extent_io.c
@@ -585,6 +585,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
eb->dev_bytenr = (u64)-1;
eb->cache_node.start = bytenr;
eb->cache_node.size = blocksize;
+ INIT_LIST_HEAD(&eb->recow);
free_some_buffers(tree);
ret = insert_cache_extent(&tree->cache, &eb->cache_node);
@@ -608,6 +609,7 @@ void free_extent_buffer(struct extent_buffer *eb)
struct extent_io_tree *tree = eb->tree;
BUG_ON(eb->flags & EXTENT_DIRTY);
list_del_init(&eb->lru);
+ list_del_init(&eb->recow);
remove_cache_extent(&tree->cache, &eb->cache_node);
BUG_ON(tree->cache_size < eb->len);
tree->cache_size -= eb->len;
diff --git a/extent_io.h b/extent_io.h
index 2604dcef31e3..45080c2661ae 100644
--- a/extent_io.h
+++ b/extent_io.h
@@ -39,6 +39,7 @@
#define EXTENT_DEFRAG_DONE (1 << 7)
#define EXTENT_BUFFER_FILLED (1 << 8)
#define EXTENT_CSUM (1 << 9)
+#define EXTENT_BAD_TRANSID (1 << 10)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
#define BLOCK_GROUP_DATA EXTENT_WRITEBACK
@@ -72,6 +73,7 @@ struct extent_buffer {
u32 len;
struct extent_io_tree *tree;
struct list_head lru;
+ struct list_head recow;
int refs;
int flags;
int fd;
--
1.8.3.1

View File

@ -1,3 +1,10 @@
-------------------------------------------------------------------
Thu Oct 31 01:05:56 CET 2013 - dsterba@suse.cz
- fsck updates
- more mkfs sanity checks
- qgroup rescan wait
-------------------------------------------------------------------
Fri Oct 4 20:16:02 UTC 2013 - rgoldwyn@suse.com

View File

@ -35,6 +35,19 @@ Patch10: 0010-Btrfs-progs-make-btrfsck-a-hardlink-at-install-time.patch
Patch12: 0012-libbtrfs-Set-SONAME-to-libbtrfs.so.0-instead-of-libb.patch
Patch40: 0040-btrfs-progs-fix-loop-device-mount-checks.patch
Patch1: btrfs-progs-mkfs-default-extref.diff
Patch50: 0050-Btrfs-progs-commit-the-csum_root-if-we-do-init-csum-.patch
Patch51: 0051-btrfs-progs-Fix-getopt-on-arm-ppc-platforms.patch
Patch52: 0052-btrfs-progs-fix-duplicate-__-su-typedefs-on-ppc64.patch
Patch53: 0053-btrfs-progs-use-reentrant-localtime.patch
Patch54: 0054-btrfs-progs-don-t-have-to-report-ENOMEDIUM-error-dur.patch
Patch55: 0055-Btrfs-progs-added-btrfs-quota-rescan-w-switch-wait.patch
Patch56: 0056-btrfs-progs-fix-qgroup-realloc-inheritance.patch
Patch57: 0057-Btrfs-progs-fix-restore-command-leaving-corrupted-fi.patch
Patch58: 0058-btrfs-progs-avoid-write-to-the-disk-before-sure-to-c.patch
Patch59: 0059-btrfs-progs-error-if-device-for-mkfs-is-too-small.patch
Patch60: 0060-btrfs-progs-error-if-device-have-no-space-to-make-pr.patch
Patch61: 0061-btrfs-progs-calculate-available-blocks-on-device-pro.patch
Patch62: 0062-Btrfs-progs-keep-track-of-transid-failures-and-fix-t.patch
Patch1000: local-version-override.patch
Patch1001: btrfs-progs-use-IEEE1541-suffixes-for-sizes.patch
Patch1002: btrfs-progs-add-man-page-for-btrfs-convert.patch
@ -83,6 +96,19 @@ build applications to interface with btrfs.
%patch1001 -p1
%patch1002 -p1
%patch1003 -p1
%patch50 -p1
%patch51 -p1
%patch52 -p1
%patch53 -p1
%patch54 -p1
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch60 -p1
%patch61 -p1
%patch62 -p1
%build
make %{?_smp_mflags} CFLAGS="%{optflags}" all btrfs-convert \

View File

@ -7,7 +7,7 @@ Index: btrfs-progs-v0.19-116-g13eced9/version.sh
# Released under the GNU GPLv2
-v="v0.20-rc1"
+v="v0.20-rc1+20130701"
+v="v0.20-rc1+20131031"
which git &> /dev/null
if [ $? == 0 -a -d .git ]; then