Fix ZFS memory and resource leaks.

* grub-core/fs/zfs/zfs.c (fill_vdev_info_real): New paramter inserted.
	All users updated.
	Free type on exit.
	(fill_vdev_info): New parameter inserted. All users updated.
	(check_pool_label): Likewise.
	(scan_disk): Likewise.
	(scan_devices): Close non-inserted disks.
	(fzap_iterate): Free l.
	(unmount_device): Free children descripto memory.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-11-10 08:38:06 +01:00
parent ad9a2f44b4
commit 45bd824d2e
2 changed files with 77 additions and 21 deletions

View file

@ -1,3 +1,17 @@
2011-11-10 Vladimir Serbinenko <phcoder@gmail.com>
Fix ZFS memory and resource leaks.
* grub-core/fs/zfs/zfs.c (fill_vdev_info_real): New paramter inserted.
All users updated.
Free type on exit.
(fill_vdev_info): New parameter inserted. All users updated.
(check_pool_label): Likewise.
(scan_disk): Likewise.
(scan_devices): Close non-inserted disks.
(fzap_iterate): Free l.
(unmount_device): Free children descripto memory.
2011-11-10 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix grub_strncat

View file

@ -535,7 +535,8 @@ static grub_err_t
fill_vdev_info_real (struct grub_zfs_data *data,
const char *nvlist,
struct grub_zfs_device_desc *fill,
struct grub_zfs_device_desc *insert)
struct grub_zfs_device_desc *insert,
int *inserted)
{
char *type;
@ -545,10 +546,16 @@ fill_vdev_info_real (struct grub_zfs_data *data,
return grub_errno;
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &(fill->id)))
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
{
grub_free (type);
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
}
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "guid", &(fill->guid)))
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
{
grub_free (type);
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
}
if (grub_strcmp (type, VDEV_TYPE_DISK) == 0
|| grub_strcmp (type, VDEV_TYPE_FILE) == 0)
@ -563,8 +570,11 @@ fill_vdev_info_real (struct grub_zfs_data *data,
fill->original = insert->original;
if (!data->device_original)
data->device_original = fill;
*inserted = 1;
}
grub_free (type);
return GRUB_ERR_NONE;
}
@ -580,17 +590,27 @@ fill_vdev_info_real (struct grub_zfs_data *data,
grub_uint64_t par;
fill->type = DEVICE_RAIDZ;
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "nparity", &par))
return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity");
{
grub_free (type);
return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity");
}
fill->nparity = par;
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "ashift", &par))
return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz ashift");
{
grub_free (type);
return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz ashift");
}
fill->ashift = par;
}
nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, ZPOOL_CONFIG_CHILDREN);
nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist,
ZPOOL_CONFIG_CHILDREN);
if (nelm <= 0)
return grub_error (GRUB_ERR_BAD_FS, "incorrect mirror VDEV");
{
grub_free (type);
return grub_error (GRUB_ERR_BAD_FS, "incorrect mirror VDEV");
}
if (!fill->children)
{
@ -608,34 +628,43 @@ fill_vdev_info_real (struct grub_zfs_data *data,
child = grub_zfs_nvlist_lookup_nvlist_array
(nvlist, ZPOOL_CONFIG_CHILDREN, i);
err = fill_vdev_info_real (data, child, &fill->children[i], insert);
err = fill_vdev_info_real (data, child, &fill->children[i], insert,
inserted);
grub_free (child);
if (err)
return err;
{
grub_free (type);
return err;
}
}
grub_free (type);
return GRUB_ERR_NONE;
}
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported",
type);
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported", type);
grub_free (type);
return grub_errno;
}
static grub_err_t
fill_vdev_info (struct grub_zfs_data *data,
char *nvlist, struct grub_zfs_device_desc *diskdesc)
char *nvlist, struct grub_zfs_device_desc *diskdesc,
int *inserted)
{
grub_uint64_t id;
unsigned i;
*inserted = 0;
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &id))
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
for (i = 0; i < data->n_devices_attached; i++)
if (data->devices_attached[i].id == id)
return fill_vdev_info_real (data, nvlist, &data->devices_attached[i],
diskdesc);
diskdesc, inserted);
data->n_devices_attached++;
if (data->n_devices_attached > data->n_devices_allocated)
@ -658,7 +687,7 @@ fill_vdev_info (struct grub_zfs_data *data,
return fill_vdev_info_real (data, nvlist,
&data->devices_attached[data->n_devices_attached - 1],
diskdesc);
diskdesc, inserted);
}
/*
@ -667,7 +696,8 @@ fill_vdev_info (struct grub_zfs_data *data,
*/
static grub_err_t
check_pool_label (struct grub_zfs_data *data,
struct grub_zfs_device_desc *diskdesc)
struct grub_zfs_device_desc *diskdesc,
int *inserted)
{
grub_uint64_t pool_state, txg = 0;
char *nvlist;
@ -679,6 +709,8 @@ check_pool_label (struct grub_zfs_data *data,
int found;
grub_err_t err;
*inserted = 0;
err = zfs_fetch_nvlist (diskdesc, &nvlist);
if (err)
return err;
@ -778,7 +810,7 @@ check_pool_label (struct grub_zfs_data *data,
grub_free (nvlist);
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev tree");
}
err = fill_vdev_info (data, nv, diskdesc);
err = fill_vdev_info (data, nv, diskdesc, inserted);
if (err)
{
grub_free (nv);
@ -796,7 +828,7 @@ check_pool_label (struct grub_zfs_data *data,
static grub_err_t
scan_disk (grub_device_t dev, struct grub_zfs_data *data,
int original)
int original, int *inserted)
{
int label = 0;
uberblock_phys_t *ub_array, *ubbest = NULL;
@ -858,7 +890,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
grub_memmove (&(data->current_uberblock),
&ubbest->ubp_uberblock, sizeof (uberblock_t));
err = check_pool_label (data, &desc);
err = check_pool_label (data, &desc, inserted);
if (err)
{
grub_errno = GRUB_ERR_NONE;
@ -889,6 +921,7 @@ scan_devices (struct grub_zfs_data *data)
{
grub_device_t dev;
grub_err_t err;
int inserted;
dev = grub_device_open (name);
if (!dev)
return 0;
@ -897,7 +930,7 @@ scan_devices (struct grub_zfs_data *data)
grub_device_close (dev);
return 0;
}
err = scan_disk (dev, data, 0);
err = scan_disk (dev, data, 0, &inserted);
if (err == GRUB_ERR_BAD_FS)
{
grub_device_close (dev);
@ -910,6 +943,9 @@ scan_devices (struct grub_zfs_data *data)
grub_print_error ();
return 0;
}
if (!inserted)
grub_device_close (dev);
return 0;
}
@ -2042,10 +2078,14 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
if (hook (buf, le->le_name_length,
val, le->le_value_length, le->le_int_size))
return 1;
{
grub_free (l);
return 1;
}
grub_free (buf);
grub_free (val);
}
grub_free (l);
}
return 0;
}
@ -3156,6 +3196,7 @@ unmount_device (struct grub_zfs_device_desc *desc)
case DEVICE_MIRROR:
for (i = 0; i < desc->n_children; i++)
unmount_device (&desc->children[i]);
grub_free (desc->children);
return;
}
}
@ -3190,6 +3231,7 @@ zfs_mount (grub_device_t dev)
grub_size_t ospsize;
grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN;
uberblock_t *ub;
int inserted;
if (! dev->disk)
{
@ -3210,7 +3252,7 @@ zfs_mount (grub_device_t dev)
data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
* data->n_devices_allocated);
data->n_devices_attached = 0;
err = scan_disk (dev, data, 1);
err = scan_disk (dev, data, 1, &inserted);
if (err)
{
zfs_unmount (data);