@@ -769,9 +769,6 @@ zfsctl_snapshot_path_objset(zfsvfs_t *zfsvfs, uint64_t objsetid,
769
769
uint64_t id , pos = 0 ;
770
770
int error = 0 ;
771
771
772
- if (zfsvfs -> z_vfs -> vfs_mntpoint == NULL )
773
- return (SET_ERROR (ENOENT ));
774
-
775
772
cookie = spl_fstrans_mark ();
776
773
snapname = kmem_alloc (ZFS_MAX_DATASET_NAME_LEN , KM_SLEEP );
777
774
@@ -788,8 +785,14 @@ zfsctl_snapshot_path_objset(zfsvfs_t *zfsvfs, uint64_t objsetid,
788
785
break ;
789
786
}
790
787
791
- snprintf (full_path , path_len , "%s/.zfs/snapshot/%s" ,
792
- zfsvfs -> z_vfs -> vfs_mntpoint , snapname );
788
+ mutex_enter (& zfsvfs -> z_vfs -> vfs_mntpt_lock );
789
+ if (zfsvfs -> z_vfs -> vfs_mntpoint != NULL ) {
790
+ snprintf (full_path , path_len , "%s/.zfs/snapshot/%s" ,
791
+ zfsvfs -> z_vfs -> vfs_mntpoint , snapname );
792
+ } else
793
+ error = SET_ERROR (ENOENT );
794
+ mutex_exit (& zfsvfs -> z_vfs -> vfs_mntpt_lock );
795
+
793
796
out :
794
797
kmem_free (snapname , ZFS_MAX_DATASET_NAME_LEN );
795
798
spl_fstrans_unmark (cookie );
@@ -1049,6 +1052,66 @@ exportfs_flush(void)
1049
1052
(void ) call_usermodehelper (argv [0 ], argv , envp , UMH_WAIT_PROC );
1050
1053
}
1051
1054
1055
+ /*
1056
+ * Returns the path in char format for given struct path. Uses
1057
+ * d_path exported by kernel to convert struct path to char
1058
+ * format. Returns the correct path for mountpoints and chroot
1059
+ * environments.
1060
+ *
1061
+ * If chroot environment has directories that are mounted with
1062
+ * --bind or --rbind flag, d_path returns the complete path inside
1063
+ * chroot environment but does not return the absolute path, i.e.
1064
+ * the path to chroot environment is missing.
1065
+ */
1066
+ static int
1067
+ get_root_path (struct path * path , char * buff , int len )
1068
+ {
1069
+ char * path_buffer , * path_ptr ;
1070
+ int error = 0 ;
1071
+
1072
+ path_get (path );
1073
+ path_buffer = kmem_zalloc (len , KM_SLEEP );
1074
+ path_ptr = d_path (path , path_buffer , len );
1075
+ if (IS_ERR (path_ptr ))
1076
+ error = SET_ERROR (- PTR_ERR (path_ptr ));
1077
+ else
1078
+ strcpy (buff , path_ptr );
1079
+
1080
+ kmem_free (path_buffer , len );
1081
+ path_put (path );
1082
+ return (error );
1083
+ }
1084
+
1085
+ /*
1086
+ * Returns if the current process root is chrooted or not. Linux
1087
+ * kernel exposes the task_struct for current process and init.
1088
+ * Since init process root points to actual root filesystem when
1089
+ * Linux runtime is reached, we can compare the current process
1090
+ * root with init process root to determine if root of the current
1091
+ * process is different from init, which can reliably determine if
1092
+ * current process is in chroot context or not.
1093
+ */
1094
+ static int
1095
+ is_current_chrooted (void )
1096
+ {
1097
+ struct task_struct * curr = current , * global = & init_task ;
1098
+ struct path cr_root , gl_root ;
1099
+
1100
+ task_lock (curr );
1101
+ get_fs_root (curr -> fs , & cr_root );
1102
+ task_unlock (curr );
1103
+
1104
+ task_lock (global );
1105
+ get_fs_root (global -> fs , & gl_root );
1106
+ task_unlock (global );
1107
+
1108
+ int chrooted = !path_equal (& cr_root , & gl_root );
1109
+ path_put (& gl_root );
1110
+ path_put (& cr_root );
1111
+
1112
+ return (chrooted );
1113
+ }
1114
+
1052
1115
/*
1053
1116
* Attempt to unmount a snapshot by making a call to user space.
1054
1117
* There is no assurance that this can or will succeed, is just a
@@ -1122,14 +1185,50 @@ zfsctl_snapshot_mount(struct path *path, int flags)
1122
1185
if (error )
1123
1186
goto error ;
1124
1187
1188
+ if (is_current_chrooted () == 0 ) {
1189
+ /*
1190
+ * Current process is not in chroot context
1191
+ */
1192
+
1193
+ char * m = kmem_zalloc (MAXPATHLEN , KM_SLEEP );
1194
+ struct path mnt_path ;
1195
+ mnt_path .mnt = path -> mnt ;
1196
+ mnt_path .dentry = path -> mnt -> mnt_root ;
1197
+
1198
+ /*
1199
+ * Get path to current mountpoint
1200
+ */
1201
+ error = get_root_path (& mnt_path , m , MAXPATHLEN );
1202
+ if (error != 0 ) {
1203
+ kmem_free (m , MAXPATHLEN );
1204
+ goto error ;
1205
+ }
1206
+ mutex_enter (& zfsvfs -> z_vfs -> vfs_mntpt_lock );
1207
+ if (zfsvfs -> z_vfs -> vfs_mntpoint != NULL ) {
1208
+ /*
1209
+ * If current mnountpoint and vfs_mntpoint are not same,
1210
+ * store current mountpoint in vfs_mntpoint.
1211
+ */
1212
+ if (strcmp (zfsvfs -> z_vfs -> vfs_mntpoint , m ) != 0 ) {
1213
+ kmem_strfree (zfsvfs -> z_vfs -> vfs_mntpoint );
1214
+ zfsvfs -> z_vfs -> vfs_mntpoint = kmem_strdup (m );
1215
+ }
1216
+ } else
1217
+ zfsvfs -> z_vfs -> vfs_mntpoint = kmem_strdup (m );
1218
+ mutex_exit (& zfsvfs -> z_vfs -> vfs_mntpt_lock );
1219
+ kmem_free (m , MAXPATHLEN );
1220
+ }
1221
+
1125
1222
/*
1126
1223
* Construct a mount point path from sb of the ctldir inode and dirent
1127
1224
* name, instead of from d_path(), so that chroot'd process doesn't fail
1128
1225
* on mount.zfs(8).
1129
1226
*/
1227
+ mutex_enter (& zfsvfs -> z_vfs -> vfs_mntpt_lock );
1130
1228
snprintf (full_path , MAXPATHLEN , "%s/.zfs/snapshot/%s" ,
1131
1229
zfsvfs -> z_vfs -> vfs_mntpoint ? zfsvfs -> z_vfs -> vfs_mntpoint : "" ,
1132
1230
dname (dentry ));
1231
+ mutex_exit (& zfsvfs -> z_vfs -> vfs_mntpt_lock );
1133
1232
1134
1233
/*
1135
1234
* Multiple concurrent automounts of a snapshot are never allowed.
0 commit comments