15

Similar question exists but the solution (using mv) is awful because in this case it works as "copy, then remove" rather than pure "move".

So, I created a pool:

zpool create tank /dev/loop0

and rsynced my data from another storage in there directly so that my data is now in /tank.

zfs list
NAME      USED  AVAIL  REFER  MOUNTPOINT
tank      591G  2.10T   591G  /tank

Now I've realized that I need my data to be in a child filesystem, not in /tank filesystem directly.

So how do I move or rename the existing root filesystem so that it becomes a child within the pool?

Simple rename won't work:

zfs rename tank tank/mydata
cannot rename to 'tank/mydata': datasets must be within same pool

(Btw, why does it complain the datasets are not within same pool when if fact I only have one pool?)

I know there are solutions that involve copying all the data (mv, or sending the whole dataset to another device and back), but shouldn't there be a simple elegant way?

Just noting that I do not care of snapshots at this stage (there are none yet to care of).

Anton
  • 151
  • 1
  • 1
  • 3

4 Answers4

8

Given the problem documented by @USDMatt, ZFS send/receive is probably the best way to go.

zfs snapshot tank@snap
zfs send tank@snap | zfs receive tank/anotherfs
zfs set mountpoint=/beep/boop tank/anotherfs
rm -rf /tank/*
zfs destroy tank@snap

Watch out when running the rm -rf if you don't change the mount point of if you have other filesystems in your tank zpool. You don't want to recursively remove the contents of the new filesystem (/tank/newname) or any other child filesystems (/tank/*) accidentally.

notpeter
  • 3,505
  • 1
  • 24
  • 44
  • This is interesting. Would this work if the drive was near full? or would it need 50% freespace? Im trying to rename a root level pool only. If i have to recreate the datasets (maybe 40) after, im not even sure what that may look like, at this point. – Brian Thomas Jul 01 '21 at 21:49
5

(see notes in comments, this works, but you'll never be able to delete initial the snapshot, so it's not a good solution)

With ZFS this is surprisingly straightforward: just snapshot, clone and then rm. No extra space or copy time required.

zfs snapshot tank@mydata
zfs clone tank@mydata tank/newname
zfs set mountpoint=/beep/boop tank/newname
rm -rf /tank/*

Watch out when running the rm -rf if you don't change the mount point of if you have other filesystems in your zpool. You don't want to recursively remove the contents of the new filesystem (/tank/newname) or any other child filesystems (tank/*) accidentally. Once you've confirmed your files are not in the root fs (/tank/) and only in your new filesystem, you can also delete that initial snapshot.

zfs delete tank@mydata
notpeter
  • 3,505
  • 1
  • 24
  • 44
  • 1
    Seems like a plausible answer (I can't think of any other way to get the data into a new dataset without moving it) but unfortunately you can't delete this original snapshot. Clones have a few awkward side effects. You can't delete tank@mydata as the new dataset depends on it. You can promote the new dataset, which will move tank@mydata to tank/newname@mydata, but now you've swapped the dependency around and you get funny 'dataset already exists' errors if you try and remove the new dataset (At least on FreeBSD, although I assume this is likely ZFS specific rather than OS). – USD Matt Dec 07 '12 at 14:56
  • 2
    @USDMatt: You are totally right. This works perfectly if you're working with subfileystems (tank/a -> tank/a@snap -> tank/asnap-clone -> tank/renamed-asnap-clone) but not if you're working at the root of the zpool. Feels like a bug, chalk it up as another reason to never fill the root filesystem of your pool). – notpeter Dec 07 '12 at 15:21
  • 2
    Here is some possibly related commentary about the special nature of the root dataset. https://github.com/openzfs/zfs/issues/3699#issuecomment-140314874 – mpb Jul 07 '20 at 19:34
  • I'm looking for a solution to rename the root, not into a child, so the above two comments(first one by `USDMatt`, then the concur by `notpeter`) are most important. e.g. "only if working for subfilesystems" I have populated data, and want to rename my whole tank's top level dir, because the name has purpose built into it, and i realize its main purpose now, haha. was `vault` will become either `backup` or `duplicate` or whatever AWS calls their 2nd az's, because its just dup backup data, but i dont want to have to repoplute the whole thing when i rename it. – Brian Thomas Jul 01 '21 at 21:46
  • darn it, can somebody fix my vote to an upvote here? not sure how it got locked into a downvote?? or did somebody already downvote me elsehow??? Sometimes the point system thingy here really bugs.. – Brian Thomas Jul 01 '21 at 21:58
2

I don't think there's a simple elegant way... although you could just change your mountpoint...

mkdir /tank
zfs set mountpoint=/tank/mydata <possibly renamed tank set>

Or maybe rename tank and then mount it where you need it...

Either that, or create a filesystem in the right place and cp, mv, or zfs send/receive...

ewwhite
  • 194,921
  • 91
  • 434
  • 799
  • hmm, this is either antipattern or possibly, thinkingdeeper, a trojan horse of a good idea, because who would have thought. So i wonder what happens to the dir that the datasets are mounted onto now, if the drive is full already. would this work for that? This is just, for me, to satisfy semantics when reading the tanks top level dir name. e.g. nas/vault to nas/backup – Brian Thomas Jul 01 '21 at 21:54
0

was copying whole disk to a new dataset, then found out it was a root folder:/

zfs clone tank tank/mynewdataset && rm -rf /mnt/tank/ && zfs promote tank/mynewdataset

this made my root data appear in the 'child' dataset, and fixed 2 issues with other solutions: sizes are correct, copy didn't execute.

user533385
  • 66
  • 2