@@ -410,11 +410,11 @@ get_usage(zfs_help_t idx)
410410 "\tproject -C [-k] [-r] <directory ...>\n"
411411 "\tproject [-p id] [-r] [-s] <directory ...>\n" ));
412412 case HELP_HOLD :
413- return (gettext ("\thold [-r] <tag> <snapshot> ...\n" ));
413+ return (gettext ("\thold [-r] <tag> <snapshot|dataset > ...\n" ));
414414 case HELP_HOLDS :
415- return (gettext ("\tholds [-rHp] <snapshot> ...\n" ));
415+ return (gettext ("\tholds [-rHp] <snapshot|dataset > ...\n" ));
416416 case HELP_RELEASE :
417- return (gettext ("\trelease [-r] <tag> <snapshot> ...\n" ));
417+ return (gettext ("\trelease [-r] <tag> <snapshot|dataset > ...\n" ));
418418 case HELP_DIFF :
419419 return (gettext ("\tdiff [-FHth] <snapshot> "
420420 "[snapshot|filesystem]\n" ));
@@ -6677,6 +6677,63 @@ zfs_do_unallow(int argc, char **argv)
66776677 return (zfs_do_allow_unallow_impl (argc , argv , B_TRUE ));
66786678}
66796679
6680+ typedef struct dataset_hold_arg {
6681+ nvlist_t * nvl ;
6682+ const char * tag ;
6683+ boolean_t holding ;
6684+ boolean_t recursive ;
6685+ } dataset_hold_arg_t ;
6686+
6687+ static int
6688+ zfs_dataset_hold_rele_one (zfs_handle_t * zhp , void * arg )
6689+ {
6690+ dataset_hold_arg_t * ha = arg ;
6691+ int rv = 0 ;
6692+ const char * name = zfs_get_name (zhp );
6693+
6694+ if (ha -> holding ) {
6695+ fnvlist_add_string (ha -> nvl , name , ha -> tag );
6696+ } else {
6697+ nvlist_t * torelease = fnvlist_alloc ();
6698+ fnvlist_add_boolean (torelease , ha -> tag );
6699+ fnvlist_add_nvlist (ha -> nvl , name , torelease );
6700+ fnvlist_free (torelease );
6701+ }
6702+
6703+ if (ha -> recursive )
6704+ rv = zfs_iter_filesystems_v2 (zhp , 0 ,
6705+ zfs_dataset_hold_rele_one , ha );
6706+ zfs_close (zhp );
6707+ return (rv );
6708+ }
6709+
6710+ static int
6711+ zfs_dataset_hold_rele_recurse (zfs_handle_t * zhp , const char * tag ,
6712+ boolean_t holding , boolean_t recursive )
6713+ {
6714+ dataset_hold_arg_t ha = {
6715+ .nvl = fnvlist_alloc (),
6716+ .tag = tag ,
6717+ .holding = holding ,
6718+ .recursive = recursive ,
6719+ };
6720+ int ret ;
6721+
6722+ ret = zfs_dataset_hold_rele_one (zfs_handle_dup (zhp ), & ha );
6723+ if (ret != 0 ) {
6724+ fnvlist_free (ha .nvl );
6725+ return (ret );
6726+ }
6727+
6728+ if (holding )
6729+ ret = zfs_hold_nvl (zhp , -1 , ha .nvl );
6730+ else
6731+ ret = lzc_release (ha .nvl , NULL );
6732+
6733+ fnvlist_free (ha .nvl );
6734+ return (ret );
6735+ }
6736+
66806737static int
66816738zfs_do_hold_rele_impl (int argc , char * * argv , boolean_t holding )
66826739{
@@ -6725,9 +6782,16 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
67256782
67266783 delim = strchr (path , '@' );
67276784 if (delim == NULL ) {
6728- (void ) fprintf (stderr ,
6729- gettext ("'%s' is not a snapshot\n" ), path );
6730- ++ errors ;
6785+ zhp = zfs_open (g_zfs , path ,
6786+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME );
6787+ if (zhp == NULL ) {
6788+ ++ errors ;
6789+ continue ;
6790+ }
6791+ if (zfs_dataset_hold_rele_recurse (zhp , tag , holding ,
6792+ recursive ) != 0 )
6793+ ++ errors ;
6794+ zfs_close (zhp );
67316795 continue ;
67326796 }
67336797 (void ) strlcpy (parent , path , MIN (sizeof (parent ),
@@ -6865,7 +6929,7 @@ holds_callback(zfs_handle_t *zhp, void *data)
68656929 const char * zname = zfs_get_name (zhp );
68666930 size_t znamelen = strlen (zname );
68676931
6868- if (cbp -> cb_recursive ) {
6932+ if (cbp -> cb_recursive && cbp -> cb_snapname != NULL ) {
68696933 const char * snapname ;
68706934 const char * delim = strchr (zname , '@' );
68716935 if (delim == NULL )
@@ -6955,9 +7019,14 @@ zfs_do_holds(int argc, char **argv)
69557019
69567020 delim = strchr (snapshot , '@' );
69577021 if (delim == NULL ) {
6958- (void ) fprintf (stderr ,
6959- gettext ("'%s' is not a snapshot\n" ), snapshot );
6960- errors = B_TRUE ;
7022+ cb .cb_recursive = recursive ;
7023+ cb .cb_snapname = NULL ;
7024+ cb .cb_nvlp = & nvl ;
7025+ ret = zfs_for_each (1 , argv + i , flags ,
7026+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME ,
7027+ NULL , NULL , limit , holds_callback , & cb );
7028+ if (ret != 0 )
7029+ errors = B_TRUE ;
69617030 continue ;
69627031 }
69637032 snapname = delim + 1 ;
0 commit comments