[PATCH] Consistently use zfs_ioctl()

Martin Matuska mm at FreeBSD.org
Tue Jul 26 20:42:58 UTC 2011


Dn(a 26. 7. 2011 15:21, Pawel Jakub Dawidek  wrote / napísal(a):
> On Mon, Jul 25, 2011 at 01:26:36PM -0700, Xin LI wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA256
>>
>> Hi,
>>
>> Here is a patch that makes libzfs use zfs_ioctl consistently. Some
>> functionality in libzfs calls ioctl() directly with raw ZFS ioctls,
>> which causes some kernel message like:
>>
>> WARNING pid 30031 (initial thread): ioctl sign-extension ioctl
>> ffffffffd5985a3a
>>
>> Objections? I have kept #sun'ed out blocks out.
>
> zfs_ioctl() does something with history records, I think. Are you sure
> zfs_ioctl() is 1-to-1 equivalent of plain ioctl()?
>
> Some minor nits inline.
Yes, zfs_ioctl deals with history and calls ioctl the very same way:
cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c:
int
zfs_ioctl(libzfs_handle_t *hdl, unsigned long request, zfs_cmd_t *zc)
{
        int error;
 
        zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str;
        error = ioctl(hdl->libzfs_fd, request, zc);
        if (hdl->libzfs_log_str) {
                free(hdl->libzfs_log_str);
                hdl->libzfs_log_str = NULL;
        }
        zc->zc_history = 0;
 
        return (error);
}
 
Now to ioctl(): we are not calling ioctl directly. Ioctl() is actually
zcmd_ioctl() - see bottom of the following code:
 
cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h:
static int zfs_kernel_version = 0;
 
/*
 * This is FreeBSD version of ioctl, because Solaris' ioctl() updates
 * zc_nvlist_dst_size even if an error is returned, on FreeBSD if an
 * error is returned zc_nvlist_dst_size won't be updated.
 */
static __inline int
zcmd_ioctl(int fd, unsigned long cmd, zfs_cmd_t *zc)
{
        size_t oldsize, zfs_kernel_version_size;
        int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
 
        zfs_kernel_version_size = sizeof(zfs_kernel_version);
        if (zfs_kernel_version == 0) {
                sysctlbyname("vfs.zfs.version.spa", &zfs_kernel_version,
                    &zfs_kernel_version_size, NULL, 0);
        }
 
        if (zfs_kernel_version == SPA_VERSION_15 ||
            zfs_kernel_version == SPA_VERSION_14 ||
            zfs_kernel_version == SPA_VERSION_13)
                cflag = ZFS_CMD_COMPAT_V15;
 
        oldsize = zc->zc_nvlist_dst_size;
        ret = zcmd_ioctl_compat(fd, cmd, zc, cflag);
 
        if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) {
                ret = -1;
                errno = ENOMEM;
        }
 
        return (ret);
}
#define ioctl(fd, cmd, zc)      zcmd_ioctl((fd), (cmd), (zc))
 
This function calls my zcmd_ioctl_compat in:
sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
 
Probably there is a problem in this function (my compat code)? But for
ZFS_CMD_COMPAT_NONE it is just passed to the kernel as it was before.
 
>
>
>> Index: cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
>> ===================================================================
>> --- cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
(revision 224337)
>> +++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
(working copy)
>> @@ -2382,6 +2382,7 @@ zfs_prop_get_userquota_common(zfs_handle_t *zhp, c
>> {
>> int err;
>> zfs_cmd_t zc = { 0 };
>> + libzfs_handle_t *hdl = zhp->zfs_hdl;
>>
>> (void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
>>
>> @@ -2392,7 +2393,7 @@ zfs_prop_get_userquota_common(zfs_handle_t *zhp, c
>> if (err)
>> return (err);
>>
>> - err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
>> + err = zfs_ioctl(hdl, ZFS_IOC_USERSPACE_ONE, &zc);
>
> Do we really need additional variable that is used only once?
> Wouldn't it be better to just replace ioctl(zhp->zfs_hdl->libzfs_fd)
> with zfs_ioctl(zhp->zfs_hdl)?
I agree, we don't and just for one use we waste resources.
>
>> @@ -2458,11 +2459,12 @@ zfs_do_list_ioctl(zfs_handle_t *zhp, unsigned
long
>> {
>> int rc;
>> uint64_t orig_cookie;
>> + libzfs_handle_t *hdl = zhp->zfs_hdl;
>>
>> orig_cookie = zc->zc_cookie;
>> top:
>> (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
>> - rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc);
>> + rc = zfs_ioctl(hdl, arg, zc);
>
> Same here.
>
>> @@ -3924,6 +3926,7 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_pro
>> zfs_userspace_cb_t func, void *arg)
>> {
>> zfs_cmd_t zc = { 0 };
>> + libzfs_handle_t *hdl = zhp->zfs_hdl;
>> int error;
>> zfs_useracct_t buf[100];
>>
>> @@ -3937,7 +3940,7 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_pro
>> zfs_useracct_t *zua = buf;
>>
>> zc.zc_nvlist_dst_size = sizeof (buf);
>> - error = ioctl(zhp->zfs_hdl->libzfs_fd,
>> + error = zfs_ioctl(hdl,
>> ZFS_IOC_USERSPACE_MANY, &zc);
>
> And here.
>
 
 
-- 
Martin Matuska
FreeBSD committer
http://blog.vx.sk


More information about the zfs-devel mailing list