]>
Commit | Line | Data |
---|---|---|
ee154f01 BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License (the "License"). | |
6 | * You may not use this file except in compliance with the License. | |
7 | * | |
8 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
1d3ba0bf | 9 | * or https://opensource.org/licenses/CDDL-1.0. |
ee154f01 BB |
10 | * See the License for the specific language governing permissions |
11 | * and limitations under the License. | |
12 | * | |
13 | * When distributing Covered Code, include this CDDL HEADER in each | |
14 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 | * If applicable, add the following below this CDDL HEADER, with the | |
16 | * fields enclosed by brackets "[]" replaced with your own identifying | |
17 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 | * | |
19 | * CDDL HEADER END | |
20 | */ | |
21 | /* | |
22 | * Copyright (c) 2011, Lawrence Livermore National Security, LLC. | |
5475aada | 23 | * Copyright (c) 2015 by Chunwei Chen. All rights reserved. |
ee154f01 BB |
24 | */ |
25 | ||
26 | ||
278bee93 | 27 | #include <sys/zfs_ctldir.h> |
ee154f01 BB |
28 | #include <sys/zfs_vfsops.h> |
29 | #include <sys/zfs_vnops.h> | |
ebe7e575 | 30 | #include <sys/zfs_znode.h> |
24ef51f6 | 31 | #include <sys/dmu_objset.h> |
ee154f01 BB |
32 | #include <sys/vfs.h> |
33 | #include <sys/zpl.h> | |
9d36cdb6 | 34 | #include <sys/file.h> |
ee154f01 | 35 | |
ee154f01 | 36 | static struct dentry * |
8f195a90 | 37 | zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
ee154f01 | 38 | { |
81e97e21 | 39 | cred_t *cr = CRED(); |
ee154f01 | 40 | struct inode *ip; |
657ce253 | 41 | znode_t *zp; |
ee154f01 | 42 | int error; |
40d06e3c | 43 | fstrans_cookie_t cookie; |
c5d02870 RS |
44 | pathname_t *ppn = NULL; |
45 | pathname_t pn; | |
9d36cdb6 | 46 | int zfs_flags = 0; |
0037b49e | 47 | zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; |
ee154f01 | 48 | |
d6df043c | 49 | if (dlen(dentry) >= ZAP_MAXNAMELEN) |
d1d7e268 | 50 | return (ERR_PTR(-ENAMETOOLONG)); |
9878a89d | 51 | |
81e97e21 | 52 | crhold(cr); |
40d06e3c | 53 | cookie = spl_fstrans_mark(); |
c5d02870 RS |
54 | |
55 | /* If we are a case insensitive fs, we need the real name */ | |
0037b49e | 56 | if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { |
9d36cdb6 | 57 | zfs_flags = FIGNORECASE; |
da5e151f | 58 | pn_alloc(&pn); |
c5d02870 RS |
59 | ppn = &pn; |
60 | } | |
61 | ||
657ce253 MM |
62 | error = -zfs_lookup(ITOZ(dir), dname(dentry), &zp, |
63 | zfs_flags, cr, NULL, ppn); | |
40d06e3c | 64 | spl_fstrans_unmark(cookie); |
ee154f01 | 65 | ASSERT3S(error, <=, 0); |
81e97e21 | 66 | crfree(cr); |
ee154f01 | 67 | |
7b3e34ba BB |
68 | spin_lock(&dentry->d_lock); |
69 | dentry->d_time = jiffies; | |
70 | spin_unlock(&dentry->d_lock); | |
71 | ||
ee154f01 | 72 | if (error) { |
9d36cdb6 RS |
73 | /* |
74 | * If we have a case sensitive fs, we do not want to | |
75 | * insert negative entries, so return NULL for ENOENT. | |
76 | * Fall through if the error is not ENOENT. Also free memory. | |
77 | */ | |
78 | if (ppn) { | |
da5e151f | 79 | pn_free(ppn); |
9d36cdb6 RS |
80 | if (error == -ENOENT) |
81 | return (NULL); | |
82 | } | |
83 | ||
ee154f01 | 84 | if (error == -ENOENT) |
d1d7e268 | 85 | return (d_splice_alias(NULL, dentry)); |
ee154f01 | 86 | else |
d1d7e268 | 87 | return (ERR_PTR(error)); |
ee154f01 | 88 | } |
657ce253 | 89 | ip = ZTOI(zp); |
ee154f01 | 90 | |
c5d02870 RS |
91 | /* |
92 | * If we are case insensitive, call the correct function | |
93 | * to install the name. | |
94 | */ | |
95 | if (ppn) { | |
96 | struct dentry *new_dentry; | |
97 | struct qstr ci_name; | |
98 | ||
d5b897a6 | 99 | if (strcmp(dname(dentry), pn.pn_buf) == 0) { |
100 | new_dentry = d_splice_alias(ip, dentry); | |
101 | } else { | |
102 | ci_name.name = pn.pn_buf; | |
103 | ci_name.len = strlen(pn.pn_buf); | |
104 | new_dentry = d_add_ci(dentry, ip, &ci_name); | |
105 | } | |
da5e151f | 106 | pn_free(ppn); |
c5d02870 RS |
107 | return (new_dentry); |
108 | } else { | |
109 | return (d_splice_alias(ip, dentry)); | |
110 | } | |
ee154f01 BB |
111 | } |
112 | ||
ebe7e575 | 113 | void |
2a068a13 YY |
114 | zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, |
115 | zuserns_t *mnt_ns) | |
9fd91dae BB |
116 | { |
117 | vap->va_mask = ATTR_MODE; | |
118 | vap->va_mode = mode; | |
2a068a13 YY |
119 | |
120 | vap->va_uid = zfs_uid_from_mnt((struct user_namespace *)mnt_ns, | |
121 | crgetuid(cr)); | |
9fd91dae BB |
122 | |
123 | if (dir && dir->i_mode & S_ISGID) { | |
570d6edf | 124 | vap->va_gid = KGID_TO_SGID(dir->i_gid); |
9fd91dae BB |
125 | if (S_ISDIR(mode)) |
126 | vap->va_mode |= S_ISGID; | |
127 | } else { | |
2a068a13 YY |
128 | vap->va_gid = zfs_gid_from_mnt((struct user_namespace *)mnt_ns, |
129 | crgetgid(cr)); | |
9fd91dae BB |
130 | } |
131 | } | |
132 | ||
ee154f01 | 133 | static int |
e2a82961 CK |
134 | #ifdef HAVE_IOPS_CREATE_USERNS |
135 | zpl_create(struct user_namespace *user_ns, struct inode *dir, | |
136 | struct dentry *dentry, umode_t mode, bool flag) | |
137 | #else | |
066e8252 | 138 | zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) |
e2a82961 | 139 | #endif |
ee154f01 | 140 | { |
81e97e21 | 141 | cred_t *cr = CRED(); |
657ce253 | 142 | znode_t *zp; |
ee154f01 BB |
143 | vattr_t *vap; |
144 | int error; | |
40d06e3c | 145 | fstrans_cookie_t cookie; |
2a068a13 YY |
146 | #ifndef HAVE_IOPS_CREATE_USERNS |
147 | zuserns_t *user_ns = NULL; | |
148 | #endif | |
ee154f01 | 149 | |
81e97e21 | 150 | crhold(cr); |
d1d7e268 | 151 | vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); |
2a068a13 | 152 | zpl_vap_init(vap, dir, mode, cr, user_ns); |
ee154f01 | 153 | |
40d06e3c | 154 | cookie = spl_fstrans_mark(); |
657ce253 | 155 | error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, |
2a068a13 | 156 | mode, &zp, cr, 0, NULL, user_ns); |
e89260a1 | 157 | if (error == 0) { |
657ce253 | 158 | error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); |
214806c7 | 159 | if (error == 0) |
657ce253 | 160 | error = zpl_init_acl(ZTOI(zp), dir); |
214806c7 | 161 | |
161ed825 | 162 | if (error) { |
657ce253 | 163 | (void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0); |
161ed825 T |
164 | remove_inode_hash(ZTOI(zp)); |
165 | iput(ZTOI(zp)); | |
166 | } else { | |
167 | d_instantiate(dentry, ZTOI(zp)); | |
168 | } | |
e89260a1 BB |
169 | } |
170 | ||
a438ff0e | 171 | spl_fstrans_unmark(cookie); |
d1d7e268 | 172 | kmem_free(vap, sizeof (vattr_t)); |
81e97e21 | 173 | crfree(cr); |
ee154f01 BB |
174 | ASSERT3S(error, <=, 0); |
175 | ||
176 | return (error); | |
177 | } | |
178 | ||
179 | static int | |
e2a82961 CK |
180 | #ifdef HAVE_IOPS_MKNOD_USERNS |
181 | zpl_mknod(struct user_namespace *user_ns, struct inode *dir, | |
182 | struct dentry *dentry, umode_t mode, | |
183 | #else | |
066e8252 | 184 | zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, |
e2a82961 | 185 | #endif |
b39d3b9f | 186 | dev_t rdev) |
ee154f01 | 187 | { |
81e97e21 | 188 | cred_t *cr = CRED(); |
657ce253 | 189 | znode_t *zp; |
ee154f01 BB |
190 | vattr_t *vap; |
191 | int error; | |
40d06e3c | 192 | fstrans_cookie_t cookie; |
2a068a13 YY |
193 | #ifndef HAVE_IOPS_MKNOD_USERNS |
194 | zuserns_t *user_ns = NULL; | |
195 | #endif | |
ee154f01 | 196 | |
aa6d8c10 NB |
197 | /* |
198 | * We currently expect Linux to supply rdev=0 for all sockets | |
199 | * and fifos, but we want to know if this behavior ever changes. | |
200 | */ | |
201 | if (S_ISSOCK(mode) || S_ISFIFO(mode)) | |
202 | ASSERT(rdev == 0); | |
203 | ||
81e97e21 | 204 | crhold(cr); |
d1d7e268 | 205 | vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); |
2a068a13 | 206 | zpl_vap_init(vap, dir, mode, cr, user_ns); |
ee154f01 | 207 | vap->va_rdev = rdev; |
ee154f01 | 208 | |
40d06e3c | 209 | cookie = spl_fstrans_mark(); |
657ce253 | 210 | error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, |
2a068a13 | 211 | mode, &zp, cr, 0, NULL, user_ns); |
023699cd | 212 | if (error == 0) { |
657ce253 | 213 | error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); |
214806c7 | 214 | if (error == 0) |
657ce253 | 215 | error = zpl_init_acl(ZTOI(zp), dir); |
214806c7 | 216 | |
161ed825 | 217 | if (error) { |
657ce253 | 218 | (void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0); |
161ed825 T |
219 | remove_inode_hash(ZTOI(zp)); |
220 | iput(ZTOI(zp)); | |
221 | } else { | |
222 | d_instantiate(dentry, ZTOI(zp)); | |
223 | } | |
023699cd | 224 | } |
7b3e34ba | 225 | |
a438ff0e | 226 | spl_fstrans_unmark(cookie); |
d1d7e268 | 227 | kmem_free(vap, sizeof (vattr_t)); |
81e97e21 | 228 | crfree(cr); |
ee154f01 BB |
229 | ASSERT3S(error, <=, 0); |
230 | ||
34d5a5fd | 231 | return (error); |
ee154f01 BB |
232 | } |
233 | ||
ace1eae8 CC |
234 | #ifdef HAVE_TMPFILE |
235 | static int | |
0b1b66b4 RE |
236 | #ifdef HAVE_TMPFILE_USERNS |
237 | zpl_tmpfile(struct user_namespace *userns, struct inode *dir, | |
238 | struct dentry *dentry, umode_t mode) | |
239 | #else | |
066e8252 | 240 | zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) |
0b1b66b4 | 241 | #endif |
ace1eae8 CC |
242 | { |
243 | cred_t *cr = CRED(); | |
244 | struct inode *ip; | |
245 | vattr_t *vap; | |
246 | int error; | |
247 | fstrans_cookie_t cookie; | |
2a068a13 YY |
248 | #ifndef HAVE_TMPFILE_USERNS |
249 | zuserns_t *userns = NULL; | |
250 | #endif | |
ace1eae8 CC |
251 | |
252 | crhold(cr); | |
253 | vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); | |
ddb4e69d TK |
254 | /* |
255 | * The VFS does not apply the umask, therefore it is applied here | |
256 | * when POSIX ACLs are not enabled. | |
257 | */ | |
258 | if (!IS_POSIXACL(dir)) | |
259 | mode &= ~current_umask(); | |
2a068a13 | 260 | zpl_vap_init(vap, dir, mode, cr, userns); |
ace1eae8 CC |
261 | |
262 | cookie = spl_fstrans_mark(); | |
2a068a13 | 263 | error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL, userns); |
ace1eae8 CC |
264 | if (error == 0) { |
265 | /* d_tmpfile will do drop_nlink, so we should set it first */ | |
266 | set_nlink(ip, 1); | |
267 | d_tmpfile(dentry, ip); | |
268 | ||
269 | error = zpl_xattr_security_init(ip, dir, &dentry->d_name); | |
270 | if (error == 0) | |
271 | error = zpl_init_acl(ip, dir); | |
272 | /* | |
273 | * don't need to handle error here, file is already in | |
274 | * unlinked set. | |
275 | */ | |
276 | } | |
277 | ||
278 | spl_fstrans_unmark(cookie); | |
279 | kmem_free(vap, sizeof (vattr_t)); | |
280 | crfree(cr); | |
281 | ASSERT3S(error, <=, 0); | |
282 | ||
283 | return (error); | |
284 | } | |
285 | #endif | |
286 | ||
ee154f01 BB |
287 | static int |
288 | zpl_unlink(struct inode *dir, struct dentry *dentry) | |
289 | { | |
81e97e21 | 290 | cred_t *cr = CRED(); |
ee154f01 | 291 | int error; |
40d06e3c | 292 | fstrans_cookie_t cookie; |
0037b49e | 293 | zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; |
ee154f01 | 294 | |
81e97e21 | 295 | crhold(cr); |
40d06e3c | 296 | cookie = spl_fstrans_mark(); |
657ce253 | 297 | error = -zfs_remove(ITOZ(dir), dname(dentry), cr, 0); |
9d36cdb6 RS |
298 | |
299 | /* | |
300 | * For a CI FS we must invalidate the dentry to prevent the | |
301 | * creation of negative entries. | |
302 | */ | |
0037b49e | 303 | if (error == 0 && zfsvfs->z_case == ZFS_CASE_INSENSITIVE) |
9d36cdb6 RS |
304 | d_invalidate(dentry); |
305 | ||
40d06e3c | 306 | spl_fstrans_unmark(cookie); |
81e97e21 | 307 | crfree(cr); |
ee154f01 BB |
308 | ASSERT3S(error, <=, 0); |
309 | ||
310 | return (error); | |
311 | } | |
312 | ||
313 | static int | |
e2a82961 CK |
314 | #ifdef HAVE_IOPS_MKDIR_USERNS |
315 | zpl_mkdir(struct user_namespace *user_ns, struct inode *dir, | |
316 | struct dentry *dentry, umode_t mode) | |
317 | #else | |
066e8252 | 318 | zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
e2a82961 | 319 | #endif |
ee154f01 | 320 | { |
81e97e21 | 321 | cred_t *cr = CRED(); |
ee154f01 | 322 | vattr_t *vap; |
657ce253 | 323 | znode_t *zp; |
ee154f01 | 324 | int error; |
40d06e3c | 325 | fstrans_cookie_t cookie; |
2a068a13 YY |
326 | #ifndef HAVE_IOPS_MKDIR_USERNS |
327 | zuserns_t *user_ns = NULL; | |
328 | #endif | |
ee154f01 | 329 | |
81e97e21 | 330 | crhold(cr); |
d1d7e268 | 331 | vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); |
2a068a13 | 332 | zpl_vap_init(vap, dir, mode | S_IFDIR, cr, user_ns); |
ee154f01 | 333 | |
40d06e3c | 334 | cookie = spl_fstrans_mark(); |
2a068a13 YY |
335 | error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL, |
336 | user_ns); | |
023699cd | 337 | if (error == 0) { |
657ce253 | 338 | error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); |
214806c7 | 339 | if (error == 0) |
657ce253 | 340 | error = zpl_init_acl(ZTOI(zp), dir); |
214806c7 | 341 | |
161ed825 | 342 | if (error) { |
657ce253 | 343 | (void) zfs_rmdir(ITOZ(dir), dname(dentry), NULL, cr, 0); |
161ed825 T |
344 | remove_inode_hash(ZTOI(zp)); |
345 | iput(ZTOI(zp)); | |
346 | } else { | |
347 | d_instantiate(dentry, ZTOI(zp)); | |
348 | } | |
023699cd | 349 | } |
7b3e34ba | 350 | |
a438ff0e | 351 | spl_fstrans_unmark(cookie); |
d1d7e268 | 352 | kmem_free(vap, sizeof (vattr_t)); |
81e97e21 | 353 | crfree(cr); |
ee154f01 BB |
354 | ASSERT3S(error, <=, 0); |
355 | ||
356 | return (error); | |
357 | } | |
358 | ||
359 | static int | |
02730c33 | 360 | zpl_rmdir(struct inode *dir, struct dentry *dentry) |
ee154f01 | 361 | { |
81e97e21 | 362 | cred_t *cr = CRED(); |
ee154f01 | 363 | int error; |
40d06e3c | 364 | fstrans_cookie_t cookie; |
0037b49e | 365 | zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; |
ee154f01 | 366 | |
81e97e21 | 367 | crhold(cr); |
40d06e3c | 368 | cookie = spl_fstrans_mark(); |
657ce253 | 369 | error = -zfs_rmdir(ITOZ(dir), dname(dentry), NULL, cr, 0); |
9d36cdb6 RS |
370 | |
371 | /* | |
372 | * For a CI FS we must invalidate the dentry to prevent the | |
373 | * creation of negative entries. | |
374 | */ | |
0037b49e | 375 | if (error == 0 && zfsvfs->z_case == ZFS_CASE_INSENSITIVE) |
9d36cdb6 RS |
376 | d_invalidate(dentry); |
377 | ||
40d06e3c | 378 | spl_fstrans_unmark(cookie); |
81e97e21 | 379 | crfree(cr); |
ee154f01 BB |
380 | ASSERT3S(error, <=, 0); |
381 | ||
382 | return (error); | |
383 | } | |
384 | ||
385 | static int | |
e2a82961 CK |
386 | #ifdef HAVE_USERNS_IOPS_GETATTR |
387 | zpl_getattr_impl(struct user_namespace *user_ns, | |
388 | const struct path *path, struct kstat *stat, u32 request_mask, | |
389 | unsigned int query_flags) | |
390 | #else | |
a3478c07 OF |
391 | zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, |
392 | unsigned int query_flags) | |
e2a82961 | 393 | #endif |
ee154f01 | 394 | { |
ee154f01 | 395 | int error; |
40d06e3c | 396 | fstrans_cookie_t cookie; |
abbf0bd4 RY |
397 | struct inode *ip = path->dentry->d_inode; |
398 | znode_t *zp __maybe_unused = ITOZ(ip); | |
ee154f01 | 399 | |
40d06e3c | 400 | cookie = spl_fstrans_mark(); |
a3478c07 OF |
401 | |
402 | /* | |
abbf0bd4 | 403 | * XXX query_flags currently ignored. |
a3478c07 OF |
404 | */ |
405 | ||
e2a82961 | 406 | #ifdef HAVE_USERNS_IOPS_GETATTR |
abbf0bd4 | 407 | error = -zfs_getattr_fast(user_ns, ip, stat); |
e2a82961 | 408 | #else |
abbf0bd4 | 409 | error = -zfs_getattr_fast(kcred->user_ns, ip, stat); |
e2a82961 | 410 | #endif |
abbf0bd4 RY |
411 | |
412 | #ifdef STATX_BTIME | |
413 | if (request_mask & STATX_BTIME) { | |
414 | stat->btime = zp->z_btime; | |
415 | stat->result_mask |= STATX_BTIME; | |
416 | } | |
417 | #endif | |
418 | ||
419 | #ifdef STATX_ATTR_IMMUTABLE | |
420 | if (zp->z_pflags & ZFS_IMMUTABLE) | |
421 | stat->attributes |= STATX_ATTR_IMMUTABLE; | |
422 | stat->attributes_mask |= STATX_ATTR_IMMUTABLE; | |
423 | #endif | |
424 | ||
425 | #ifdef STATX_ATTR_APPEND | |
426 | if (zp->z_pflags & ZFS_APPENDONLY) | |
427 | stat->attributes |= STATX_ATTR_APPEND; | |
428 | stat->attributes_mask |= STATX_ATTR_APPEND; | |
429 | #endif | |
430 | ||
431 | #ifdef STATX_ATTR_NODUMP | |
432 | if (zp->z_pflags & ZFS_NODUMP) | |
433 | stat->attributes |= STATX_ATTR_NODUMP; | |
434 | stat->attributes_mask |= STATX_ATTR_NODUMP; | |
435 | #endif | |
436 | ||
40d06e3c | 437 | spl_fstrans_unmark(cookie); |
ee154f01 BB |
438 | ASSERT3S(error, <=, 0); |
439 | ||
440 | return (error); | |
441 | } | |
a3478c07 | 442 | ZPL_GETATTR_WRAPPER(zpl_getattr); |
ee154f01 BB |
443 | |
444 | static int | |
e2a82961 CK |
445 | #ifdef HAVE_SETATTR_PREPARE_USERNS |
446 | zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry, | |
447 | struct iattr *ia) | |
448 | #else | |
5484965a | 449 | zpl_setattr(struct dentry *dentry, struct iattr *ia) |
e2a82961 | 450 | #endif |
ee154f01 | 451 | { |
023699cd | 452 | struct inode *ip = dentry->d_inode; |
81e97e21 | 453 | cred_t *cr = CRED(); |
5484965a | 454 | vattr_t *vap; |
ee154f01 | 455 | int error; |
40d06e3c | 456 | fstrans_cookie_t cookie; |
ee154f01 | 457 | |
2a068a13 YY |
458 | #ifdef HAVE_SETATTR_PREPARE_USERNS |
459 | error = zpl_setattr_prepare(user_ns, dentry, ia); | |
460 | #else | |
e2a82961 | 461 | error = zpl_setattr_prepare(kcred->user_ns, dentry, ia); |
2a068a13 | 462 | #endif |
ee154f01 BB |
463 | if (error) |
464 | return (error); | |
465 | ||
81e97e21 | 466 | crhold(cr); |
d1d7e268 | 467 | vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); |
5484965a BB |
468 | vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK; |
469 | vap->va_mode = ia->ia_mode; | |
570d6edf RY |
470 | vap->va_uid = KUID_TO_SUID(ia->ia_uid); |
471 | vap->va_gid = KGID_TO_SGID(ia->ia_gid); | |
5484965a BB |
472 | vap->va_size = ia->ia_size; |
473 | vap->va_atime = ia->ia_atime; | |
474 | vap->va_mtime = ia->ia_mtime; | |
475 | vap->va_ctime = ia->ia_ctime; | |
476 | ||
795699a6 BB |
477 | if (vap->va_mask & ATTR_ATIME) |
478 | ip->i_atime = zpl_inode_timestamp_truncate(ia->ia_atime, ip); | |
704cd075 | 479 | |
40d06e3c | 480 | cookie = spl_fstrans_mark(); |
2a068a13 YY |
481 | #ifdef HAVE_SETATTR_PREPARE_USERNS |
482 | error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); | |
483 | #else | |
484 | error = -zfs_setattr(ITOZ(ip), vap, 0, cr, NULL); | |
485 | #endif | |
023699cd MM |
486 | if (!error && (ia->ia_valid & ATTR_MODE)) |
487 | error = zpl_chmod_acl(ip); | |
5484965a | 488 | |
a438ff0e | 489 | spl_fstrans_unmark(cookie); |
d1d7e268 | 490 | kmem_free(vap, sizeof (vattr_t)); |
81e97e21 | 491 | crfree(cr); |
ee154f01 BB |
492 | ASSERT3S(error, <=, 0); |
493 | ||
5484965a | 494 | return (error); |
ee154f01 BB |
495 | } |
496 | ||
497 | static int | |
e2a82961 CK |
498 | #ifdef HAVE_IOPS_RENAME_USERNS |
499 | zpl_rename2(struct user_namespace *user_ns, struct inode *sdip, | |
500 | struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, | |
501 | unsigned int flags) | |
502 | #else | |
b8d9e264 CC |
503 | zpl_rename2(struct inode *sdip, struct dentry *sdentry, |
504 | struct inode *tdip, struct dentry *tdentry, unsigned int flags) | |
e2a82961 | 505 | #endif |
ee154f01 | 506 | { |
81e97e21 | 507 | cred_t *cr = CRED(); |
ee154f01 | 508 | int error; |
40d06e3c | 509 | fstrans_cookie_t cookie; |
2a068a13 YY |
510 | #ifndef HAVE_IOPS_RENAME_USERNS |
511 | zuserns_t *user_ns = NULL; | |
512 | #endif | |
ee154f01 | 513 | |
b8d9e264 CC |
514 | /* We don't have renameat2(2) support */ |
515 | if (flags) | |
516 | return (-EINVAL); | |
517 | ||
81e97e21 | 518 | crhold(cr); |
40d06e3c | 519 | cookie = spl_fstrans_mark(); |
657ce253 | 520 | error = -zfs_rename(ITOZ(sdip), dname(sdentry), ITOZ(tdip), |
2a068a13 | 521 | dname(tdentry), cr, 0, user_ns); |
40d06e3c | 522 | spl_fstrans_unmark(cookie); |
81e97e21 | 523 | crfree(cr); |
ee154f01 BB |
524 | ASSERT3S(error, <=, 0); |
525 | ||
526 | return (error); | |
527 | } | |
528 | ||
e2a82961 | 529 | #if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS) |
b8d9e264 CC |
530 | static int |
531 | zpl_rename(struct inode *sdip, struct dentry *sdentry, | |
532 | struct inode *tdip, struct dentry *tdentry) | |
533 | { | |
534 | return (zpl_rename2(sdip, sdentry, tdip, tdentry, 0)); | |
535 | } | |
536 | #endif | |
537 | ||
ee154f01 | 538 | static int |
e2a82961 CK |
539 | #ifdef HAVE_IOPS_SYMLINK_USERNS |
540 | zpl_symlink(struct user_namespace *user_ns, struct inode *dir, | |
541 | struct dentry *dentry, const char *name) | |
542 | #else | |
ee154f01 | 543 | zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) |
e2a82961 | 544 | #endif |
ee154f01 | 545 | { |
81e97e21 | 546 | cred_t *cr = CRED(); |
ee154f01 | 547 | vattr_t *vap; |
657ce253 | 548 | znode_t *zp; |
ee154f01 | 549 | int error; |
40d06e3c | 550 | fstrans_cookie_t cookie; |
2a068a13 YY |
551 | #ifndef HAVE_IOPS_SYMLINK_USERNS |
552 | zuserns_t *user_ns = NULL; | |
553 | #endif | |
ee154f01 | 554 | |
81e97e21 | 555 | crhold(cr); |
d1d7e268 | 556 | vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); |
2a068a13 | 557 | zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr, user_ns); |
ee154f01 | 558 | |
40d06e3c | 559 | cookie = spl_fstrans_mark(); |
657ce253 | 560 | error = -zfs_symlink(ITOZ(dir), dname(dentry), vap, |
2a068a13 | 561 | (char *)name, &zp, cr, 0, user_ns); |
227bc969 | 562 | if (error == 0) { |
657ce253 | 563 | error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); |
161ed825 | 564 | if (error) { |
657ce253 | 565 | (void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0); |
161ed825 T |
566 | remove_inode_hash(ZTOI(zp)); |
567 | iput(ZTOI(zp)); | |
568 | } else { | |
569 | d_instantiate(dentry, ZTOI(zp)); | |
570 | } | |
227bc969 | 571 | } |
7b3e34ba | 572 | |
a438ff0e | 573 | spl_fstrans_unmark(cookie); |
d1d7e268 | 574 | kmem_free(vap, sizeof (vattr_t)); |
81e97e21 | 575 | crfree(cr); |
ee154f01 BB |
576 | ASSERT3S(error, <=, 0); |
577 | ||
578 | return (error); | |
579 | } | |
580 | ||
beeed459 BB |
581 | #if defined(HAVE_PUT_LINK_COOKIE) |
582 | static void | |
583 | zpl_put_link(struct inode *unused, void *cookie) | |
584 | { | |
585 | kmem_free(cookie, MAXPATHLEN); | |
586 | } | |
587 | #elif defined(HAVE_PUT_LINK_NAMEIDATA) | |
588 | static void | |
589 | zpl_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr) | |
590 | { | |
591 | const char *link = nd_get_link(nd); | |
592 | ||
593 | if (!IS_ERR(link)) | |
594 | kmem_free(link, MAXPATHLEN); | |
595 | } | |
596 | #elif defined(HAVE_PUT_LINK_DELAYED) | |
597 | static void | |
598 | zpl_put_link(void *ptr) | |
599 | { | |
600 | kmem_free(ptr, MAXPATHLEN); | |
601 | } | |
bd29109f | 602 | #endif |
beeed459 BB |
603 | |
604 | static int | |
605 | zpl_get_link_common(struct dentry *dentry, struct inode *ip, char **link) | |
ee154f01 | 606 | { |
beeed459 | 607 | fstrans_cookie_t cookie; |
81e97e21 | 608 | cred_t *cr = CRED(); |
8b4f9a2d BB |
609 | int error; |
610 | ||
81e97e21 | 611 | crhold(cr); |
beeed459 | 612 | *link = NULL; |
1c2358c1 BB |
613 | |
614 | struct iovec iov; | |
8b4f9a2d | 615 | iov.iov_len = MAXPATHLEN; |
beeed459 | 616 | iov.iov_base = kmem_zalloc(MAXPATHLEN, KM_SLEEP); |
8b4f9a2d | 617 | |
d0cd9a5c BA |
618 | zfs_uio_t uio; |
619 | zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, MAXPATHLEN - 1, 0); | |
8b4f9a2d | 620 | |
40d06e3c | 621 | cookie = spl_fstrans_mark(); |
50950001 | 622 | error = -zfs_readlink(ip, &uio, cr); |
40d06e3c | 623 | spl_fstrans_unmark(cookie); |
bd29109f BB |
624 | crfree(cr); |
625 | ||
bd29109f | 626 | if (error) |
beeed459 | 627 | kmem_free(iov.iov_base, MAXPATHLEN); |
bd29109f | 628 | else |
beeed459 | 629 | *link = iov.iov_base; |
8b4f9a2d | 630 | |
beeed459 BB |
631 | return (error); |
632 | } | |
633 | ||
634 | #if defined(HAVE_GET_LINK_DELAYED) | |
65c7cc49 | 635 | static const char * |
beeed459 BB |
636 | zpl_get_link(struct dentry *dentry, struct inode *inode, |
637 | struct delayed_call *done) | |
638 | { | |
639 | char *link = NULL; | |
640 | int error; | |
641 | ||
642 | if (!dentry) | |
643 | return (ERR_PTR(-ECHILD)); | |
644 | ||
645 | error = zpl_get_link_common(dentry, inode, &link); | |
bd29109f BB |
646 | if (error) |
647 | return (ERR_PTR(error)); | |
beeed459 BB |
648 | |
649 | set_delayed_call(done, zpl_put_link, link); | |
650 | ||
651 | return (link); | |
ee154f01 | 652 | } |
beeed459 | 653 | #elif defined(HAVE_GET_LINK_COOKIE) |
65c7cc49 | 654 | static const char * |
beeed459 BB |
655 | zpl_get_link(struct dentry *dentry, struct inode *inode, void **cookie) |
656 | { | |
657 | char *link = NULL; | |
658 | int error; | |
ee154f01 | 659 | |
beeed459 BB |
660 | if (!dentry) |
661 | return (ERR_PTR(-ECHILD)); | |
662 | ||
663 | error = zpl_get_link_common(dentry, inode, &link); | |
664 | if (error) | |
665 | return (ERR_PTR(error)); | |
666 | ||
667 | return (*cookie = link); | |
668 | } | |
669 | #elif defined(HAVE_FOLLOW_LINK_COOKIE) | |
65c7cc49 | 670 | static const char * |
beeed459 | 671 | zpl_follow_link(struct dentry *dentry, void **cookie) |
ee154f01 | 672 | { |
beeed459 BB |
673 | char *link = NULL; |
674 | int error; | |
ee154f01 | 675 | |
beeed459 BB |
676 | error = zpl_get_link_common(dentry, dentry->d_inode, &link); |
677 | if (error) | |
678 | return (ERR_PTR(error)); | |
679 | ||
680 | return (*cookie = link); | |
ee154f01 | 681 | } |
beeed459 BB |
682 | #elif defined(HAVE_FOLLOW_LINK_NAMEIDATA) |
683 | static void * | |
684 | zpl_follow_link(struct dentry *dentry, struct nameidata *nd) | |
bd29109f | 685 | { |
beeed459 BB |
686 | char *link = NULL; |
687 | int error; | |
688 | ||
689 | error = zpl_get_link_common(dentry, dentry->d_inode, &link); | |
690 | if (error) | |
691 | nd_set_link(nd, ERR_PTR(error)); | |
692 | else | |
693 | nd_set_link(nd, link); | |
694 | ||
695 | return (NULL); | |
bd29109f BB |
696 | } |
697 | #endif | |
ee154f01 BB |
698 | |
699 | static int | |
700 | zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |
701 | { | |
81e97e21 | 702 | cred_t *cr = CRED(); |
ee154f01 | 703 | struct inode *ip = old_dentry->d_inode; |
ee154f01 | 704 | int error; |
40d06e3c | 705 | fstrans_cookie_t cookie; |
ee154f01 BB |
706 | |
707 | if (ip->i_nlink >= ZFS_LINK_MAX) | |
d1d7e268 | 708 | return (-EMLINK); |
ee154f01 | 709 | |
81e97e21 | 710 | crhold(cr); |
2946a1a1 | 711 | ip->i_ctime = current_time(ip); |
1daad981 AM |
712 | /* Must have an existing ref, so igrab() cannot return NULL */ |
713 | VERIFY3P(igrab(ip), !=, NULL); | |
ee154f01 | 714 | |
40d06e3c | 715 | cookie = spl_fstrans_mark(); |
657ce253 | 716 | error = -zfs_link(ITOZ(dir), ITOZ(ip), dname(dentry), cr, 0); |
ee154f01 BB |
717 | if (error) { |
718 | iput(ip); | |
719 | goto out; | |
720 | } | |
721 | ||
722 | d_instantiate(dentry, ip); | |
723 | out: | |
a438ff0e | 724 | spl_fstrans_unmark(cookie); |
81e97e21 | 725 | crfree(cr); |
ee154f01 BB |
726 | ASSERT3S(error, <=, 0); |
727 | ||
728 | return (error); | |
729 | } | |
730 | ||
731 | const struct inode_operations zpl_inode_operations = { | |
ee154f01 BB |
732 | .setattr = zpl_setattr, |
733 | .getattr = zpl_getattr, | |
0fedeedd | 734 | #ifdef HAVE_GENERIC_SETXATTR |
ee154f01 BB |
735 | .setxattr = generic_setxattr, |
736 | .getxattr = generic_getxattr, | |
737 | .removexattr = generic_removexattr, | |
0fedeedd | 738 | #endif |
ee154f01 | 739 | .listxattr = zpl_xattr_list, |
b695c34e | 740 | #if defined(CONFIG_FS_POSIX_ACL) |
0420c126 | 741 | #if defined(HAVE_SET_ACL) |
742 | .set_acl = zpl_set_acl, | |
066e8252 | 743 | #endif /* HAVE_SET_ACL */ |
023699cd | 744 | .get_acl = zpl_get_acl, |
b695c34e | 745 | #endif /* CONFIG_FS_POSIX_ACL */ |
ee154f01 BB |
746 | }; |
747 | ||
748 | const struct inode_operations zpl_dir_inode_operations = { | |
ee154f01 BB |
749 | .create = zpl_create, |
750 | .lookup = zpl_lookup, | |
751 | .link = zpl_link, | |
752 | .unlink = zpl_unlink, | |
753 | .symlink = zpl_symlink, | |
754 | .mkdir = zpl_mkdir, | |
755 | .rmdir = zpl_rmdir, | |
756 | .mknod = zpl_mknod, | |
e2a82961 | 757 | #if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) |
b8d9e264 CC |
758 | .rename = zpl_rename2, |
759 | #else | |
ee154f01 | 760 | .rename = zpl_rename, |
ace1eae8 CC |
761 | #endif |
762 | #ifdef HAVE_TMPFILE | |
763 | .tmpfile = zpl_tmpfile, | |
b8d9e264 | 764 | #endif |
ee154f01 | 765 | .setattr = zpl_setattr, |
a6695d83 | 766 | .getattr = zpl_getattr, |
0fedeedd | 767 | #ifdef HAVE_GENERIC_SETXATTR |
a6695d83 BB |
768 | .setxattr = generic_setxattr, |
769 | .getxattr = generic_getxattr, | |
770 | .removexattr = generic_removexattr, | |
0fedeedd | 771 | #endif |
a6695d83 | 772 | .listxattr = zpl_xattr_list, |
b695c34e | 773 | #if defined(CONFIG_FS_POSIX_ACL) |
0420c126 | 774 | #if defined(HAVE_SET_ACL) |
775 | .set_acl = zpl_set_acl, | |
066e8252 | 776 | #endif /* HAVE_SET_ACL */ |
023699cd | 777 | .get_acl = zpl_get_acl, |
b695c34e | 778 | #endif /* CONFIG_FS_POSIX_ACL */ |
ee154f01 BB |
779 | }; |
780 | ||
781 | const struct inode_operations zpl_symlink_inode_operations = { | |
a5e046ea | 782 | #ifdef HAVE_GENERIC_READLINK |
ee154f01 | 783 | .readlink = generic_readlink, |
a5e046ea | 784 | #endif |
beeed459 BB |
785 | #if defined(HAVE_GET_LINK_DELAYED) || defined(HAVE_GET_LINK_COOKIE) |
786 | .get_link = zpl_get_link, | |
787 | #elif defined(HAVE_FOLLOW_LINK_COOKIE) || defined(HAVE_FOLLOW_LINK_NAMEIDATA) | |
ee154f01 | 788 | .follow_link = zpl_follow_link, |
beeed459 BB |
789 | #endif |
790 | #if defined(HAVE_PUT_LINK_COOKIE) || defined(HAVE_PUT_LINK_NAMEIDATA) | |
ee154f01 | 791 | .put_link = zpl_put_link, |
beeed459 | 792 | #endif |
6f2255ba BB |
793 | .setattr = zpl_setattr, |
794 | .getattr = zpl_getattr, | |
0fedeedd | 795 | #ifdef HAVE_GENERIC_SETXATTR |
f31b3ebe BB |
796 | .setxattr = generic_setxattr, |
797 | .getxattr = generic_getxattr, | |
798 | .removexattr = generic_removexattr, | |
0fedeedd | 799 | #endif |
f31b3ebe | 800 | .listxattr = zpl_xattr_list, |
ee154f01 BB |
801 | }; |
802 | ||
803 | const struct inode_operations zpl_special_inode_operations = { | |
a6695d83 BB |
804 | .setattr = zpl_setattr, |
805 | .getattr = zpl_getattr, | |
0fedeedd | 806 | #ifdef HAVE_GENERIC_SETXATTR |
a6695d83 BB |
807 | .setxattr = generic_setxattr, |
808 | .getxattr = generic_getxattr, | |
809 | .removexattr = generic_removexattr, | |
0fedeedd | 810 | #endif |
a6695d83 | 811 | .listxattr = zpl_xattr_list, |
b695c34e | 812 | #if defined(CONFIG_FS_POSIX_ACL) |
0420c126 | 813 | #if defined(HAVE_SET_ACL) |
814 | .set_acl = zpl_set_acl, | |
066e8252 | 815 | #endif /* HAVE_SET_ACL */ |
023699cd | 816 | .get_acl = zpl_get_acl, |
b695c34e | 817 | #endif /* CONFIG_FS_POSIX_ACL */ |
ee154f01 | 818 | }; |