memory allocated by device_list_add has to be freed, the
function introduced here device_list_remove() would just
go that.
however the challenging part is about where we would
call this function.
there are two ways its handled
the threads calling open_ctree_broken(), open_ctree() and
open_ctree_fd() (which leads call to device_list_add)
would anyway call close_ctree() so we put device_list_remove()
there which will take care of freeing memory.
now for threads calling device_list_add() outside of
open_ctree(), has to call device_list_remove() separately
which can be called as a last function in the thread
this patch just does that.
device_list_remove accepts() NULL (deletes entire list)
or fsid (which would delete only the fsid matched in the
device_fs list). As of now though all calling functions
use NULL, I see potential that we would use fsid when we
have to create a single device list using both the
device-tree and from the btrfs-kernel.
further, mkfs.c thread should call device_list_remove()
as well, however mkfs.c uses a lot of in-flight exits()
which makes it very difficult to bring in this fix into
mkfs.c. I shall be doing it in a separate patch.
Signed-off-by: Anand Jain <anand.jain@xxxxxxxxxx>
---
cmds-device.c | 4 +++
cmds-filesystem.c | 11 ++++++++-
cmds-replace.c | 2 +
cmds-scrub.c | 3 ++
disk-io.c | 1 +
mkfs.c | 1 +
utils.h | 1 +
volumes.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
volumes.h | 3 ++
9 files changed, 79 insertions(+), 3 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index 9525fcf..e4a1f1b 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -29,6 +29,7 @@
#include "utils.h"
#include "commands.h"
+#include "volumes.h"
/* FIXME - imported cruft, fix sparse errors and warnings */
#ifdef __CHECKER__
@@ -128,6 +129,7 @@ static int cmd_add_dev(int argc, char **argv)
}
close(fdmnt);
+ device_list_remove(NULL);
if (ret)
return ret+20;
else
@@ -213,6 +215,7 @@ static int cmd_scan_dev(int argc, char **argv)
int ret;
printf("Scanning for Btrfs filesystems\n");
ret = scan_for_btrfs(where, 1);
+ device_list_remove(NULL);
if (ret){
fprintf(stderr, "ERROR: error %d while scanning\n", ret);
return 18;
@@ -397,6 +400,7 @@ static int cmd_dev_stats(int argc, char **argv)
out:
free(di_args);
close(fdmnt);
+ device_list_remove(NULL);
return err;
}
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index a028e1d..1c26476 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -455,6 +455,7 @@ static int cmd_show(int argc, char **argv)
print_one_uuid(fs_devices);
}
printf("%s\n", BTRFS_BUILD_VERSION);
+ device_list_remove(NULL);
return 0;
}
@@ -683,13 +684,19 @@ static const char * const cmd_label_usage[] = {
static int cmd_label(int argc, char **argv)
{
+ int ret;
if (check_argc_min(argc, 2) || check_argc_max(argc, 3))
usage(cmd_label_usage);
if (argc > 2)
- return set_label(argv[1], argv[2]);
+ ret = set_label(argv[1], argv[2]);
else
- return get_label(argv[1]);
+ ret = get_label(argv[1]);
+
+ if (is_existing_blk_or_reg_file(argv[1]))
+ device_list_remove(NULL);
+
+ return ret;
}
const struct cmd_group filesystem_cmd_group = {
diff --git a/cmds-replace.c b/cmds-replace.c
index c68986a..99a5abc 100644
--- a/cmds-replace.c
+++ b/cmds-replace.c
@@ -340,6 +340,7 @@ static int cmd_start_replace(int argc, char **argv)
}
}
close(fdmnt);
+ device_list_remove(NULL);
return 0;
leave_with_error:
@@ -349,6 +350,7 @@ leave_with_error:
close(fdsrcdev);
if (fddstdev != -1)
close(fddstdev);
+ device_list_remove(NULL);
return -1;
}
diff --git a/cmds-scrub.c b/cmds-scrub.c
index 95dfee3..08aab54 100644
--- a/cmds-scrub.c
+++ b/cmds-scrub.c
@@ -1496,6 +1496,7 @@ out:
unlink(sock_path);
}
close(fdmnt);
+ device_list_remove(NULL);
if (err)
return 1;
@@ -1564,6 +1565,7 @@ static int cmd_scrub_cancel(int argc, char **argv)
out:
if (fdmnt != -1)
close(fdmnt);
+ device_list_remove(NULL);
return ret;
}
@@ -1722,6 +1724,7 @@ out:
free(di_args);
if (fdres > -1)
close(fdres);
+ device_list_remove(NULL);
return err;
}
diff --git a/disk-io.c b/disk-io.c
index 3937e3f..9b72576 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -1338,6 +1338,7 @@ int close_ctree(struct btrfs_root *root)
}
close_all_devices(fs_info);
+ device_list_remove(NULL);
free_mapping_cache(fs_info);
extent_io_tree_cleanup(&fs_info->extent_cache);
extent_io_tree_cleanup(&fs_info->free_space_cache);
diff --git a/mkfs.c b/mkfs.c
index 95fceb3..5d131dd 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -1461,6 +1461,7 @@ int main(int ac, char **av)
if (is_block_device(file))
if (test_dev_for_mkfs(file, force_overwrite, estr)) {
fprintf(stderr, "Error: %s", estr);
+ device_list_remove(NULL);
exit(1);
}
}
diff --git a/utils.h b/utils.h
index 1fa1c5a..f5b03a7 100644
--- a/utils.h
+++ b/utils.h
@@ -70,4 +70,5 @@ u64 btrfs_device_size(int fd, struct stat *st);
int test_dev_for_mkfs(char *file, int force_overwrite, char *estr);
int scan_for_btrfs(int where, int update_kernel);
int get_label_mounted(const char *mount_path, char *labelp);
+int is_existing_blk_or_reg_file(const char* filename);
#endif
diff --git a/volumes.c b/volumes.c
index 00c384a..fa27055 100644
--- a/volumes.c
+++ b/volumes.c
@@ -87,7 +87,7 @@ static struct btrfs_fs_devices *find_fsid(u8 *fsid)
return NULL;
}
-static int device_list_add(const char *path,
+int device_list_add(const char *path,
struct btrfs_super_block *disk_super,
u64 devid, struct btrfs_fs_devices **fs_devices_ret)
{
@@ -155,6 +155,60 @@ static int device_list_add(const char *path,
return 0;
}
+/* This will remove given fsid and it devices from the list,
+ * or when arg is NULL it will delete all.
+ */
+int device_list_remove(u8 *fsid)
+{
+ struct list_head *fsids;
+ struct list_head *cur_fsid;
+ struct btrfs_fs_devices *fs_devices;
+ struct list_head *cur_dev;
+ struct btrfs_device *device;
+ int del = 1;
+
+ fsids = btrfs_scanned_uuids();
+ list_for_each(cur_fsid, fsids) {
+ fs_devices = list_entry(cur_fsid, struct btrfs_fs_devices,
+ list);
+ if (fsid && memcmp(fs_devices->fsid, fsid, BTRFS_FSID_SIZE))
+ continue;
+
+ /* first check if all devs are closed before remove */
+ list_for_each(cur_dev, &fs_devices->devices) {
+ device = list_entry(cur_dev,
+ struct btrfs_device, dev_list);
+ if (device->fd > 0) {
+ fprintf(stderr, "attempted to remove device "\
+ "list without closing\n");
+ if (fsid)
+ return 1;
+ else {
+ del = 0;
+ break;
+ }
+ }
+ }
+
+ if (del) {
+ list_for_each(cur_dev, &fs_devices->devices) {
+ device = list_entry(cur_dev,
+ struct btrfs_device, dev_list);
+ list_del(&device->dev_list);
+ if (device->name)
+ kfree(device->name);
+ if (device->label)
+ kfree(device->label);
+ kfree(device);
+ }
+ list_del(&fs_devices->list);
+ kfree(fs_devices);
+ }
+ del = 1;
+ }
+ return 0;
+}
+
int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
{
struct btrfs_fs_devices *seed_devices;
diff --git a/volumes.h b/volumes.h
index 911f788..55a0b71 100644
--- a/volumes.h
+++ b/volumes.h
@@ -190,4 +190,7 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);
struct btrfs_device *btrfs_find_device_by_devid(struct btrfs_root *root,
u64 devid, int instance);
+int device_list_add(const char *path, struct btrfs_super_block *disk_super,
+ u64 devid, struct btrfs_fs_devices **fs_devices_ret);
+int device_list_remove(u8 *fsid);
#endif
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html