MFC r316908: 7541 zpool import/tryimport ioctl returns ENOMEM because provided buffer is too small for config

illumos/illumos-gate@8b65a70b76
8b65a70b76

https://www.illumos.org/issues/7541
  When calling zpool import, zpool does a few ioctls to ZFS.
  zpool allocates a buffer in userland and passes it to the kernel so that ZFS
  can copy info into it. ZFS will use it to put the nvlist that describes the
  pool configuration.
  If the allocated buffer is too small, ZFS will return ENOMEM and the call will
  have to be redone. This wastes CPU time and slows down the import process. This
  happens very often for the ZFS_IOC_POOL_TRYIMPORT call.

Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
Author: Pavel Zakharov <pavel.zakharov@delphix.com>
MFC after:	2 weeks
This commit is contained in:
Andriy Gapon 2017-05-24 21:32:35 +00:00
commit b6be31c7ca
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=318819
2 changed files with 7 additions and 4 deletions

View File

@ -132,6 +132,8 @@ typedef enum {
SHARED_SMB = 0x4
} zfs_share_type_t;
#define CONFIG_BUF_MINSIZE 65536
int zfs_error(libzfs_handle_t *, int, const char *);
int zfs_error_fmt(libzfs_handle_t *, int, const char *, ...);
void zfs_error_aux(libzfs_handle_t *, const char *, ...);

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright 2015 RackTop Systems.
* Copyright 2016 Nexenta Systems, Inc.
*/
@ -379,13 +379,14 @@ refresh_config(libzfs_handle_t *hdl, nvlist_t *config)
{
nvlist_t *nvl;
zfs_cmd_t zc = { 0 };
int err;
int err, dstbuf_size;
if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0)
return (NULL);
if (zcmd_alloc_dst_nvlist(hdl, &zc,
zc.zc_nvlist_conf_size * 2) != 0) {
dstbuf_size = MAX(CONFIG_BUF_MINSIZE, zc.zc_nvlist_conf_size * 4);
if (zcmd_alloc_dst_nvlist(hdl, &zc, dstbuf_size) != 0) {
zcmd_free_nvlists(&zc);
return (NULL);
}