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:
parent
ad9a2f44b4
commit
45bd824d2e
2 changed files with 77 additions and 21 deletions
14
ChangeLog
14
ChangeLog
|
@ -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>
|
2011-11-10 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix grub_strncat
|
* grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix grub_strncat
|
||||||
|
|
|
@ -535,7 +535,8 @@ static grub_err_t
|
||||||
fill_vdev_info_real (struct grub_zfs_data *data,
|
fill_vdev_info_real (struct grub_zfs_data *data,
|
||||||
const char *nvlist,
|
const char *nvlist,
|
||||||
struct grub_zfs_device_desc *fill,
|
struct grub_zfs_device_desc *fill,
|
||||||
struct grub_zfs_device_desc *insert)
|
struct grub_zfs_device_desc *insert,
|
||||||
|
int *inserted)
|
||||||
{
|
{
|
||||||
char *type;
|
char *type;
|
||||||
|
|
||||||
|
@ -545,10 +546,16 @@ fill_vdev_info_real (struct grub_zfs_data *data,
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &(fill->id)))
|
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)))
|
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
|
if (grub_strcmp (type, VDEV_TYPE_DISK) == 0
|
||||||
|| grub_strcmp (type, VDEV_TYPE_FILE) == 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;
|
fill->original = insert->original;
|
||||||
if (!data->device_original)
|
if (!data->device_original)
|
||||||
data->device_original = fill;
|
data->device_original = fill;
|
||||||
|
*inserted = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_free (type);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,17 +590,27 @@ fill_vdev_info_real (struct grub_zfs_data *data,
|
||||||
grub_uint64_t par;
|
grub_uint64_t par;
|
||||||
fill->type = DEVICE_RAIDZ;
|
fill->type = DEVICE_RAIDZ;
|
||||||
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "nparity", &par))
|
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;
|
fill->nparity = par;
|
||||||
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "ashift", &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;
|
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)
|
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)
|
if (!fill->children)
|
||||||
{
|
{
|
||||||
|
@ -608,34 +628,43 @@ fill_vdev_info_real (struct grub_zfs_data *data,
|
||||||
child = grub_zfs_nvlist_lookup_nvlist_array
|
child = grub_zfs_nvlist_lookup_nvlist_array
|
||||||
(nvlist, ZPOOL_CONFIG_CHILDREN, i);
|
(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);
|
grub_free (child);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
{
|
||||||
|
grub_free (type);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
grub_free (type);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported",
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported", type);
|
||||||
type);
|
grub_free (type);
|
||||||
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
fill_vdev_info (struct grub_zfs_data *data,
|
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;
|
grub_uint64_t id;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
*inserted = 0;
|
||||||
|
|
||||||
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &id))
|
if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &id))
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
|
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
|
||||||
|
|
||||||
for (i = 0; i < data->n_devices_attached; i++)
|
for (i = 0; i < data->n_devices_attached; i++)
|
||||||
if (data->devices_attached[i].id == id)
|
if (data->devices_attached[i].id == id)
|
||||||
return fill_vdev_info_real (data, nvlist, &data->devices_attached[i],
|
return fill_vdev_info_real (data, nvlist, &data->devices_attached[i],
|
||||||
diskdesc);
|
diskdesc, inserted);
|
||||||
|
|
||||||
data->n_devices_attached++;
|
data->n_devices_attached++;
|
||||||
if (data->n_devices_attached > data->n_devices_allocated)
|
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,
|
return fill_vdev_info_real (data, nvlist,
|
||||||
&data->devices_attached[data->n_devices_attached - 1],
|
&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
|
static grub_err_t
|
||||||
check_pool_label (struct grub_zfs_data *data,
|
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;
|
grub_uint64_t pool_state, txg = 0;
|
||||||
char *nvlist;
|
char *nvlist;
|
||||||
|
@ -679,6 +709,8 @@ check_pool_label (struct grub_zfs_data *data,
|
||||||
int found;
|
int found;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
|
*inserted = 0;
|
||||||
|
|
||||||
err = zfs_fetch_nvlist (diskdesc, &nvlist);
|
err = zfs_fetch_nvlist (diskdesc, &nvlist);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -778,7 +810,7 @@ check_pool_label (struct grub_zfs_data *data,
|
||||||
grub_free (nvlist);
|
grub_free (nvlist);
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev tree");
|
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)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (nv);
|
grub_free (nv);
|
||||||
|
@ -796,7 +828,7 @@ check_pool_label (struct grub_zfs_data *data,
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
scan_disk (grub_device_t dev, struct grub_zfs_data *data,
|
scan_disk (grub_device_t dev, struct grub_zfs_data *data,
|
||||||
int original)
|
int original, int *inserted)
|
||||||
{
|
{
|
||||||
int label = 0;
|
int label = 0;
|
||||||
uberblock_phys_t *ub_array, *ubbest = NULL;
|
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),
|
grub_memmove (&(data->current_uberblock),
|
||||||
&ubbest->ubp_uberblock, sizeof (uberblock_t));
|
&ubbest->ubp_uberblock, sizeof (uberblock_t));
|
||||||
|
|
||||||
err = check_pool_label (data, &desc);
|
err = check_pool_label (data, &desc, inserted);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
@ -889,6 +921,7 @@ scan_devices (struct grub_zfs_data *data)
|
||||||
{
|
{
|
||||||
grub_device_t dev;
|
grub_device_t dev;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
int inserted;
|
||||||
dev = grub_device_open (name);
|
dev = grub_device_open (name);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -897,7 +930,7 @@ scan_devices (struct grub_zfs_data *data)
|
||||||
grub_device_close (dev);
|
grub_device_close (dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
err = scan_disk (dev, data, 0);
|
err = scan_disk (dev, data, 0, &inserted);
|
||||||
if (err == GRUB_ERR_BAD_FS)
|
if (err == GRUB_ERR_BAD_FS)
|
||||||
{
|
{
|
||||||
grub_device_close (dev);
|
grub_device_close (dev);
|
||||||
|
@ -910,6 +943,9 @@ scan_devices (struct grub_zfs_data *data)
|
||||||
grub_print_error ();
|
grub_print_error ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!inserted)
|
||||||
|
grub_device_close (dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2042,10 +2078,14 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
|
||||||
|
|
||||||
if (hook (buf, le->le_name_length,
|
if (hook (buf, le->le_name_length,
|
||||||
val, le->le_value_length, le->le_int_size))
|
val, le->le_value_length, le->le_int_size))
|
||||||
return 1;
|
{
|
||||||
|
grub_free (l);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
grub_free (buf);
|
grub_free (buf);
|
||||||
grub_free (val);
|
grub_free (val);
|
||||||
}
|
}
|
||||||
|
grub_free (l);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3156,6 +3196,7 @@ unmount_device (struct grub_zfs_device_desc *desc)
|
||||||
case DEVICE_MIRROR:
|
case DEVICE_MIRROR:
|
||||||
for (i = 0; i < desc->n_children; i++)
|
for (i = 0; i < desc->n_children; i++)
|
||||||
unmount_device (&desc->children[i]);
|
unmount_device (&desc->children[i]);
|
||||||
|
grub_free (desc->children);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3190,6 +3231,7 @@ zfs_mount (grub_device_t dev)
|
||||||
grub_size_t ospsize;
|
grub_size_t ospsize;
|
||||||
grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN;
|
grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN;
|
||||||
uberblock_t *ub;
|
uberblock_t *ub;
|
||||||
|
int inserted;
|
||||||
|
|
||||||
if (! dev->disk)
|
if (! dev->disk)
|
||||||
{
|
{
|
||||||
|
@ -3210,7 +3252,7 @@ zfs_mount (grub_device_t dev)
|
||||||
data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
|
data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
|
||||||
* data->n_devices_allocated);
|
* data->n_devices_allocated);
|
||||||
data->n_devices_attached = 0;
|
data->n_devices_attached = 0;
|
||||||
err = scan_disk (dev, data, 1);
|
err = scan_disk (dev, data, 1, &inserted);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
zfs_unmount (data);
|
zfs_unmount (data);
|
||||||
|
|
Loading…
Add table
Reference in a new issue