summaryrefslogtreecommitdiffstats
path: root/module/zfs/dsl_dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/dsl_dir.c')
-rw-r--r--module/zfs/dsl_dir.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c
index 5b6ce0420..b3b677fb8 100644
--- a/module/zfs/dsl_dir.c
+++ b/module/zfs/dsl_dir.c
@@ -25,6 +25,7 @@
* Copyright (c) 2014 Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
+ * Copyright (c) 2018, loli10K <[email protected]>. All rights reserved.
*/
#include <sys/dmu.h>
@@ -1888,6 +1889,8 @@ dsl_dir_rename_check(void *arg, dmu_tx_t *tx)
dsl_pool_t *dp = dmu_tx_pool(tx);
dsl_dir_t *dd, *newparent;
dsl_valid_rename_arg_t dvra;
+ dsl_dataset_t *parentds;
+ objset_t *parentos;
const char *mynewname;
int error;
@@ -1918,6 +1921,29 @@ dsl_dir_rename_check(void *arg, dmu_tx_t *tx)
return (SET_ERROR(EEXIST));
}
+ /* can't rename below anything but filesystems (eg. no ZVOLs) */
+ error = dsl_dataset_hold_obj(newparent->dd_pool,
+ dsl_dir_phys(newparent)->dd_head_dataset_obj, FTAG, &parentds);
+ if (error != 0) {
+ dsl_dir_rele(newparent, FTAG);
+ dsl_dir_rele(dd, FTAG);
+ return (error);
+ }
+ error = dmu_objset_from_ds(parentds, &parentos);
+ if (error != 0) {
+ dsl_dataset_rele(parentds, FTAG);
+ dsl_dir_rele(newparent, FTAG);
+ dsl_dir_rele(dd, FTAG);
+ return (error);
+ }
+ if (dmu_objset_type(parentos) != DMU_OST_ZFS) {
+ dsl_dataset_rele(parentds, FTAG);
+ dsl_dir_rele(newparent, FTAG);
+ dsl_dir_rele(dd, FTAG);
+ return (SET_ERROR(ZFS_ERR_WRONG_PARENT));
+ }
+ dsl_dataset_rele(parentds, FTAG);
+
ASSERT3U(strnlen(ddra->ddra_newname, ZFS_MAX_DATASET_NAME_LEN),
<, ZFS_MAX_DATASET_NAME_LEN);
ASSERT3U(strnlen(ddra->ddra_oldname, ZFS_MAX_DATASET_NAME_LEN),