# Possible Feature Request for zfs?



## mg16373 (Feb 20, 2013)

Hi! In some situation I did not feel good when I modify my zfs pools or filesystems structures. What do you think about the following "Extension"?

--Simulation--

```
[server ~]$ zpool get all raid1p1

NAME     PROPERTY       VALUE       SOURCE
raid1p1  size           3.62T       -
raid1p1  capacity       41%         -
raid1p1  altroot        -           default
raid1p1  health         ONLINE      -
raid1p1  guid           14252030461883037602  default
raid1p1  version        28          default
raid1p1  bootfs         -           default
[color="DarkRed"]raid1p1  protected      on          local         <-- new property[/color]
raid1p1  delegation     on          default
raid1p1  autoreplace    off         default
raid1p1  cachefile      -           default
raid1p1  failmode       wait        default
raid1p1  listsnapshots  on          local
raid1p1  autoexpand     off         default
raid1p1  dedupditto     0           default
raid1p1  dedupratio     1.00x       -
raid1p1  free           2.13T       -
raid1p1  allocated      1.50T       -
raid1p1  readonly       off         -
raid1p1  comment        -           default
raid1p1  expandsize     0           -
```

Simulated output for filesystem properties:


```
[server ~]$ zfs get all raid1p1/myimportantdata

NAME                     PROPERTY              VALUE                  SOURCE
raid1p1/myimportantdata  type                  filesystem             -
raid1p1/myimportantdata  creation              Sun Jan 27 23:47 2013  -
raid1p1/myimportantdata  used                  2.49T                  -
raid1p1/myimportantdata  available             1.07T                  -
raid1p1/myimportantdata  referenced            31K                    -
raid1p1/myimportantdata  compressratio         1.01x                  -
raid1p1/myimportantdata  mounted               yes                    -
[color="DarkRed"]raid1p1/myimportantdata  protected             yes                    local    <-- new property[/color]
raid1p1/myimportantdata  quota                 none                   default
raid1p1/myimportantdata  reservation           none                   default
raid1p1/myimportantdata  recordsize            128K                   default
...
```
----

My "problem" is when I remove snapshots from a filesystem the command syntax are identicaly for two reasons:

1) *zfs destroy raid1p1/myimportantdata@snapshot*     <-- removes only my snapshot
2) *zfs destroy raid1p1/myimportantdata*              <-- destroys my very important filesystem 

Every day I manage the zfs filesystem and their snapshots within shell scripts. When this scripts have a bug and the '@'-symbol was not entered I can destroy my filesystem without any warnings. The same nightmare is possible for pool operations.

Do you understand what I meen? A simple "flag" or "property" can help me/us to protect the pool/filesystem when I have a bad day 

Example: I will remove a snapshot but I have a syntax error in my command line. The property "protected" is set to "yes". Now I type [cmd=]zfs remove raid1p1/myimportantdata[/cmd] and then press enter. Zfs checks now the property and returns an error like 
	
	



```
Operating failed. Filesystem is protected
```
 
The same example is possible for pool operations. When I realy want to destroy a filesystem or pool first I must enter the following command:

[cmd=]zfs set protected=no|off raid1p1/myimportantdata[/cmd] or [cmd=]zpool set protected=off raid1p1[/cmd]      

After this additional layer of "security" I can destroy the pool or filesystem.. What do you think about it? And sorry for my bad english ;-)

Best regards,
Markus


----------



## usdmatt (Feb 20, 2013)

It's a fairly reasonable idea. It is very easy to destroy a pool or dataset by sending the wrong command. I know I've run 'zpool destroy test' a few times when trying things out on a test pool then suddenly thought "crap, I didn't just type 'zpool destroy temp' did I?" (temp being a pool that I actually currently use, which I should probably rename).

I doubt this feature would be implemented directly by FreeBSD though. There is still a concerted effort for the 'open' ZFS to be compatible across all OS's that use it and FreeBSD currently gets the majority of ZFS code from Illumos. As such, it would probably need to be discussed by the ZFS working group, implemented in the 'head' ZFS code, and then be brought into FreeBSD from there.

One other note, if you try to destroy a snapshot and forget the snapshot name as described, the destroy wouldn't work. You cannot destroy a dataset that has children (including snapshots) unless you specify the -r option for recursive, and there's not really a reason to use -r when trying to destroy a snapshot. As always I recommend people stay away from -r/-f unless they are sure about what they are doing or they have got a message telling them they need to use -r/-f, understand it, and want to continue anyway.

Edit: There is a 'zfs hold' command which can place a hold on a snapshot, stopping it from being deleted which is similar to what you propose but limited to snapshots. Unfortunately it doesn't look like you can put a hold on a pool or dataset (according to the man page)


----------



## mg16373 (Feb 20, 2013)

usdmatt said:
			
		

> It's a fairly reasonable idea. It is very easy to destroy a pool or dataset by sending the wrong command.



Thank you for reply.




			
				usdmatt said:
			
		

> I know I've run 'zpool destroy test' a few times when trying things out on a test pool then suddenly thought "crap, I didn't just type 'zpool destroy temp' did I?" (temp being a pool that I actually currently use, which I should probably rename).



100% ACK. Sometimes me was hot and cold at the same time :e



			
				usdmatt said:
			
		

> I doubt this feature would be implemented directly by FreeBSD though. There is still a concerted effort for the 'open' ZFS to be compatible across all OS's that use it and FreeBSD currently gets the majority ...



Yes I know but this thread and the following discussion is the first little step.
I'm only a hobby C programmer but I will review the zfs Code to find the right place where the modifications are done.


----------



## mg16373 (Feb 20, 2013)

I have began to look into the source code and it seems to relative easy to enhance the property named "PROTECTED" . In a copy of the distributed source I had done some modifications to register the new property and functions "get/set" (based on the 'readonly' propertry). With a little bit more of time it seems not impossible to add the functionality.

And I have found a very interesting code:


```
/* readonly index (boolean) properties */
        zprop_register_index(ZFS_PROP_MOUNTED, "mounted", 0, PROP_READONLY,
            ZFS_TYPE_FILESYSTEM, "yes | no", "MOUNTED", boolean_table);                          
        zprop_register_index(ZFS_PROP_DEFER_DESTROY, "defer_destroy", 0,
            [B]PROP_READONLY, ZFS_TYPE_SNAPSHOT, "yes | no", "DEFER_DESTROY"[/B], boolean_table);
```

How ever! I will be very happy when this property find open ears and they will be implemented.


----------



## phoenix (Feb 20, 2013)

Read up on the *hold* option for the zfs(8) command.  It does what you want.

Snapshot a filesystem.  Hold the snapshot.  You can never delete the filesystem by accident, as it won't delete filesystems with snapshots, and you can't delete that snapshot until you release the hold.


----------



## mg16373 (Feb 20, 2013)

phoenix said:
			
		

> Read up on the *hold* option for the zfs(8) command.  It does what you want.
> 
> Snapshot a filesystem.  Hold the snapshot.  You can never delete the filesystem by accident, as it won't delete filesystems with snapshots, and you can't delete that snapshot until you release the hold.



OK. When I have understand you then can I use this "state" to mark a filesystem as undestroyable. Is then the pool also undestroyable? I don't know because I will not test this on my configuration ;-)


----------



## phoenix (Feb 20, 2013)

Snapshot holds do not prevent a pool from being destroyed.

However, the command to destroy a pool is very different from the command to destroy a filesystem ("z*pool* destroy" vs "z*fs* destroy"), so I highly doubt you'd confuse the two accidentally.


----------



## mg16373 (Feb 20, 2013)

phoenix said:
			
		

> Snapshot holds do not prevent a pool from being destroyed.



Yes that's it was I mean. No protection for the pool.



			
				phoenix said:
			
		

> However, the command to destroy a pool is very different from the command to destroy a filesystem ("z*pool* destroy" vs "z*fs* destroy"), so I highly doubt you'd confuse the two accidentally.



The syntax to destroy a pool is: "zpool destroy [-f] pool"
... and for filesystem is:  "zfs destroy [-fnpRrv] filesystem|volume"

You have right. The command is different but both commands are doing what I say without any warnings! "Destroy" is "Destroy". I want protect me from myself!


----------



## Sebulon (Feb 21, 2013)

IÂ´ve found two quotes against this, just from this forum:

"To err is human - and to blame it on a computer is even more so."
"UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things."

/Sebulon


----------



## wblock@ (Feb 21, 2013)

Rename /sbin/zfs to /sbin/zfs.bin and write a shell script wrapper that passes everything through except certain dangerous commands.

```
warning: attempt to destroy ZFS filesystem
if you really want to do this, run
/sbin/zfs.bin destroy ...
```


----------



## mg16373 (Feb 21, 2013)

wblock@ said:
			
		

> Rename /sbin/zfs to /sbin/zfs.bin and write a shell script wrapper that passes everything through except certain dangerous commands.
> 
> ```
> warning: attempt to destroy ZFS filesystem
> ...



Thank you but this is only a workaround for me. I have begun to modify the source tree of zfs to add the functionality. I don't know how long the work needed.


----------



## throAU (Feb 22, 2013)

Sebulon said:
			
		

> "UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things."



Whilst this is true, having the *ability* to secure a filesystem from accidental deletion doesn't stop you doing clever things.  It makes doing clever things safer.

I don't think anyone sane could argue that having a flag or some other way (as mentioned, a snapshot on "hold") to enable the admin (if he/she so chooses) to prevent accidental filesytem destruction is a bad thing.



			
				wblock@ said:
			
		

> Rename /sbin/zfs to /sbin/zfs.bin and write a shell script wrapper that passes everything through except certain dangerous commands.
> 
> ```
> warning: attempt to destroy ZFS filesystem
> ...




Whilst this is a good idea in theory, if I understand the OP correctly, one of the reasons for requesting this feature is to protect against buggy scripts as well as human error during interactive shell.

Writing yourself a wrapper relies on you writing the wrapper to be bug-free 

We have filesystem flags to prevent unlinking files (e.g. chflags sunlink) - having this sort of thing at the filesystem level (which is potentially *far* more disastrous) is IMHO a good idea.


----------



## Savagedlight (Feb 22, 2013)

I would really love to see this implemented, as it is far too easy to destroy a pool right now. Adding an optional blockage on a pool (or file system) level would certainly reduce the amount of adrenaline involved in such tasks.

mg16373: How about using the delegation system for now? (see 'allow' in the zfs man page)
Make a new unprivileged user dedicated to ZFS maintenance, which have access to everything but the dangerous commands you'd like a lock on. This only works for the file systems, and not the pool itself... but it should definitely make it harder to do the mistake, as you'd be maintaining ZFS on an user without access to either of the destroy commands.


----------



## RusDyr (Feb 28, 2013)

I agree with the need for such a property. What's against just extending the "hold" property on the zpool and the filesystem without any snapshot?


----------

