Print this page
NEX-16159 Time spent sharing SMB filesystems could be reduced by optimizing smb_getdataset for default mount points
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Reviewed by: Matt Barden <matt.barden@nexenta.com>
SMB-136 Snapshots not visible in Windows previous versions


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2016 Martin Matuska. All rights reserved.
  26  */
  27 
  28 #include <synch.h>
  29 #include <pthread.h>
  30 #include <unistd.h>
  31 #include <string.h>
  32 #include <strings.h>
  33 #include <sys/errno.h>
  34 #include <libzfs.h>
  35 
  36 #include <smbsrv/libsmb.h>
  37 #include <smbsrv/libsmbns.h>
  38 #include <smbsrv/libmlsvc.h>
  39 #include <smbsrv/smbinfo.h>
  40 #include "smbd.h"
  41 
  42 /*
  43  * This file supports three basic functions that all use the
  44  * the zfs_iter_snapshots function to get the snapshot info


  93         time_t mg_snaptime;
  94         char *mg_snapname;
  95 } smbd_vss_map_gmttoken_t;
  96 
  97 
  98 /*
  99  * path - path of the dataset
 100  * count - return value of the number of snapshots for the dataset
 101  */
 102 int
 103 smbd_vss_get_count(const char *path, uint32_t *count)
 104 {
 105         char dataset[MAXPATHLEN];
 106         libzfs_handle_t *libhd;
 107         zfs_handle_t *zfshd;
 108         smbd_vss_count_t vss_count;
 109 
 110         bzero(&vss_count, sizeof (smbd_vss_count_t));
 111         *count = 0;
 112 
 113         if (smb_getdataset(path, dataset, MAXPATHLEN) != 0)
 114                 return (-1);
 115 
 116         if ((libhd = libzfs_init()) == NULL)

 117                 return (-1);

 118 
 119         if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
 120                 libzfs_fini(libhd);
 121                 return (-1);
 122         }
 123 
 124         (void) zfs_iter_snapshots(zfshd, B_FALSE, smbd_vss_iterate_count,
 125             (void *)&vss_count);
 126 
 127         if (vss_count.vc_count > SMBD_VSS_SNAPSHOT_MAX)
 128                 vss_count.vc_count = SMBD_VSS_SNAPSHOT_MAX;
 129 
 130         *count = vss_count.vc_count;
 131         zfs_close(zfshd);
 132         libzfs_fini(libhd);
 133         return (0);
 134 }
 135 
 136 /*
 137  * path - is the path of the dataset


 148 {
 149         char dataset[MAXPATHLEN];
 150         libzfs_handle_t *libhd;
 151         zfs_handle_t *zfshd;
 152         smbd_vss_get_uint64_date_t vss_uint64_date;
 153         int i;
 154         uint64_t *timep;
 155 
 156         *return_count = 0;
 157         *num_gmttokens = 0;
 158 
 159         if (count == 0)
 160                 return;
 161 
 162         if (count > SMBD_VSS_SNAPSHOT_MAX)
 163                 count = SMBD_VSS_SNAPSHOT_MAX;
 164 
 165         vss_uint64_date.gd_count = count;
 166         vss_uint64_date.gd_return_count = 0;
 167         vss_uint64_date.gd_gmt_array = malloc(count * sizeof (uint64_t));

 168         if (vss_uint64_date.gd_gmt_array == NULL)
 169                 return;
 170 
 171         if (smb_getdataset(path, dataset, MAXPATHLEN) != 0) {
 172                 free(vss_uint64_date.gd_gmt_array);
 173                 return;
 174         }
 175 
 176         if ((libhd = libzfs_init()) == NULL) {
 177                 free(vss_uint64_date.gd_gmt_array);

 178                 return;
 179         }
 180 
 181         if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
 182                 free(vss_uint64_date.gd_gmt_array);
 183                 libzfs_fini(libhd);
 184                 return;
 185         }
 186 
 187         (void) zfs_iter_snapshots(zfshd, B_FALSE,
 188             smbd_vss_iterate_get_uint64_date, (void *)&vss_uint64_date);
 189 
 190         *num_gmttokens = vss_uint64_date.gd_return_count;
 191         *return_count = vss_uint64_date.gd_return_count;
 192 
 193         /*
 194          * Sort the list since neither zfs nor the client sorts it.
 195          */
 196         qsort((char *)vss_uint64_date.gd_gmt_array,
 197             vss_uint64_date.gd_return_count,


 234 smbd_vss_map_gmttoken(const char *path, char *gmttoken, time_t toktime,
 235         char *snapname)
 236 {
 237         char dataset[MAXPATHLEN];
 238         libzfs_handle_t *libhd;
 239         zfs_handle_t *zfshd;
 240         smbd_vss_map_gmttoken_t vss_map_gmttoken;
 241         char *zsnap;
 242         const char *lsnap;
 243         struct tm tm;
 244 
 245         if (gmttoken != NULL && *gmttoken == '@' &&
 246             strptime(gmttoken, smbd_vss_gmttoken_fmt, &tm) != NULL) {
 247                 toktime = timegm(&tm);
 248         }
 249 
 250         vss_map_gmttoken.mg_snaptime = toktime;
 251         vss_map_gmttoken.mg_snapname = snapname;
 252         *snapname = '\0';
 253 
 254         if (smb_getdataset(path, dataset, MAXPATHLEN) != 0)
 255                 return (-1);
 256 
 257         if ((libhd = libzfs_init()) == NULL)

 258                 return (-1);

 259 
 260         if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
 261                 libzfs_fini(libhd);
 262                 return (-1);
 263         }
 264 
 265         (void) zfs_iter_snapshots(zfshd, B_FALSE, smbd_vss_iterate_map_gmttoken,
 266             (void *)&vss_map_gmttoken);
 267 
 268         /* compare the zfs snapshot name and the local snap name */
 269         zsnap = snapname;
 270         lsnap = dataset;
 271         while ((*lsnap != '\0') && (*zsnap != '\0') && (*lsnap == *zsnap)) {
 272                 zsnap++;
 273                 lsnap++;
 274         }
 275 
 276         /* Now we should be passed the dataset name */
 277         if ((*zsnap == '@') && (*lsnap == '\0')) {
 278                 zsnap++;




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2016 Martin Matuska. All rights reserved.
  26  */
  27 
  28 #include <synch.h>
  29 #include <pthread.h>
  30 #include <unistd.h>
  31 #include <string.h>
  32 #include <strings.h>
  33 #include <sys/errno.h>
  34 #include <libzfs.h>
  35 
  36 #include <smbsrv/libsmb.h>
  37 #include <smbsrv/libsmbns.h>
  38 #include <smbsrv/libmlsvc.h>
  39 #include <smbsrv/smbinfo.h>
  40 #include "smbd.h"
  41 
  42 /*
  43  * This file supports three basic functions that all use the
  44  * the zfs_iter_snapshots function to get the snapshot info


  93         time_t mg_snaptime;
  94         char *mg_snapname;
  95 } smbd_vss_map_gmttoken_t;
  96 
  97 
  98 /*
  99  * path - path of the dataset
 100  * count - return value of the number of snapshots for the dataset
 101  */
 102 int
 103 smbd_vss_get_count(const char *path, uint32_t *count)
 104 {
 105         char dataset[MAXPATHLEN];
 106         libzfs_handle_t *libhd;
 107         zfs_handle_t *zfshd;
 108         smbd_vss_count_t vss_count;
 109 
 110         bzero(&vss_count, sizeof (smbd_vss_count_t));
 111         *count = 0;
 112 
 113         if ((libhd = libzfs_init()) == NULL)
 114                 return (-1);
 115 
 116         if (smb_getdataset(libhd, path, dataset, MAXPATHLEN) != 0) {
 117                 libzfs_fini(libhd);
 118                 return (-1);
 119         }
 120 
 121         if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
 122                 libzfs_fini(libhd);
 123                 return (-1);
 124         }
 125 
 126         (void) zfs_iter_snapshots(zfshd, B_FALSE, smbd_vss_iterate_count,
 127             (void *)&vss_count);
 128 
 129         if (vss_count.vc_count > SMBD_VSS_SNAPSHOT_MAX)
 130                 vss_count.vc_count = SMBD_VSS_SNAPSHOT_MAX;
 131 
 132         *count = vss_count.vc_count;
 133         zfs_close(zfshd);
 134         libzfs_fini(libhd);
 135         return (0);
 136 }
 137 
 138 /*
 139  * path - is the path of the dataset


 150 {
 151         char dataset[MAXPATHLEN];
 152         libzfs_handle_t *libhd;
 153         zfs_handle_t *zfshd;
 154         smbd_vss_get_uint64_date_t vss_uint64_date;
 155         int i;
 156         uint64_t *timep;
 157 
 158         *return_count = 0;
 159         *num_gmttokens = 0;
 160 
 161         if (count == 0)
 162                 return;
 163 
 164         if (count > SMBD_VSS_SNAPSHOT_MAX)
 165                 count = SMBD_VSS_SNAPSHOT_MAX;
 166 
 167         vss_uint64_date.gd_count = count;
 168         vss_uint64_date.gd_return_count = 0;
 169         vss_uint64_date.gd_gmt_array = malloc(count * sizeof (uint64_t));
 170 
 171         if (vss_uint64_date.gd_gmt_array == NULL)
 172                 return;
 173 
 174         if ((libhd = libzfs_init()) == NULL) {
 175                 free(vss_uint64_date.gd_gmt_array);
 176                 return;
 177         }
 178 
 179         if (smb_getdataset(libhd, path, dataset, MAXPATHLEN) != 0) {
 180                 free(vss_uint64_date.gd_gmt_array);
 181                 libzfs_fini(libhd);
 182                 return;
 183         }
 184 
 185         if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
 186                 free(vss_uint64_date.gd_gmt_array);
 187                 libzfs_fini(libhd);
 188                 return;
 189         }
 190 
 191         (void) zfs_iter_snapshots(zfshd, B_FALSE,
 192             smbd_vss_iterate_get_uint64_date, (void *)&vss_uint64_date);
 193 
 194         *num_gmttokens = vss_uint64_date.gd_return_count;
 195         *return_count = vss_uint64_date.gd_return_count;
 196 
 197         /*
 198          * Sort the list since neither zfs nor the client sorts it.
 199          */
 200         qsort((char *)vss_uint64_date.gd_gmt_array,
 201             vss_uint64_date.gd_return_count,


 238 smbd_vss_map_gmttoken(const char *path, char *gmttoken, time_t toktime,
 239         char *snapname)
 240 {
 241         char dataset[MAXPATHLEN];
 242         libzfs_handle_t *libhd;
 243         zfs_handle_t *zfshd;
 244         smbd_vss_map_gmttoken_t vss_map_gmttoken;
 245         char *zsnap;
 246         const char *lsnap;
 247         struct tm tm;
 248 
 249         if (gmttoken != NULL && *gmttoken == '@' &&
 250             strptime(gmttoken, smbd_vss_gmttoken_fmt, &tm) != NULL) {
 251                 toktime = timegm(&tm);
 252         }
 253 
 254         vss_map_gmttoken.mg_snaptime = toktime;
 255         vss_map_gmttoken.mg_snapname = snapname;
 256         *snapname = '\0';
 257 
 258         if ((libhd = libzfs_init()) == NULL)
 259                 return (-1);
 260 
 261         if (smb_getdataset(libhd, path, dataset, MAXPATHLEN) != 0) {
 262                 libzfs_fini(libhd);
 263                 return (-1);
 264         }
 265 
 266         if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
 267                 libzfs_fini(libhd);
 268                 return (-1);
 269         }
 270 
 271         (void) zfs_iter_snapshots(zfshd, B_FALSE, smbd_vss_iterate_map_gmttoken,
 272             (void *)&vss_map_gmttoken);
 273 
 274         /* compare the zfs snapshot name and the local snap name */
 275         zsnap = snapname;
 276         lsnap = dataset;
 277         while ((*lsnap != '\0') && (*zsnap != '\0') && (*lsnap == *zsnap)) {
 278                 zsnap++;
 279                 lsnap++;
 280         }
 281 
 282         /* Now we should be passed the dataset name */
 283         if ((*zsnap == '@') && (*lsnap == '\0')) {
 284                 zsnap++;