1 /* $OpenBSD: tmpfs_vnops.c,v 1.56 2024/10/18 05:52:32 miod Exp $ */
2 /* $NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $ */
3
4 /*
5 * Copyright (c) 2005, 2006, 2007, 2012 The NetBSD Foundation, Inc.
6 * Copyright (c) 2013 Pedro Martelletto
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
11 * 2005 program, and by Taylor R Campbell.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 * tmpfs vnode interface.
37 */
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/fcntl.h>
42 #include <sys/event.h>
43 #include <sys/namei.h>
44 #include <sys/stat.h>
45 #include <sys/uio.h>
46 #include <sys/unistd.h>
47 #include <sys/vnode.h>
48 #include <sys/lockf.h>
49 #include <sys/file.h>
50
51 #include <miscfs/fifofs/fifo.h>
52 #include <tmpfs/tmpfs_vnops.h>
53 #include <tmpfs/tmpfs.h>
54
55 int tmpfs_kqfilter(void *v);
56
57 /*
58 * vnode operations vector used for files stored in a tmpfs file system.
59 */
60 const struct vops tmpfs_vops = {
61 .vop_lookup = tmpfs_lookup,
62 .vop_create = tmpfs_create,
63 .vop_mknod = tmpfs_mknod,
64 .vop_open = tmpfs_open,
65 .vop_close = tmpfs_close,
66 .vop_access = tmpfs_access,
67 .vop_getattr = tmpfs_getattr,
68 .vop_setattr = tmpfs_setattr,
69 .vop_read = tmpfs_read,
70 .vop_write = tmpfs_write,
71 .vop_ioctl = tmpfs_ioctl,
72 .vop_kqfilter = tmpfs_kqfilter,
73 .vop_revoke = vop_generic_revoke,
74 .vop_fsync = tmpfs_fsync,
75 .vop_remove = tmpfs_remove,
76 .vop_link = tmpfs_link,
77 .vop_rename = tmpfs_rename,
78 .vop_mkdir = tmpfs_mkdir,
79 .vop_rmdir = tmpfs_rmdir,
80 .vop_symlink = tmpfs_symlink,
81 .vop_readdir = tmpfs_readdir,
82 .vop_readlink = tmpfs_readlink,
83 .vop_abortop = vop_generic_abortop,
84 .vop_inactive = tmpfs_inactive,
85 .vop_reclaim = tmpfs_reclaim,
86 .vop_lock = tmpfs_lock,
87 .vop_unlock = tmpfs_unlock,
88 .vop_bmap = vop_generic_bmap,
89 .vop_strategy = tmpfs_strategy,
90 .vop_print = tmpfs_print,
91 .vop_islocked = tmpfs_islocked,
92 .vop_pathconf = tmpfs_pathconf,
93 .vop_advlock = tmpfs_advlock,
94 .vop_bwrite = tmpfs_bwrite,
95 };
96
97 /*
98 * tmpfs_lookup: path name traversal routine.
99 *
100 * Arguments: dvp (directory being searched), vpp (result),
101 * cnp (component name - path).
102 *
103 * => Caller holds a reference and lock on dvp.
104 * => We return looked-up vnode (vpp) locked, with a reference held.
105 */
106 int
tmpfs_lookup(void * v)107 tmpfs_lookup(void *v)
108 {
109 struct vop_lookup_args /* {
110 struct vnode *a_dvp;
111 struct vnode **a_vpp;
112 struct componentname *a_cnp;
113 } */ *ap = v;
114 struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp;
115 struct componentname *cnp = ap->a_cnp;
116 struct ucred *cred = cnp->cn_cred;
117 const int lastcn = (cnp->cn_flags & ISLASTCN) != 0;
118 const int lockparent = (cnp->cn_flags & LOCKPARENT) != 0;
119 tmpfs_node_t *dnode, *tnode;
120 tmpfs_dirent_t *de;
121 int cachefound;
122 int error;
123
124 KASSERT(VOP_ISLOCKED(dvp));
125
126 dnode = VP_TO_TMPFS_DIR(dvp);
127 cnp->cn_flags &= ~PDIRUNLOCK;
128 *vpp = NULL;
129
130 /* Check accessibility of directory. */
131 error = VOP_ACCESS(dvp, VEXEC, cred, curproc);
132 if (error) {
133 goto out;
134 }
135
136 /*
137 * If requesting the last path component on a read-only file system
138 * with a write operation, deny it.
139 */
140 if (lastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) != 0 &&
141 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
142 error = EROFS;
143 goto out;
144 }
145
146 /*
147 * Avoid doing a linear scan of the directory if the requested
148 * directory/name couple is already in the cache.
149 */
150 cachefound = cache_lookup(dvp, vpp, cnp);
151 if (cachefound == ENOENT /* && *vpp == NULLVP */)
152 return ENOENT; /* Negative cache hit. */
153 else if (cachefound != -1)
154 return 0; /* Found in cache. */
155
156 if (cnp->cn_flags & ISDOTDOT) {
157 tmpfs_node_t *pnode;
158
159 /*
160 * Lookup of ".." case.
161 */
162 if (lastcn) {
163 if (cnp->cn_nameiop == RENAME) {
164 error = EINVAL;
165 goto out;
166 }
167 if (cnp->cn_nameiop == DELETE) {
168 /* Keep the name for tmpfs_rmdir(). */
169 cnp->cn_flags |= SAVENAME;
170 }
171 }
172 KASSERT(dnode->tn_type == VDIR);
173 pnode = dnode->tn_spec.tn_dir.tn_parent;
174 if (pnode == NULL) {
175 error = ENOENT;
176 goto out;
177 }
178
179 /*
180 * Lock the parent tn_nlock before releasing the vnode lock,
181 * and thus prevents parent from disappearing.
182 */
183 rw_enter_write(&pnode->tn_nlock);
184 VOP_UNLOCK(dvp);
185
186 /*
187 * Get a vnode of the '..' entry and re-acquire the lock.
188 * Release the tn_nlock.
189 */
190 error = tmpfs_vnode_get(dvp->v_mount, pnode, vpp);
191 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
192 goto out;
193
194 } else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
195 /*
196 * Lookup of "." case.
197 */
198 if (lastcn && cnp->cn_nameiop == RENAME) {
199 error = EISDIR;
200 goto out;
201 }
202 vref(dvp);
203 *vpp = dvp;
204 error = 0;
205 goto done;
206 }
207
208 /*
209 * Other lookup cases: perform directory scan.
210 */
211 de = tmpfs_dir_lookup(dnode, cnp);
212 if (de == NULL) {
213 /*
214 * The entry was not found in the directory. This is valid
215 * if we are creating or renaming an entry and are working
216 * on the last component of the path name.
217 */
218 if (lastcn && (cnp->cn_nameiop == CREATE ||
219 cnp->cn_nameiop == RENAME)) {
220 error = VOP_ACCESS(dvp, VWRITE, cred, curproc);
221 if (error) {
222 goto out;
223 }
224 /*
225 * We are creating an entry in the file system, so
226 * save its name for further use by tmpfs_create().
227 */
228 cnp->cn_flags |= SAVENAME;
229 error = EJUSTRETURN;
230 } else {
231 error = ENOENT;
232 }
233 goto done;
234 }
235
236 tnode = de->td_node;
237
238 /*
239 * If it is not the last path component and found a non-directory
240 * or non-link entry (which may itself be pointing to a directory),
241 * raise an error.
242 */
243 if (!lastcn && tnode->tn_type != VDIR && tnode->tn_type != VLNK) {
244 error = ENOTDIR;
245 goto out;
246 }
247
248 /* Check the permissions. */
249 if (lastcn && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
250 error = VOP_ACCESS(dvp, VWRITE, cred, curproc);
251 if (error)
252 goto out;
253
254 /*
255 * If not root and directory is sticky, check for permission
256 * on directory or on file. This implements append-only
257 * directories.
258 */
259 if ((dnode->tn_mode & S_ISTXT) != 0) {
260 if (cred->cr_uid != 0 &&
261 cred->cr_uid != dnode->tn_uid &&
262 cred->cr_uid != tnode->tn_uid) {
263 error = EPERM;
264 goto out;
265 }
266 }
267
268 /*
269 * XXX pedro: We might need cn_nameptr later in tmpfs_remove()
270 * or tmpfs_rmdir() for a tmpfs_dir_lookup(). We should really
271 * get rid of SAVENAME at some point.
272 */
273 if (cnp->cn_nameiop == DELETE)
274 cnp->cn_flags |= SAVENAME;
275 }
276
277 /* Get a vnode for the matching entry. */
278 rw_enter_write(&tnode->tn_nlock);
279 error = tmpfs_vnode_get(dvp->v_mount, tnode, vpp);
280 done:
281 /*
282 * Cache the result, unless request was for creation (as it does
283 * not improve the performance).
284 */
285 if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
286 cache_enter(dvp, *vpp, cnp);
287 }
288 out:
289 /*
290 * If (1) we succeeded, (2) found a distinct vnode != .. to return and (3)
291 * were either explicitly told to keep the parent locked or are in the
292 * middle of a lookup, unlock the parent vnode.
293 */
294 if ((error == 0 || error == EJUSTRETURN) && /* (1) */
295 (*vpp != dvp || (cnp->cn_flags & ISDOTDOT)) && /* (2) */
296 (!lockparent || !lastcn)) { /* (3) */
297 VOP_UNLOCK(dvp);
298 cnp->cn_flags |= PDIRUNLOCK;
299 } else
300 KASSERT(VOP_ISLOCKED(dvp));
301
302 KASSERT((*vpp && VOP_ISLOCKED(*vpp)) || error);
303
304 return error;
305 }
306
307 int
tmpfs_create(void * v)308 tmpfs_create(void *v)
309 {
310 struct vop_create_args /* {
311 struct vnode *a_dvp;
312 struct vnode **a_vpp;
313 struct componentname *a_cnp;
314 struct vattr *a_vap;
315 } */ *ap = v;
316 struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp;
317 struct componentname *cnp = ap->a_cnp;
318 struct vattr *vap = ap->a_vap;
319
320 KASSERT(VOP_ISLOCKED(dvp));
321 KASSERT(cnp->cn_flags & HASBUF);
322 KASSERT(vap->va_type == VREG || vap->va_type == VSOCK);
323 return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
324 }
325
326 int
tmpfs_mknod(void * v)327 tmpfs_mknod(void *v)
328 {
329 struct vop_mknod_args /* {
330 struct vnode *a_dvp;
331 struct vnode **a_vpp;
332 struct componentname *a_cnp;
333 struct vattr *a_vap;
334 } */ *ap = v;
335 struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp;
336 struct componentname *cnp = ap->a_cnp;
337 struct vattr *vap = ap->a_vap;
338 enum vtype vt = vap->va_type;
339 int error;
340
341 if (vt != VBLK && vt != VCHR && vt != VFIFO)
342 return EINVAL;
343
344 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
345
346 if (error == 0)
347 vput(*vpp);
348
349 return error;
350 }
351
352 int
tmpfs_open(void * v)353 tmpfs_open(void *v)
354 {
355 struct vop_open_args /* {
356 struct vnode *a_vp;
357 int a_mode;
358 kauth_cred_t a_cred;
359 } */ *ap = v;
360 struct vnode *vp = ap->a_vp;
361 mode_t mode = ap->a_mode;
362 tmpfs_node_t *node;
363
364 KASSERT(VOP_ISLOCKED(vp));
365
366 node = VP_TO_TMPFS_NODE(vp);
367 if (node->tn_links < 1) {
368 /*
369 * The file is still active, but all its names have been
370 * removed (e.g. by a "rmdir $(pwd)"). It cannot be opened
371 * any more, as it is about to be destroyed.
372 */
373 return ENOENT;
374 }
375
376 /* If the file is marked append-only, deny write requests. */
377 if ((node->tn_flags & APPEND) != 0 &&
378 (mode & (FWRITE | O_APPEND)) == FWRITE) {
379 return EPERM;
380 }
381 return 0;
382 }
383
384 int
tmpfs_close(void * v)385 tmpfs_close(void *v)
386 {
387 #ifdef DIAGNOSTIC
388 struct vop_close_args /* {
389 struct vnode *a_vp;
390 int a_fflag;
391 kauth_cred_t a_cred;
392 } */ *ap = v;
393 struct vnode *vp = ap->a_vp;
394
395 KASSERT(VOP_ISLOCKED(vp));
396 #endif
397 return 0;
398 }
399
400 int
tmpfs_access(void * v)401 tmpfs_access(void *v)
402 {
403 struct vop_access_args /* {
404 struct vnode *a_vp;
405 int a_mode;
406 kauth_cred_t a_cred;
407 } */ *ap = v;
408 struct vnode *vp = ap->a_vp;
409 mode_t mode = ap->a_mode;
410 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
411 const int writing = (mode & VWRITE) != 0;
412
413 KASSERT(VOP_ISLOCKED(vp));
414
415 /* Possible? */
416 switch (vp->v_type) {
417 case VDIR:
418 case VLNK:
419 case VREG:
420 if (writing && (vp->v_mount->mnt_flag & MNT_RDONLY) != 0) {
421 return EROFS;
422 }
423 break;
424 case VBLK:
425 case VCHR:
426 case VSOCK:
427 case VFIFO:
428 break;
429 default:
430 return EINVAL;
431 }
432 if (writing && (node->tn_flags & IMMUTABLE) != 0) {
433 return EPERM;
434 }
435
436 return (vaccess(vp->v_type, node->tn_mode, node->tn_uid, node->tn_gid,
437 mode, ap->a_cred));
438 }
439
440 int
tmpfs_getattr(void * v)441 tmpfs_getattr(void *v)
442 {
443 struct vop_getattr_args /* {
444 struct vnode *a_vp;
445 struct vattr *a_vap;
446 kauth_cred_t a_cred;
447 } */ *ap = v;
448 struct vnode *vp = ap->a_vp;
449 struct vattr *vap = ap->a_vap;
450 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
451
452 vattr_null(vap);
453
454 vap->va_type = vp->v_type;
455 vap->va_mode = node->tn_mode;
456 vap->va_nlink = node->tn_links;
457 vap->va_uid = node->tn_uid;
458 vap->va_gid = node->tn_gid;
459 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
460 vap->va_fileid = node->tn_id;
461 vap->va_size = node->tn_size;
462 vap->va_blocksize = PAGE_SIZE;
463 vap->va_atime = node->tn_atime;
464 vap->va_mtime = node->tn_mtime;
465 vap->va_ctime = node->tn_ctime;
466 /* vap->va_birthtime = node->tn_birthtime; */
467 vap->va_gen = TMPFS_NODE_GEN(node);
468 vap->va_flags = node->tn_flags;
469 vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ?
470 node->tn_spec.tn_dev.tn_rdev : VNOVAL;
471 vap->va_bytes = round_page(node->tn_size);
472 vap->va_filerev = VNOVAL;
473 vap->va_vaflags = 0;
474 vap->va_spare = VNOVAL; /* XXX */
475
476 return 0;
477 }
478
479 #define GOODTIME(tv) ((tv)->tv_nsec != VNOVAL)
480 /* XXX Should this operation be atomic? I think it should, but code in
481 * XXX other places (e.g., ufs) doesn't seem to be... */
482 int
tmpfs_setattr(void * v)483 tmpfs_setattr(void *v)
484 {
485 struct vop_setattr_args /* {
486 struct vnode *a_vp;
487 struct vattr *a_vap;
488 kauth_cred_t a_cred;
489 } */ *ap = v;
490 struct vnode *vp = ap->a_vp;
491 struct vattr *vap = ap->a_vap;
492 struct ucred *cred = ap->a_cred;
493 struct proc *p = curproc;
494 int error = 0;
495
496 KASSERT(VOP_ISLOCKED(vp));
497
498 /* Abort if any unsettable attribute is given. */
499 if (vap->va_type != VNON || vap->va_nlink != VNOVAL ||
500 vap->va_fsid != VNOVAL || vap->va_fileid != VNOVAL ||
501 vap->va_blocksize != VNOVAL || GOODTIME(&vap->va_ctime) ||
502 vap->va_gen != VNOVAL || vap->va_rdev != VNOVAL ||
503 vap->va_bytes != VNOVAL) {
504 return EINVAL;
505 }
506 if (error == 0 && (vap->va_flags != VNOVAL))
507 error = tmpfs_chflags(vp, vap->va_flags, cred, p);
508
509 if (error == 0 && (vap->va_size != VNOVAL))
510 error = tmpfs_chsize(vp, vap->va_size, cred, p);
511
512 if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL))
513 error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
514
515 if (error == 0 && (vap->va_mode != VNOVAL))
516 error = tmpfs_chmod(vp, vap->va_mode, cred, p);
517
518 if (error == 0 && ((vap->va_vaflags & VA_UTIMES_CHANGE)
519 || GOODTIME(&vap->va_atime)
520 || GOODTIME(&vap->va_mtime)))
521 error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime,
522 vap->va_vaflags, cred, p);
523
524 return error;
525 }
526
527 int
tmpfs_read(void * v)528 tmpfs_read(void *v)
529 {
530 struct vop_read_args /* {
531 struct vnode *a_vp;
532 struct uio *a_uio;
533 int a_ioflag;
534 struct ucred *a_cred;
535 } */ *ap = v;
536 struct vnode *vp = ap->a_vp;
537 struct uio *uio = ap->a_uio;
538 /* const int ioflag = ap->a_ioflag; */
539 tmpfs_node_t *node;
540 int error;
541
542 KASSERT(VOP_ISLOCKED(vp));
543
544 if (vp->v_type != VREG) {
545 return EISDIR;
546 }
547 if (uio->uio_offset < 0) {
548 return EINVAL;
549 }
550 if (uio->uio_resid == 0)
551 return 0;
552
553 node = VP_TO_TMPFS_NODE(vp);
554 error = 0;
555
556 while (error == 0 && uio->uio_resid > 0) {
557 vsize_t len;
558
559 if (node->tn_size <= uio->uio_offset) {
560 break;
561 }
562 len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid);
563 if (len == 0) {
564 break;
565 }
566 error = tmpfs_uiomove(node, uio, len);
567 }
568
569 if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
570 tmpfs_update(node, TMPFS_NODE_ACCESSED);
571
572 return error;
573 }
574
575 int
tmpfs_write(void * v)576 tmpfs_write(void *v)
577 {
578 struct vop_write_args /* {
579 struct vnode *a_vp;
580 struct uio *a_uio;
581 int a_ioflag;
582 kauth_cred_t a_cred;
583 } */ *ap = v;
584 struct vnode *vp = ap->a_vp;
585 struct uio *uio = ap->a_uio;
586 const int ioflag = ap->a_ioflag;
587 tmpfs_node_t *node;
588 off_t oldsize;
589 ssize_t overrun;
590 int extended;
591 int error;
592
593 KASSERT(VOP_ISLOCKED(vp));
594
595 node = VP_TO_TMPFS_NODE(vp);
596 oldsize = node->tn_size;
597
598 if (vp->v_type != VREG)
599 return (EINVAL);
600
601 if (uio->uio_resid == 0)
602 return (0);
603
604 if (ioflag & IO_APPEND) {
605 uio->uio_offset = node->tn_size;
606 }
607
608 if (uio->uio_offset < 0 ||
609 (u_int64_t)uio->uio_offset + uio->uio_resid > LLONG_MAX)
610 return (EFBIG);
611
612 /* do the filesize rlimit check */
613 if ((error = vn_fsizechk(vp, uio, ioflag, &overrun)))
614 return (error);
615
616 extended = uio->uio_offset + uio->uio_resid > node->tn_size;
617 if (extended) {
618 error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid);
619 if (error)
620 goto out;
621 }
622
623 error = 0;
624 while (error == 0 && uio->uio_resid > 0) {
625 vsize_t len;
626 uvm_vnp_uncache(vp);
627 len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid);
628 if (len == 0) {
629 break;
630 }
631 error = tmpfs_uiomove(node, uio, len);
632 }
633 if (error) {
634 (void)tmpfs_reg_resize(vp, oldsize);
635 }
636
637 tmpfs_update(node, TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED);
638 if (extended)
639 VN_KNOTE(vp, NOTE_WRITE | NOTE_EXTEND);
640 else
641 VN_KNOTE(vp, NOTE_WRITE);
642 out:
643 if (error) {
644 KASSERT(oldsize == node->tn_size);
645 } else {
646 KASSERT(uio->uio_resid == 0);
647
648 /* correct the result for writes clamped by vn_fsizechk() */
649 uio->uio_resid += overrun;
650
651 }
652 return error;
653 }
654
655 int
tmpfs_fsync(void * v)656 tmpfs_fsync(void *v)
657 {
658 #ifdef DIAGNOSTIC
659 struct vop_fsync_args /* {
660 struct vnode *a_vp;
661 struct ucred *a_cred;
662 int a_flags;
663 off_t a_offlo;
664 off_t a_offhi;
665 struct lwp *a_l;
666 } */ *ap = v;
667 struct vnode *vp = ap->a_vp;
668
669 /* Nothing to do. Just update. */
670 KASSERT(VOP_ISLOCKED(vp));
671 #endif
672 return 0;
673 }
674
675 /*
676 * tmpfs_remove: unlink a file.
677 *
678 * => Both directory (dvp) and file (vp) are locked.
679 * => We unlock and drop the reference on both.
680 */
681 int
tmpfs_remove(void * v)682 tmpfs_remove(void *v)
683 {
684 struct vop_remove_args /* {
685 struct vnode *a_dvp;
686 struct vnode *a_vp;
687 struct componentname *a_cnp;
688 } */ *ap = v;
689 struct vnode *dvp = ap->a_dvp, *vp = ap->a_vp;
690 struct componentname *cnp = ap->a_cnp;
691 tmpfs_node_t *dnode, *node;
692 tmpfs_dirent_t *de;
693 int error;
694
695 KASSERT(cnp->cn_flags & HASBUF);
696
697 if (vp->v_type == VDIR) {
698 error = EPERM;
699 goto out;
700 }
701
702 dnode = VP_TO_TMPFS_NODE(dvp);
703 node = VP_TO_TMPFS_NODE(vp);
704
705 /* Files marked as immutable or append-only cannot be deleted. */
706 if (node->tn_flags & (IMMUTABLE | APPEND)) {
707 error = EPERM;
708 goto out;
709 }
710
711 /*
712 * Likewise, files residing on directories marked as append-only cannot
713 * be deleted.
714 */
715 if (dnode->tn_flags & APPEND) {
716 error = EPERM;
717 goto out;
718 }
719
720 /* Lookup the directory entry (check the cached hint first). */
721 de = tmpfs_dir_cached(node);
722 if (de == NULL) {
723 de = tmpfs_dir_lookup(dnode, cnp);
724 }
725
726 KASSERT(de && de->td_node == node);
727
728 /*
729 * Remove the entry from the directory (drops the link count) and
730 * destroy it.
731 * Note: the inode referred by it will not be destroyed
732 * until the vnode is reclaimed/recycled.
733 */
734 tmpfs_dir_detach(dnode, de);
735 tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de);
736 if (node->tn_links > 0) {
737 /* We removed a hard link. */
738 tmpfs_update(node, TMPFS_NODE_CHANGED);
739 }
740 error = 0;
741 out:
742 pool_put(&namei_pool, cnp->cn_pnbuf);
743 return error;
744 }
745
746 /*
747 * tmpfs_link: create a hard link.
748 */
749 int
tmpfs_link(void * v)750 tmpfs_link(void *v)
751 {
752 struct vop_link_args /* {
753 struct vnode *a_dvp;
754 struct vnode *a_vp;
755 struct componentname *a_cnp;
756 } */ *ap = v;
757 struct vnode *dvp = ap->a_dvp;
758 struct vnode *vp = ap->a_vp;
759 struct componentname *cnp = ap->a_cnp;
760 tmpfs_node_t *dnode, *node;
761 tmpfs_dirent_t *de;
762 int error;
763
764 KASSERT(VOP_ISLOCKED(dvp));
765 KASSERT(dvp != vp);
766
767 dnode = VP_TO_TMPFS_DIR(dvp);
768 node = VP_TO_TMPFS_NODE(vp);
769
770 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
771
772 /* Check for maximum number of links limit. */
773 if (node->tn_links == LINK_MAX) {
774 error = EMLINK;
775 goto out;
776 }
777 KASSERT(node->tn_links < LINK_MAX);
778
779 /* We cannot create links of files marked immutable or append-only. */
780 if (node->tn_flags & (IMMUTABLE | APPEND)) {
781 error = EPERM;
782 goto out;
783 }
784
785 if (TMPFS_DIRSEQ_FULL(dnode)) {
786 error = ENOSPC;
787 goto out;
788 }
789
790 /* Allocate a new directory entry to represent the inode. */
791 error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount),
792 cnp->cn_nameptr, cnp->cn_namelen, &de);
793 if (error) {
794 goto out;
795 }
796
797 /*
798 * Insert the entry into the directory.
799 * It will increase the inode link count.
800 */
801 tmpfs_dir_attach(dnode, de, node);
802
803 /* Update the timestamps and trigger the event. */
804 if (node->tn_vnode) {
805 VN_KNOTE(node->tn_vnode, NOTE_LINK);
806 }
807 tmpfs_update(node, TMPFS_NODE_CHANGED);
808 error = 0;
809 out:
810 pool_put(&namei_pool, cnp->cn_pnbuf);
811 VOP_UNLOCK(vp);
812 vput(dvp);
813 return error;
814 }
815
816 int
tmpfs_mkdir(void * v)817 tmpfs_mkdir(void *v)
818 {
819 struct vop_mkdir_args /* {
820 struct vnode *a_dvp;
821 struct vnode **a_vpp;
822 struct componentname *a_cnp;
823 struct vattr *a_vap;
824 } */ *ap = v;
825 struct vnode *dvp = ap->a_dvp;
826 struct vnode **vpp = ap->a_vpp;
827 struct componentname *cnp = ap->a_cnp;
828 struct vattr *vap = ap->a_vap;
829 int error;
830
831 KASSERT(vap->va_type == VDIR);
832 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
833 vput(dvp);
834 return error;
835 }
836
837 int
tmpfs_rmdir(void * v)838 tmpfs_rmdir(void *v)
839 {
840 struct vop_rmdir_args /* {
841 struct vnode *a_dvp;
842 struct vnode *a_vp;
843 struct componentname *a_cnp;
844 } */ *ap = v;
845 struct vnode *dvp = ap->a_dvp;
846 struct vnode *vp = ap->a_vp;
847 struct componentname *cnp = ap->a_cnp;
848 tmpfs_mount_t *tmp = VFS_TO_TMPFS(dvp->v_mount);
849 tmpfs_node_t *dnode = VP_TO_TMPFS_DIR(dvp);
850 tmpfs_node_t *node = VP_TO_TMPFS_DIR(vp);
851 tmpfs_dirent_t *de;
852 int error = 0;
853
854 KASSERT(VOP_ISLOCKED(dvp));
855 KASSERT(VOP_ISLOCKED(vp));
856 KASSERT(cnp->cn_flags & HASBUF);
857
858 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[0] == '.' &&
859 cnp->cn_nameptr[1] == '.') {
860 error = ENOTEMPTY;
861 goto out;
862 }
863
864 KASSERT(node->tn_spec.tn_dir.tn_parent == dnode);
865
866 /*
867 * Directories with more than two entries ('.' and '..') cannot be
868 * removed.
869 */
870 if (node->tn_size > 0) {
871 KASSERT(error == 0);
872 TAILQ_FOREACH(de, &node->tn_spec.tn_dir.tn_dir, td_entries) {
873 error = ENOTEMPTY;
874 break;
875 }
876 if (error)
877 goto out;
878 }
879
880 /* Lookup the directory entry (check the cached hint first). */
881 de = tmpfs_dir_cached(node);
882 if (de == NULL)
883 de = tmpfs_dir_lookup(dnode, cnp);
884
885 KASSERT(de && de->td_node == node);
886
887 /* Check flags to see if we are allowed to remove the directory. */
888 if (dnode->tn_flags & APPEND || node->tn_flags & (IMMUTABLE | APPEND)) {
889 error = EPERM;
890 goto out;
891 }
892
893 /* Decrement the link count for the virtual '.' entry. */
894 node->tn_links--;
895 tmpfs_update(node, TMPFS_NODE_STATUSALL);
896
897 /* Detach the directory entry from the directory. */
898 tmpfs_dir_detach(dnode, de);
899
900 /* Purge the cache for parent. */
901 cache_purge(dvp);
902
903 /*
904 * Destroy the directory entry.
905 * Note: the inode referred by it will not be destroyed
906 * until the vnode is reclaimed.
907 */
908 tmpfs_free_dirent(tmp, de);
909 KASSERT(TAILQ_FIRST(&node->tn_spec.tn_dir.tn_dir) == NULL);
910
911 KASSERT(node->tn_links == 0);
912 out:
913 pool_put(&namei_pool, cnp->cn_pnbuf);
914 /* Release the nodes. */
915 vput(dvp);
916 vput(vp);
917 return error;
918 }
919
920 int
tmpfs_symlink(void * v)921 tmpfs_symlink(void *v)
922 {
923 struct vop_symlink_args /* {
924 struct vnode *a_dvp;
925 struct vnode **a_vpp;
926 struct componentname *a_cnp;
927 struct vattr *a_vap;
928 char *a_target;
929 } */ *ap = v;
930 struct vnode *dvp = ap->a_dvp;
931 struct vnode **vpp = ap->a_vpp;
932 struct componentname *cnp = ap->a_cnp;
933 struct vattr *vap = ap->a_vap;
934 char *target = ap->a_target;
935 int error;
936
937 KASSERT(vap->va_type == 0);
938 vap->va_type = VLNK;
939
940 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, target);
941 vput(dvp);
942 if (error == 0)
943 vput(*vpp);
944
945 return error;
946 }
947
948 int
tmpfs_readdir(void * v)949 tmpfs_readdir(void *v)
950 {
951 struct vop_readdir_args /* {
952 struct vnode *a_vp;
953 struct uio *a_uio;
954 kauth_cred_t a_cred;
955 int *a_eofflag;
956 } */ *ap = v;
957 struct vnode *vp = ap->a_vp;
958 struct uio *uio = ap->a_uio;
959 int *eofflag = ap->a_eofflag;
960 tmpfs_node_t *node;
961 int error;
962
963 KASSERT(VOP_ISLOCKED(vp));
964
965 /* This operation only makes sense on directory nodes. */
966 if (vp->v_type != VDIR) {
967 return ENOTDIR;
968 }
969 node = VP_TO_TMPFS_DIR(vp);
970 /*
971 * Retrieve the directory entries, unless it is being destroyed.
972 */
973 if (node->tn_links) {
974 error = tmpfs_dir_getdents(node, uio);
975 } else {
976 error = 0;
977 }
978
979 if (eofflag != NULL) {
980 *eofflag = !error && uio->uio_offset == TMPFS_DIRSEQ_EOF;
981 }
982 return error;
983 }
984
985 int
tmpfs_readlink(void * v)986 tmpfs_readlink(void *v)
987 {
988 struct vop_readlink_args /* {
989 struct vnode *a_vp;
990 struct uio *a_uio;
991 kauth_cred_t a_cred;
992 } */ *ap = v;
993 struct vnode *vp = ap->a_vp;
994 struct uio *uio = ap->a_uio;
995 tmpfs_node_t *node;
996 int error;
997
998 KASSERT(VOP_ISLOCKED(vp));
999 KASSERT(uio->uio_offset == 0);
1000 KASSERT(vp->v_type == VLNK);
1001
1002 node = VP_TO_TMPFS_NODE(vp);
1003 error = uiomove(node->tn_spec.tn_lnk.tn_link,
1004 MIN((size_t)node->tn_size, uio->uio_resid), uio);
1005
1006 if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
1007 tmpfs_update(node, TMPFS_NODE_ACCESSED);
1008
1009 return error;
1010 }
1011
1012 int
tmpfs_inactive(void * v)1013 tmpfs_inactive(void *v)
1014 {
1015 struct vop_inactive_args /* {
1016 struct vnode *a_vp;
1017 int *a_recycle;
1018 } */ *ap = v;
1019 struct vnode *vp = ap->a_vp;
1020 tmpfs_node_t *node;
1021
1022 KASSERT(VOP_ISLOCKED(vp));
1023
1024 node = VP_TO_TMPFS_NODE(vp);
1025
1026 if (vp->v_type == VREG && tmpfs_uio_cached(node))
1027 tmpfs_uio_uncache(node);
1028
1029 VOP_UNLOCK(vp);
1030
1031 /*
1032 * If we are done with the node, reclaim it so that it can be reused
1033 * immediately.
1034 */
1035 if (node->tn_links == 0)
1036 vrecycle(vp, curproc);
1037
1038 return 0;
1039 }
1040
1041 int
tmpfs_reclaim(void * v)1042 tmpfs_reclaim(void *v)
1043 {
1044 struct vop_reclaim_args /* {
1045 struct vnode *a_vp;
1046 } */ *ap = v;
1047 struct vnode *vp = ap->a_vp;
1048 tmpfs_mount_t *tmp = VFS_TO_TMPFS(vp->v_mount);
1049 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
1050 int racing;
1051
1052 /* Disassociate inode from vnode. */
1053 rw_enter_write(&node->tn_nlock);
1054 node->tn_vnode = NULL;
1055 vp->v_data = NULL;
1056 /* Check if tmpfs_vnode_get() is racing with us. */
1057 racing = TMPFS_NODE_RECLAIMING(node);
1058 rw_exit_write(&node->tn_nlock);
1059
1060 cache_purge(vp);
1061
1062 /*
1063 * If inode is not referenced, i.e. no links, then destroy it.
1064 * Note: if racing - inode is about to get a new vnode, leave it.
1065 */
1066 if (node->tn_links == 0 && !racing) {
1067 tmpfs_free_node(tmp, node);
1068 }
1069 return 0;
1070 }
1071
1072 int
tmpfs_pathconf(void * v)1073 tmpfs_pathconf(void *v)
1074 {
1075 struct vop_pathconf_args /* {
1076 struct vnode *a_vp;
1077 int a_name;
1078 register_t *a_retval;
1079 } */ *ap = v;
1080 const int name = ap->a_name;
1081 register_t *retval = ap->a_retval;
1082 int error = 0;
1083
1084 switch (name) {
1085 case _PC_LINK_MAX:
1086 *retval = LINK_MAX;
1087 break;
1088 case _PC_NAME_MAX:
1089 *retval = TMPFS_MAXNAMLEN;
1090 break;
1091 case _PC_CHOWN_RESTRICTED:
1092 *retval = 1;
1093 break;
1094 case _PC_NO_TRUNC:
1095 *retval = 1;
1096 break;
1097 case _PC_FILESIZEBITS:
1098 *retval = 64;
1099 break;
1100 case _PC_TIMESTAMP_RESOLUTION:
1101 *retval = 1;
1102 break;
1103 default:
1104 error = EINVAL;
1105 }
1106 return error;
1107 }
1108
1109 int
tmpfs_advlock(void * v)1110 tmpfs_advlock(void *v)
1111 {
1112 struct vop_advlock_args /* {
1113 struct vnode *a_vp;
1114 void * a_id;
1115 int a_op;
1116 struct flock *a_fl;
1117 int a_flags;
1118 } */ *ap = v;
1119 struct vnode *vp = ap->a_vp;
1120 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
1121
1122 return lf_advlock(&node->tn_lockf, node->tn_size, ap->a_id, ap->a_op,
1123 ap->a_fl, ap->a_flags);
1124 }
1125
1126 int
tmpfs_print(void * v)1127 tmpfs_print(void *v)
1128 {
1129 #if defined(DEBUG) || defined(DIAGNOSTIC) || defined(VFSLCKDEBUG)
1130 struct vop_print_args /* {
1131 struct vnode *a_vp;
1132 } */ *ap = v;
1133 struct vnode *vp = ap->a_vp;
1134 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
1135
1136 printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n"
1137 "\tmode 0%o, owner %d, group %d, size %lld",
1138 node, node->tn_flags, node->tn_links, node->tn_mode, node->tn_uid,
1139 node->tn_gid, node->tn_size);
1140 #ifdef FIFO
1141 if (vp->v_type == VFIFO)
1142 fifo_printinfo(vp);
1143 #endif
1144 printf("\n");
1145 #endif
1146 return 0;
1147 }
1148
1149 /* a null op */
1150 int
tmpfs_bwrite(void * v)1151 tmpfs_bwrite(void *v)
1152 {
1153 return 0;
1154 }
1155
1156 int
tmpfs_strategy(void * v)1157 tmpfs_strategy(void *v)
1158 {
1159 return EOPNOTSUPP;
1160 }
1161
1162 int
tmpfs_ioctl(void * v)1163 tmpfs_ioctl(void *v)
1164 {
1165 return ENOTTY;
1166 }
1167
1168 int
tmpfs_lock(void * v)1169 tmpfs_lock(void *v)
1170 {
1171 struct vop_lock_args *ap = v;
1172 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp);
1173
1174 return rrw_enter(&tnp->tn_vlock, ap->a_flags & LK_RWFLAGS);
1175 }
1176
1177 int
tmpfs_unlock(void * v)1178 tmpfs_unlock(void *v)
1179 {
1180 struct vop_unlock_args *ap = v;
1181 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp);
1182
1183 rrw_exit(&tnp->tn_vlock);
1184 return 0;
1185 }
1186
1187 int
tmpfs_islocked(void * v)1188 tmpfs_islocked(void *v)
1189 {
1190 struct vop_islocked_args *ap = v;
1191 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp);
1192
1193 return rrw_status(&tnp->tn_vlock);
1194 }
1195
1196 /*
1197 * tmpfs_rename: rename routine, the hairiest system call, with the
1198 * insane API.
1199 *
1200 * Arguments: fdvp (from-parent vnode), fvp (from-leaf), tdvp (to-parent)
1201 * and tvp (to-leaf), if exists (NULL if not).
1202 *
1203 * => Caller holds a reference on fdvp and fvp, they are unlocked.
1204 * Note: fdvp and fvp can refer to the same object (i.e. when it is root).
1205 *
1206 * => Both tdvp and tvp are referenced and locked. It is our responsibility
1207 * to release the references and unlock them (or destroy).
1208 */
1209
1210 /*
1211 * First, some forward declarations of subroutines.
1212 */
1213
1214 int tmpfs_sane_rename(struct vnode *, struct componentname *,
1215 struct vnode *, struct componentname *, struct ucred *, int);
1216 int tmpfs_rename_enter(struct mount *, struct tmpfs_mount *,
1217 struct ucred *,
1218 struct vnode *, struct tmpfs_node *, struct componentname *,
1219 struct tmpfs_dirent **, struct vnode **,
1220 struct vnode *, struct tmpfs_node *, struct componentname *,
1221 struct tmpfs_dirent **, struct vnode **);
1222 int tmpfs_rename_enter_common(struct mount *, struct tmpfs_mount *,
1223 struct ucred *,
1224 struct vnode *, struct tmpfs_node *,
1225 struct componentname *, struct tmpfs_dirent **, struct vnode **,
1226 struct componentname *, struct tmpfs_dirent **, struct vnode **);
1227 int tmpfs_rename_enter_separate(struct mount *, struct tmpfs_mount *,
1228 struct ucred *,
1229 struct vnode *, struct tmpfs_node *, struct componentname *,
1230 struct tmpfs_dirent **, struct vnode **,
1231 struct vnode *, struct tmpfs_node *, struct componentname *,
1232 struct tmpfs_dirent **, struct vnode **);
1233 void tmpfs_rename_exit(struct tmpfs_mount *,
1234 struct vnode *, struct vnode *, struct vnode *, struct vnode *);
1235 int tmpfs_rename_lock_directory(struct vnode *, struct tmpfs_node *);
1236 int tmpfs_rename_genealogy(struct tmpfs_node *, struct tmpfs_node *,
1237 struct tmpfs_node **);
1238 int tmpfs_rename_lock(struct mount *, struct ucred *, int,
1239 struct vnode *, struct tmpfs_node *, struct componentname *, int,
1240 struct tmpfs_dirent **, struct vnode **,
1241 struct vnode *, struct tmpfs_node *, struct componentname *, int,
1242 struct tmpfs_dirent **, struct vnode **);
1243 void tmpfs_rename_attachdetach(struct tmpfs_mount *,
1244 struct vnode *, struct tmpfs_dirent *, struct vnode *,
1245 struct vnode *, struct tmpfs_dirent *, struct vnode *);
1246 int tmpfs_do_remove(struct tmpfs_mount *, struct vnode *,
1247 struct tmpfs_node *, struct tmpfs_dirent *, struct vnode *, struct ucred *);
1248 int tmpfs_rename_check_possible(struct tmpfs_node *,
1249 struct tmpfs_node *, struct tmpfs_node *, struct tmpfs_node *);
1250 int tmpfs_rename_check_permitted(struct ucred *,
1251 struct tmpfs_node *, struct tmpfs_node *,
1252 struct tmpfs_node *, struct tmpfs_node *);
1253 int tmpfs_remove_check_possible(struct tmpfs_node *,
1254 struct tmpfs_node *);
1255 int tmpfs_remove_check_permitted(struct ucred *,
1256 struct tmpfs_node *, struct tmpfs_node *);
1257 int tmpfs_check_sticky(struct ucred *,
1258 struct tmpfs_node *, struct tmpfs_node *);
1259 void tmpfs_rename_cache_purge(struct vnode *, struct vnode *, struct vnode *,
1260 struct vnode *);
1261 void tmpfs_rename_abort(void *);
1262
1263 int
tmpfs_rename(void * v)1264 tmpfs_rename(void *v)
1265 {
1266 struct vop_rename_args /* {
1267 struct vnode *a_fdvp;
1268 struct vnode *a_fvp;
1269 struct componentname *a_fcnp;
1270 struct vnode *a_tdvp;
1271 struct vnode *a_tvp;
1272 struct componentname *a_tcnp;
1273 } */ *ap = v;
1274 struct vnode *fdvp = ap->a_fdvp;
1275 struct vnode *fvp = ap->a_fvp;
1276 struct componentname *fcnp = ap->a_fcnp;
1277 struct vnode *tdvp = ap->a_tdvp;
1278 struct vnode *tvp = ap->a_tvp;
1279 struct componentname *tcnp = ap->a_tcnp;
1280 struct ucred *cred;
1281 int error;
1282
1283 KASSERT(fdvp != NULL);
1284 KASSERT(fvp != NULL);
1285 KASSERT(fcnp != NULL);
1286 KASSERT(fcnp->cn_nameptr != NULL);
1287 KASSERT(tdvp != NULL);
1288 KASSERT(tcnp != NULL);
1289 KASSERT(fcnp->cn_nameptr != NULL);
1290 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
1291 /* KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */
1292 KASSERT(fdvp->v_type == VDIR);
1293 KASSERT(tdvp->v_type == VDIR);
1294 KASSERT(fcnp->cn_flags & HASBUF);
1295 KASSERT(tcnp->cn_flags & HASBUF);
1296
1297 cred = fcnp->cn_cred;
1298 KASSERT(tcnp->cn_cred == cred);
1299
1300 /*
1301 * Check for cross-device rename.
1302 * Also don't allow renames of mount points.
1303 */
1304 if (fvp->v_mount != tdvp->v_mount ||
1305 fdvp->v_mount != fvp->v_mount ||
1306 (tvp != NULL && (fvp->v_mount != tvp->v_mount))) {
1307 tmpfs_rename_abort(v);
1308 return EXDEV;
1309 }
1310
1311 /*
1312 * Can't check the locks on these until we know they're on
1313 * the same FS, as not all FS do locking the same way.
1314 */
1315 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1316 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1317
1318 /*
1319 * Reject renaming '.' and '..'.
1320 */
1321 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1322 (fcnp->cn_namelen == 2 && fcnp->cn_nameptr[0] == '.' &&
1323 fcnp->cn_nameptr[1] == '.')) {
1324 tmpfs_rename_abort(v);
1325 return EINVAL;
1326 }
1327
1328 /*
1329 * Sanitize our world from the VFS insanity. Unlock the target
1330 * directory and node, which are locked. Release the children,
1331 * which are referenced. Check for rename("x", "y/."), which
1332 * it is our responsibility to reject, not the caller's. (But
1333 * the caller does reject rename("x/.", "y"). Go figure.)
1334 */
1335
1336 VOP_UNLOCK(tdvp);
1337 if ((tvp != NULL) && (tvp != tdvp))
1338 VOP_UNLOCK(tvp);
1339
1340 vrele(fvp);
1341 if (tvp != NULL)
1342 vrele(tvp);
1343
1344 if (tvp == tdvp) {
1345 error = EINVAL;
1346 goto out;
1347 }
1348
1349 error = tmpfs_sane_rename(fdvp, fcnp, tdvp, tcnp, cred, 0);
1350
1351 out: /*
1352 * All done, whether with success or failure. Release the
1353 * directory nodes now, as the caller expects from the VFS
1354 * protocol.
1355 */
1356 vrele(fdvp);
1357 vrele(tdvp);
1358
1359 return error;
1360 }
1361
1362 /*
1363 * tmpfs_sane_rename: rename routine, the hairiest system call, with
1364 * the sane API.
1365 *
1366 * Arguments:
1367 *
1368 * . fdvp (from directory vnode),
1369 * . fcnp (from component name),
1370 * . tdvp (to directory vnode), and
1371 * . tcnp (to component name).
1372 *
1373 * fdvp and tdvp must be referenced and unlocked.
1374 */
1375 int
tmpfs_sane_rename(struct vnode * fdvp,struct componentname * fcnp,struct vnode * tdvp,struct componentname * tcnp,struct ucred * cred,int posixly_correct)1376 tmpfs_sane_rename(struct vnode *fdvp, struct componentname *fcnp,
1377 struct vnode *tdvp, struct componentname *tcnp, struct ucred *cred,
1378 int posixly_correct)
1379 {
1380 struct mount *mount;
1381 struct tmpfs_mount *tmpfs;
1382 struct tmpfs_node *fdnode, *tdnode;
1383 struct tmpfs_dirent *fde, *tde;
1384 struct vnode *fvp, *tvp;
1385 char *newname;
1386 int error;
1387
1388 KASSERT(fdvp != NULL);
1389 KASSERT(fcnp != NULL);
1390 KASSERT(tdvp != NULL);
1391 KASSERT(tcnp != NULL);
1392 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
1393 /* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */
1394 KASSERT(fdvp->v_type == VDIR);
1395 KASSERT(tdvp->v_type == VDIR);
1396 KASSERT(fdvp->v_mount == tdvp->v_mount);
1397 KASSERT((fcnp->cn_flags & ISDOTDOT) == 0);
1398 KASSERT((tcnp->cn_flags & ISDOTDOT) == 0);
1399 KASSERT((fcnp->cn_namelen != 1) || (fcnp->cn_nameptr[0] != '.'));
1400 KASSERT((tcnp->cn_namelen != 1) || (tcnp->cn_nameptr[0] != '.'));
1401 KASSERT((fcnp->cn_namelen != 2) || (fcnp->cn_nameptr[0] != '.') ||
1402 (fcnp->cn_nameptr[1] != '.'));
1403 KASSERT((tcnp->cn_namelen != 2) || (tcnp->cn_nameptr[0] != '.') ||
1404 (tcnp->cn_nameptr[1] != '.'));
1405
1406 /*
1407 * Pull out the tmpfs data structures.
1408 */
1409 fdnode = VP_TO_TMPFS_NODE(fdvp);
1410 tdnode = VP_TO_TMPFS_NODE(tdvp);
1411 KASSERT(fdnode != NULL);
1412 KASSERT(tdnode != NULL);
1413 KASSERT(fdnode->tn_vnode == fdvp);
1414 KASSERT(tdnode->tn_vnode == tdvp);
1415 KASSERT(fdnode->tn_type == VDIR);
1416 KASSERT(tdnode->tn_type == VDIR);
1417
1418 mount = fdvp->v_mount;
1419 KASSERT(mount != NULL);
1420 KASSERT(mount == tdvp->v_mount);
1421 /* XXX How can we be sure this stays true? (Not that you're
1422 * likely to mount a tmpfs read-only...) */
1423 KASSERT((mount->mnt_flag & MNT_RDONLY) == 0);
1424 tmpfs = VFS_TO_TMPFS(mount);
1425 KASSERT(tmpfs != NULL);
1426
1427 /*
1428 * Decide whether we need a new name, and allocate memory for
1429 * it if so. Do this before locking anything or taking
1430 * destructive actions so that we can back out safely and sleep
1431 * safely. XXX Is sleeping an issue here? Can this just be
1432 * moved into tmpfs_rename_attachdetach?
1433 */
1434 if (tmpfs_strname_neqlen(fcnp, tcnp)) {
1435 newname = tmpfs_strname_alloc(tmpfs, tcnp->cn_namelen);
1436 if (newname == NULL) {
1437 error = ENOSPC;
1438 goto out_unlocked;
1439 }
1440 } else {
1441 newname = NULL;
1442 }
1443
1444 /*
1445 * Lock and look up everything. GCC is not very clever.
1446 */
1447 fde = tde = NULL;
1448 fvp = tvp = NULL;
1449 error = tmpfs_rename_enter(mount, tmpfs, cred,
1450 fdvp, fdnode, fcnp, &fde, &fvp,
1451 tdvp, tdnode, tcnp, &tde, &tvp);
1452 if (error)
1453 goto out_unlocked;
1454
1455 /*
1456 * Check that everything is locked and looks right.
1457 */
1458 KASSERT(fde != NULL);
1459 KASSERT(fvp != NULL);
1460 KASSERT(fde->td_node != NULL);
1461 KASSERT(fde->td_node->tn_vnode == fvp);
1462 KASSERT(fde->td_node->tn_type == fvp->v_type);
1463 KASSERT((tde == NULL) == (tvp == NULL));
1464 KASSERT((tde == NULL) || (tde->td_node != NULL));
1465 KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp));
1466 KASSERT((tde == NULL) || (tde->td_node->tn_type == tvp->v_type));
1467 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1468 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1469 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1470 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1471
1472 /*
1473 * If the source and destination are the same object, we need
1474 * only at most delete the source entry.
1475 */
1476 if (fvp == tvp) {
1477 KASSERT(tvp != NULL);
1478 if (fde->td_node->tn_type == VDIR) {
1479 /* XXX How can this possibly happen? */
1480 error = EINVAL;
1481 goto out_locked;
1482 }
1483 if (!posixly_correct && (fde != tde)) {
1484 /* XXX Doesn't work because of locking.
1485 * error = VOP_REMOVE(fdvp, fvp);
1486 */
1487 error = tmpfs_do_remove(tmpfs, fdvp, fdnode, fde, fvp,
1488 cred);
1489 if (error)
1490 goto out_locked;
1491 }
1492 goto success;
1493 }
1494 KASSERT(fde != tde);
1495 KASSERT(fvp != tvp);
1496
1497 /*
1498 * If the target exists, refuse to rename a directory over a
1499 * non-directory or vice versa, or to clobber a non-empty
1500 * directory.
1501 */
1502 if (tvp != NULL) {
1503 KASSERT(tde != NULL);
1504 KASSERT(tde->td_node != NULL);
1505 if (fvp->v_type == VDIR && tvp->v_type == VDIR)
1506 error = ((tde->td_node->tn_size > 0)? ENOTEMPTY : 0);
1507 else if (fvp->v_type == VDIR && tvp->v_type != VDIR)
1508 error = ENOTDIR;
1509 else if (fvp->v_type != VDIR && tvp->v_type == VDIR)
1510 error = EISDIR;
1511 else
1512 error = 0;
1513 if (error)
1514 goto out_locked;
1515 KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR));
1516 }
1517
1518 /*
1519 * Authorize the rename.
1520 */
1521 error = tmpfs_rename_check_possible(fdnode, fde->td_node,
1522 tdnode, (tde? tde->td_node : NULL));
1523 if (error)
1524 goto out_locked;
1525 error = tmpfs_rename_check_permitted(cred, fdnode, fde->td_node,
1526 tdnode, (tde? tde->td_node : NULL));
1527 if (error)
1528 goto out_locked;
1529
1530 /*
1531 * Everything is hunky-dory. Shuffle the directory entries.
1532 */
1533 tmpfs_rename_attachdetach(tmpfs, fdvp, fde, fvp, tdvp, tde, tvp);
1534
1535 /*
1536 * Update the directory entry's name necessary, and flag
1537 * metadata updates. A memory allocation failure here is not
1538 * OK because we've already committed some changes that we
1539 * can't back out at this point, and we have things locked so
1540 * we can't sleep, hence the early allocation above.
1541 */
1542 if (newname != NULL) {
1543 KASSERT(tcnp->cn_namelen <= TMPFS_MAXNAMLEN);
1544
1545 tmpfs_strname_free(tmpfs, fde->td_name, fde->td_namelen);
1546 fde->td_namelen = (uint16_t)tcnp->cn_namelen;
1547 (void)memcpy(newname, tcnp->cn_nameptr, tcnp->cn_namelen);
1548 /* Commit newname and don't free it on the way out. */
1549 fde->td_name = newname;
1550 newname = NULL;
1551
1552 tmpfs_update(fde->td_node, TMPFS_NODE_CHANGED);
1553 tmpfs_update(tdnode, TMPFS_NODE_MODIFIED);
1554 }
1555
1556 success:
1557 VN_KNOTE(fvp, NOTE_RENAME);
1558 tmpfs_rename_cache_purge(fdvp, fvp, tdvp, tvp);
1559 error = 0;
1560
1561 out_locked:
1562 tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp);
1563
1564 out_unlocked:
1565 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
1566 /* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */
1567 /* KASSERT((fvp == NULL) || (VOP_ISLOCKED(fvp) != LK_EXCLUSIVE)); */
1568 /* KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */
1569
1570 if (newname != NULL)
1571 tmpfs_strname_free(tmpfs, newname, tcnp->cn_namelen);
1572
1573 return error;
1574 }
1575
1576 /*
1577 * Look up fcnp in fdnode/fdvp and store its directory entry in fde_ret
1578 * and the associated vnode in fvp_ret; fail if not found. Look up
1579 * tcnp in tdnode/tdvp and store its directory entry in tde_ret and the
1580 * associated vnode in tvp_ret; store null instead if not found. Fail
1581 * if anything has been mounted on any of the nodes involved.
1582 *
1583 * fdvp and tdvp must be referenced.
1584 *
1585 * On entry, nothing is locked.
1586 *
1587 * On success, everything is locked, and *fvp_ret, and *tvp_ret if
1588 * nonnull, are referenced. The only pairs of vnodes that may be
1589 * identical are {fdvp, tdvp} and {fvp, tvp}.
1590 *
1591 * On failure, everything remains as was.
1592 *
1593 * Locking everything including the source and target nodes is
1594 * necessary to make sure that, e.g., link count updates are OK. The
1595 * locking order is, in general, ancestor-first, matching the order you
1596 * need to use to look up a descendant anyway.
1597 */
1598 int
tmpfs_rename_enter(struct mount * mount,struct tmpfs_mount * tmpfs,struct ucred * cred,struct vnode * fdvp,struct tmpfs_node * fdnode,struct componentname * fcnp,struct tmpfs_dirent ** fde_ret,struct vnode ** fvp_ret,struct vnode * tdvp,struct tmpfs_node * tdnode,struct componentname * tcnp,struct tmpfs_dirent ** tde_ret,struct vnode ** tvp_ret)1599 tmpfs_rename_enter(struct mount *mount, struct tmpfs_mount *tmpfs,
1600 struct ucred *cred,
1601 struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp,
1602 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret,
1603 struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp,
1604 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret)
1605 {
1606 int error;
1607
1608 KASSERT(mount != NULL);
1609 KASSERT(tmpfs != NULL);
1610 KASSERT(fdvp != NULL);
1611 KASSERT(fdnode != NULL);
1612 KASSERT(fcnp != NULL);
1613 KASSERT(fde_ret != NULL);
1614 KASSERT(fvp_ret != NULL);
1615 KASSERT(tdvp != NULL);
1616 KASSERT(tdnode != NULL);
1617 KASSERT(tcnp != NULL);
1618 KASSERT(tde_ret != NULL);
1619 KASSERT(tvp_ret != NULL);
1620 KASSERT(fdnode->tn_vnode == fdvp);
1621 KASSERT(tdnode->tn_vnode == tdvp);
1622 KASSERT(fdnode->tn_type == VDIR);
1623 KASSERT(tdnode->tn_type == VDIR);
1624
1625 if (fdvp == tdvp) {
1626 KASSERT(fdnode == tdnode);
1627 error = tmpfs_rename_enter_common(mount, tmpfs, cred, fdvp,
1628 fdnode, fcnp, fde_ret, fvp_ret, tcnp, tde_ret, tvp_ret);
1629 } else {
1630 KASSERT(fdnode != tdnode);
1631 error = tmpfs_rename_enter_separate(mount, tmpfs, cred,
1632 fdvp, fdnode, fcnp, fde_ret, fvp_ret,
1633 tdvp, tdnode, tcnp, tde_ret, tvp_ret);
1634 }
1635
1636 if (error)
1637 return error;
1638
1639 KASSERT(*fde_ret != NULL);
1640 KASSERT(*fvp_ret != NULL);
1641 KASSERT((*tde_ret == NULL) == (*tvp_ret == NULL));
1642 KASSERT((*tde_ret == NULL) || ((*tde_ret)->td_node != NULL));
1643 KASSERT((*tde_ret == NULL) ||
1644 ((*tde_ret)->td_node->tn_vnode == *tvp_ret));
1645 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1646 KASSERT(VOP_ISLOCKED(*fvp_ret) == LK_EXCLUSIVE);
1647 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1648 KASSERT((*tvp_ret == NULL) ||
1649 (VOP_ISLOCKED(*tvp_ret) == LK_EXCLUSIVE));
1650 KASSERT(*fvp_ret != fdvp);
1651 KASSERT(*fvp_ret != tdvp);
1652 KASSERT(*tvp_ret != fdvp);
1653 KASSERT(*tvp_ret != tdvp);
1654 return 0;
1655 }
1656
1657 /*
1658 * Lock and look up with a common source/target directory.
1659 */
1660 int
tmpfs_rename_enter_common(struct mount * mount,struct tmpfs_mount * tmpfs,struct ucred * cred,struct vnode * dvp,struct tmpfs_node * dnode,struct componentname * fcnp,struct tmpfs_dirent ** fde_ret,struct vnode ** fvp_ret,struct componentname * tcnp,struct tmpfs_dirent ** tde_ret,struct vnode ** tvp_ret)1661 tmpfs_rename_enter_common(struct mount *mount, struct tmpfs_mount *tmpfs,
1662 struct ucred *cred,
1663 struct vnode *dvp, struct tmpfs_node *dnode,
1664 struct componentname *fcnp,
1665 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret,
1666 struct componentname *tcnp,
1667 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret)
1668 {
1669 struct tmpfs_dirent *fde, *tde;
1670 struct vnode *fvp, *tvp;
1671 int error;
1672
1673 error = tmpfs_rename_lock_directory(dvp, dnode);
1674 if (error)
1675 goto fail0;
1676
1677 /* Did we lose a race with mount? */
1678 if (dvp->v_mountedhere != NULL) {
1679 error = EBUSY;
1680 goto fail1;
1681 }
1682
1683 /* Make sure the caller may read the directory. */
1684 error = VOP_ACCESS(dvp, VEXEC, cred, curproc);
1685 if (error)
1686 goto fail1;
1687
1688 /*
1689 * The order in which we lock the source and target nodes is
1690 * irrelevant because there can only be one rename on this
1691 * directory in flight at a time, and we have it locked.
1692 */
1693
1694 fde = tmpfs_dir_lookup(dnode, fcnp);
1695 if (fde == NULL) {
1696 error = ENOENT;
1697 goto fail1;
1698 }
1699
1700 KASSERT(fde->td_node != NULL);
1701 /* We ruled out `.' earlier. */
1702 KASSERT(fde->td_node != dnode);
1703 /* We ruled out `..' earlier. */
1704 KASSERT(fde->td_node != dnode->tn_spec.tn_dir.tn_parent);
1705 rw_enter_write(&fde->td_node->tn_nlock);
1706 error = tmpfs_vnode_get(mount, fde->td_node, &fvp);
1707 if (error)
1708 goto fail1;
1709 KASSERT(fvp != NULL);
1710 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1711 KASSERT(fvp != dvp);
1712 KASSERT(fvp->v_mount == mount);
1713
1714 /* Refuse to rename a mount point. */
1715 if ((fvp->v_type == VDIR) && (fvp->v_mountedhere != NULL)) {
1716 error = EBUSY;
1717 goto fail2;
1718 }
1719
1720 tde = tmpfs_dir_lookup(dnode, tcnp);
1721 if (tde == NULL) {
1722 tvp = NULL;
1723 } else {
1724 KASSERT(tde->td_node != NULL);
1725 /* We ruled out `.' earlier. */
1726 KASSERT(tde->td_node != dnode);
1727 /* We ruled out `..' earlier. */
1728 KASSERT(tde->td_node != dnode->tn_spec.tn_dir.tn_parent);
1729 if (tde->td_node != fde->td_node) {
1730 rw_enter_write(&tde->td_node->tn_nlock);
1731 error = tmpfs_vnode_get(mount, tde->td_node, &tvp);
1732 if (error)
1733 goto fail2;
1734 KASSERT(tvp->v_mount == mount);
1735 /* Refuse to rename over a mount point. */
1736 if ((tvp->v_type == VDIR) &&
1737 (tvp->v_mountedhere != NULL)) {
1738 error = EBUSY;
1739 goto fail3;
1740 }
1741 } else {
1742 tvp = fvp;
1743 vref(tvp);
1744 }
1745 KASSERT(tvp != NULL);
1746 KASSERT(VOP_ISLOCKED(tvp) == LK_EXCLUSIVE);
1747 }
1748 KASSERT(tvp != dvp);
1749
1750 *fde_ret = fde;
1751 *fvp_ret = fvp;
1752 *tde_ret = tde;
1753 *tvp_ret = tvp;
1754 return 0;
1755
1756 fail3: if (tvp != NULL) {
1757 if (tvp != fvp)
1758 vput(tvp);
1759 else
1760 vrele(tvp);
1761 }
1762
1763 fail2: vput(fvp);
1764 fail1: VOP_UNLOCK(dvp);
1765 fail0: return error;
1766 }
1767
1768 /*
1769 * Lock and look up with separate source and target directories.
1770 */
1771 int
tmpfs_rename_enter_separate(struct mount * mount,struct tmpfs_mount * tmpfs,struct ucred * cred,struct vnode * fdvp,struct tmpfs_node * fdnode,struct componentname * fcnp,struct tmpfs_dirent ** fde_ret,struct vnode ** fvp_ret,struct vnode * tdvp,struct tmpfs_node * tdnode,struct componentname * tcnp,struct tmpfs_dirent ** tde_ret,struct vnode ** tvp_ret)1772 tmpfs_rename_enter_separate(struct mount *mount, struct tmpfs_mount *tmpfs,
1773 struct ucred *cred,
1774 struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp,
1775 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret,
1776 struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp,
1777 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret)
1778 {
1779 struct tmpfs_node *intermediate_node;
1780 struct tmpfs_dirent *fde, *tde;
1781 struct vnode *fvp, *tvp;
1782 int error;
1783
1784 KASSERT(fdvp != tdvp);
1785 KASSERT(fdnode != tdnode);
1786
1787 #if 0 /* XXX */
1788 mutex_enter(&tmpfs->tm_rename_lock);
1789 #endif
1790
1791 error = tmpfs_rename_genealogy(fdnode, tdnode, &intermediate_node);
1792 if (error)
1793 goto fail;
1794
1795 /*
1796 * intermediate_node == NULL means fdnode is not an ancestor of
1797 * tdnode.
1798 */
1799 if (intermediate_node == NULL)
1800 error = tmpfs_rename_lock(mount, cred, ENOTEMPTY,
1801 tdvp, tdnode, tcnp, 1, &tde, &tvp,
1802 fdvp, fdnode, fcnp, 0, &fde, &fvp);
1803 else
1804 error = tmpfs_rename_lock(mount, cred, EINVAL,
1805 fdvp, fdnode, fcnp, 0, &fde, &fvp,
1806 tdvp, tdnode, tcnp, 1, &tde, &tvp);
1807 if (error)
1808 goto fail;
1809
1810 KASSERT(fde != NULL);
1811 KASSERT(fde->td_node != NULL);
1812
1813 /*
1814 * Reject rename("foo/bar", "foo/bar/baz/quux/zot").
1815 */
1816 if (fde->td_node == intermediate_node) {
1817 tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp);
1818 return EINVAL;
1819 }
1820
1821 *fde_ret = fde;
1822 *fvp_ret = fvp;
1823 *tde_ret = tde;
1824 *tvp_ret = tvp;
1825 return 0;
1826
1827 fail:
1828 #if 0 /* XXX */
1829 mutex_exit(&tmpfs->tm_rename_lock);
1830 #endif
1831 return error;
1832 }
1833
1834 /*
1835 * Unlock everything we locked for rename.
1836 *
1837 * fdvp and tdvp must be referenced.
1838 *
1839 * On entry, everything is locked, and fvp and tvp referenced.
1840 *
1841 * On exit, everything is unlocked, and fvp and tvp are released.
1842 */
1843 void
tmpfs_rename_exit(struct tmpfs_mount * tmpfs,struct vnode * fdvp,struct vnode * fvp,struct vnode * tdvp,struct vnode * tvp)1844 tmpfs_rename_exit(struct tmpfs_mount *tmpfs,
1845 struct vnode *fdvp, struct vnode *fvp,
1846 struct vnode *tdvp, struct vnode *tvp)
1847 {
1848
1849 KASSERT(tmpfs != NULL);
1850 KASSERT(fdvp != NULL);
1851 KASSERT(fvp != NULL);
1852 KASSERT(fdvp != fvp);
1853 KASSERT(fdvp != tvp);
1854 KASSERT(tdvp != tvp);
1855 KASSERT(tdvp != fvp);
1856 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1857 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1858 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1859 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1860
1861 if (tvp != NULL) {
1862 if (tvp != fvp)
1863 vput(tvp);
1864 else
1865 vrele(tvp);
1866 }
1867 VOP_UNLOCK(tdvp);
1868 vput(fvp);
1869 if (fdvp != tdvp)
1870 VOP_UNLOCK(fdvp);
1871
1872 #if 0 /* XXX */
1873 if (fdvp != tdvp)
1874 mutex_exit(&tmpfs->tm_rename_lock);
1875 #endif
1876 }
1877
1878 /*
1879 * Lock a directory, but fail if it has been rmdir'd.
1880 *
1881 * vp must be referenced.
1882 */
1883 int
tmpfs_rename_lock_directory(struct vnode * vp,struct tmpfs_node * node)1884 tmpfs_rename_lock_directory(struct vnode *vp, struct tmpfs_node *node)
1885 {
1886
1887 KASSERT(vp != NULL);
1888 KASSERT(node != NULL);
1889 KASSERT(node->tn_vnode == vp);
1890 KASSERT(node->tn_type == VDIR);
1891
1892 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1893 if (node->tn_spec.tn_dir.tn_parent == NULL) {
1894 VOP_UNLOCK(vp);
1895 return ENOENT;
1896 }
1897
1898 return 0;
1899 }
1900
1901 /*
1902 * Analyze the genealogy of the source and target nodes.
1903 *
1904 * On success, stores in *intermediate_node_ret either the child of
1905 * fdnode of which tdnode is a descendant, or null if tdnode is not a
1906 * descendant of fdnode at all.
1907 *
1908 * fdnode and tdnode must be unlocked and referenced. The file
1909 * system's rename lock must also be held, to exclude concurrent
1910 * changes to the file system's genealogy other than rmdir.
1911 *
1912 * XXX This causes an extra lock/unlock of tdnode in the case when
1913 * we're just about to lock it again before locking anything else.
1914 * However, changing that requires reorganizing the code to make it
1915 * even more horrifically obscure.
1916 */
1917 int
tmpfs_rename_genealogy(struct tmpfs_node * fdnode,struct tmpfs_node * tdnode,struct tmpfs_node ** intermediate_node_ret)1918 tmpfs_rename_genealogy(struct tmpfs_node *fdnode, struct tmpfs_node *tdnode,
1919 struct tmpfs_node **intermediate_node_ret)
1920 {
1921 struct tmpfs_node *node = tdnode, *parent;
1922 int error;
1923
1924 KASSERT(fdnode != NULL);
1925 KASSERT(tdnode != NULL);
1926 KASSERT(fdnode != tdnode);
1927 KASSERT(intermediate_node_ret != NULL);
1928
1929 KASSERT(fdnode->tn_vnode != NULL);
1930 KASSERT(tdnode->tn_vnode != NULL);
1931 KASSERT(fdnode->tn_type == VDIR);
1932 KASSERT(tdnode->tn_type == VDIR);
1933
1934 /*
1935 * We need to provisionally lock tdnode->tn_vnode to keep rmdir
1936 * from deleting it -- or any ancestor -- at an inopportune
1937 * moment.
1938 */
1939 error = tmpfs_rename_lock_directory(tdnode->tn_vnode, tdnode);
1940 if (error)
1941 return error;
1942
1943 for (;;) {
1944 parent = node->tn_spec.tn_dir.tn_parent;
1945 KASSERT(parent != NULL);
1946 KASSERT(parent->tn_type == VDIR);
1947
1948 /* Did we hit the root without finding fdnode? */
1949 if (parent == node) {
1950 *intermediate_node_ret = NULL;
1951 break;
1952 }
1953
1954 /* Did we find that fdnode is an ancestor? */
1955 if (parent == fdnode) {
1956 *intermediate_node_ret = node;
1957 break;
1958 }
1959
1960 /* Neither -- keep ascending the family tree. */
1961 node = parent;
1962 }
1963
1964 VOP_UNLOCK(tdnode->tn_vnode);
1965 return 0;
1966 }
1967
1968 /*
1969 * Lock directories a and b, which must be distinct, and look up and
1970 * lock nodes a and b. Do a first and then b. Directory b may not be
1971 * an ancestor of directory a, although directory a may be an ancestor
1972 * of directory b. Fail with overlap_error if node a is directory b.
1973 * Neither componentname may be `.' or `..'.
1974 *
1975 * a_dvp and b_dvp must be referenced.
1976 *
1977 * On entry, a_dvp and b_dvp are unlocked.
1978 *
1979 * On success,
1980 * . a_dvp and b_dvp are locked,
1981 * . *a_dirent_ret is filled with a directory entry whose node is
1982 * locked and referenced,
1983 * . *b_vp_ret is filled with the corresponding vnode,
1984 * . *b_dirent_ret is filled either with null or with a directory entry
1985 * whose node is locked and referenced,
1986 * . *b_vp is filled either with null or with the corresponding vnode,
1987 * and
1988 * . the only pair of vnodes that may be identical is a_vp and b_vp.
1989 *
1990 * On failure, a_dvp and b_dvp are left unlocked, and *a_dirent_ret,
1991 * *a_vp, *b_dirent_ret, and *b_vp are left alone.
1992 */
1993 int
tmpfs_rename_lock(struct mount * mount,struct ucred * cred,int overlap_error,struct vnode * a_dvp,struct tmpfs_node * a_dnode,struct componentname * a_cnp,int a_missing_ok,struct tmpfs_dirent ** a_dirent_ret,struct vnode ** a_vp_ret,struct vnode * b_dvp,struct tmpfs_node * b_dnode,struct componentname * b_cnp,int b_missing_ok,struct tmpfs_dirent ** b_dirent_ret,struct vnode ** b_vp_ret)1994 tmpfs_rename_lock(struct mount *mount, struct ucred *cred, int overlap_error,
1995 struct vnode *a_dvp, struct tmpfs_node *a_dnode,
1996 struct componentname *a_cnp, int a_missing_ok,
1997 struct tmpfs_dirent **a_dirent_ret, struct vnode **a_vp_ret,
1998 struct vnode *b_dvp, struct tmpfs_node *b_dnode,
1999 struct componentname *b_cnp, int b_missing_ok,
2000 struct tmpfs_dirent **b_dirent_ret, struct vnode **b_vp_ret)
2001 {
2002 struct tmpfs_dirent *a_dirent, *b_dirent;
2003 struct vnode *a_vp, *b_vp;
2004 int error;
2005
2006 KASSERT(a_dvp != NULL);
2007 KASSERT(a_dnode != NULL);
2008 KASSERT(a_cnp != NULL);
2009 KASSERT(a_dirent_ret != NULL);
2010 KASSERT(a_vp_ret != NULL);
2011 KASSERT(b_dvp != NULL);
2012 KASSERT(b_dnode != NULL);
2013 KASSERT(b_cnp != NULL);
2014 KASSERT(b_dirent_ret != NULL);
2015 KASSERT(b_vp_ret != NULL);
2016 KASSERT(a_dvp != b_dvp);
2017 KASSERT(a_dnode != b_dnode);
2018 KASSERT(a_dnode->tn_vnode == a_dvp);
2019 KASSERT(b_dnode->tn_vnode == b_dvp);
2020 KASSERT(a_dnode->tn_type == VDIR);
2021 KASSERT(b_dnode->tn_type == VDIR);
2022 KASSERT(a_missing_ok != b_missing_ok);
2023
2024 error = tmpfs_rename_lock_directory(a_dvp, a_dnode);
2025 if (error)
2026 goto fail0;
2027
2028 /* Did we lose a race with mount? */
2029 if (a_dvp->v_mountedhere != NULL) {
2030 error = EBUSY;
2031 goto fail1;
2032 }
2033
2034 /* Make sure the caller may read the directory. */
2035 error = VOP_ACCESS(a_dvp, VEXEC, cred, curproc);
2036 if (error)
2037 goto fail1;
2038
2039 a_dirent = tmpfs_dir_lookup(a_dnode, a_cnp);
2040 if (a_dirent != NULL) {
2041 KASSERT(a_dirent->td_node != NULL);
2042 /* We ruled out `.' earlier. */
2043 KASSERT(a_dirent->td_node != a_dnode);
2044 /* We ruled out `..' earlier. */
2045 KASSERT(a_dirent->td_node !=
2046 a_dnode->tn_spec.tn_dir.tn_parent);
2047 if (a_dirent->td_node == b_dnode) {
2048 error = overlap_error;
2049 goto fail1;
2050 }
2051 rw_enter_write(&a_dirent->td_node->tn_nlock);
2052 error = tmpfs_vnode_get(mount, a_dirent->td_node, &a_vp);
2053 if (error)
2054 goto fail1;
2055 KASSERT(a_vp->v_mount == mount);
2056 /* Refuse to rename (over) a mount point. */
2057 if ((a_vp->v_type == VDIR) && (a_vp->v_mountedhere != NULL)) {
2058 error = EBUSY;
2059 goto fail2;
2060 }
2061 } else if (!a_missing_ok) {
2062 error = ENOENT;
2063 goto fail1;
2064 } else {
2065 a_vp = NULL;
2066 }
2067 KASSERT(a_vp != a_dvp);
2068 KASSERT(a_vp != b_dvp);
2069
2070 error = tmpfs_rename_lock_directory(b_dvp, b_dnode);
2071 if (error)
2072 goto fail2;
2073
2074 /* Did we lose a race with mount? */
2075 if (b_dvp->v_mountedhere != NULL) {
2076 error = EBUSY;
2077 goto fail3;
2078 }
2079
2080 /* Make sure the caller may read the directory. */
2081 error = VOP_ACCESS(b_dvp, VEXEC, cred, curproc);
2082 if (error)
2083 goto fail3;
2084
2085 b_dirent = tmpfs_dir_lookup(b_dnode, b_cnp);
2086 if (b_dirent != NULL) {
2087 KASSERT(b_dirent->td_node != NULL);
2088 /* We ruled out `.' earlier. */
2089 KASSERT(b_dirent->td_node != b_dnode);
2090 /* We ruled out `..' earlier. */
2091 KASSERT(b_dirent->td_node !=
2092 b_dnode->tn_spec.tn_dir.tn_parent);
2093 /* b is not an ancestor of a. */
2094 KASSERT(b_dirent->td_node != a_dnode);
2095 /* But the source and target nodes might be the same. */
2096 if ((a_dirent == NULL) ||
2097 (a_dirent->td_node != b_dirent->td_node)) {
2098 rw_enter_write(&b_dirent->td_node->tn_nlock);
2099 error = tmpfs_vnode_get(mount, b_dirent->td_node,
2100 &b_vp);
2101 if (error)
2102 goto fail3;
2103 KASSERT(b_vp->v_mount == mount);
2104 KASSERT(a_vp != b_vp);
2105 /* Refuse to rename (over) a mount point. */
2106 if ((b_vp->v_type == VDIR) &&
2107 (b_vp->v_mountedhere != NULL)) {
2108 error = EBUSY;
2109 goto fail4;
2110 }
2111 } else {
2112 b_vp = a_vp;
2113 vref(b_vp);
2114 }
2115 } else if (!b_missing_ok) {
2116 error = ENOENT;
2117 goto fail3;
2118 } else {
2119 b_vp = NULL;
2120 }
2121 KASSERT(b_vp != a_dvp);
2122 KASSERT(b_vp != b_dvp);
2123
2124 KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE);
2125 KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE);
2126 KASSERT(a_missing_ok || (a_dirent != NULL));
2127 KASSERT(a_missing_ok || (a_dirent->td_node != NULL));
2128 KASSERT(b_missing_ok || (b_dirent != NULL));
2129 KASSERT(b_missing_ok || (b_dirent->td_node != NULL));
2130 KASSERT((a_dirent == NULL) || (a_dirent->td_node != NULL));
2131 KASSERT((a_dirent == NULL) || (a_dirent->td_node->tn_vnode == a_vp));
2132 KASSERT((b_dirent == NULL) || (b_dirent->td_node != NULL));
2133 KASSERT((b_dirent == NULL) || (b_dirent->td_node->tn_vnode == b_vp));
2134 KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE));
2135 KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE));
2136
2137 *a_dirent_ret = a_dirent;
2138 *b_dirent_ret = b_dirent;
2139 *a_vp_ret = a_vp;
2140 *b_vp_ret = b_vp;
2141 return 0;
2142
2143 fail4: if (b_vp != NULL) {
2144 KASSERT(VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE);
2145 if (b_vp != a_vp)
2146 vput(b_vp);
2147 else
2148 vrele(a_vp);
2149 }
2150
2151 fail3: KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE);
2152 VOP_UNLOCK(b_dvp);
2153
2154 fail2: if (a_vp != NULL) {
2155 KASSERT(VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE);
2156 vput(a_vp);
2157 }
2158
2159 fail1: KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE);
2160 VOP_UNLOCK(a_dvp);
2161
2162 fail0: /* KASSERT(VOP_ISLOCKED(a_dvp) != LK_EXCLUSIVE); */
2163 /* KASSERT(VOP_ISLOCKED(b_dvp) != LK_EXCLUSIVE); */
2164 /* KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) != LK_EXCLUSIVE)); */
2165 /* KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) != LK_EXCLUSIVE)); */
2166 return error;
2167 }
2168
2169 /*
2170 * Shuffle the directory entries to move fvp from the directory fdvp
2171 * into the directory tdvp. fde is fvp's directory entry in fdvp. If
2172 * we are overwriting a target node, it is tvp, and tde is its
2173 * directory entry in tdvp.
2174 *
2175 * fdvp, fvp, tdvp, and tvp must all be locked and referenced.
2176 */
2177 void
tmpfs_rename_attachdetach(struct tmpfs_mount * tmpfs,struct vnode * fdvp,struct tmpfs_dirent * fde,struct vnode * fvp,struct vnode * tdvp,struct tmpfs_dirent * tde,struct vnode * tvp)2178 tmpfs_rename_attachdetach(struct tmpfs_mount *tmpfs,
2179 struct vnode *fdvp, struct tmpfs_dirent *fde, struct vnode *fvp,
2180 struct vnode *tdvp, struct tmpfs_dirent *tde, struct vnode *tvp)
2181 {
2182
2183 KASSERT(tmpfs != NULL);
2184 KASSERT(fdvp != NULL);
2185 KASSERT(fde != NULL);
2186 KASSERT(fvp != NULL);
2187 KASSERT(tdvp != NULL);
2188 KASSERT(fde->td_node != NULL);
2189 KASSERT(fde->td_node->tn_vnode == fvp);
2190 KASSERT((tde == NULL) == (tvp == NULL));
2191 KASSERT((tde == NULL) || (tde->td_node != NULL));
2192 KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp));
2193 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
2194 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
2195 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
2196 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
2197
2198 /*
2199 * If we are moving from one directory to another, detach the
2200 * source entry and reattach it to the target directory.
2201 */
2202 if (fdvp != tdvp) {
2203 /* tmpfs_dir_detach clobbers fde->td_node, so save it. */
2204 struct tmpfs_node *fnode = fde->td_node;
2205 tmpfs_node_t *fdnode = VP_TO_TMPFS_DIR(fdvp);
2206 tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp);
2207 tmpfs_dir_detach(fdnode, fde);
2208 tmpfs_dir_attach(tdnode, fde, fnode);
2209 } else if (tvp == NULL) {
2210 /*
2211 * We are changing the directory. tmpfs_dir_attach and
2212 * tmpfs_dir_detach note the events for us, but for
2213 * this case we don't call them, so we must note the
2214 * event explicitly.
2215 */
2216 VN_KNOTE(fdvp, NOTE_WRITE);
2217 }
2218
2219 /*
2220 * If we are replacing an existing target entry, delete it.
2221 */
2222 if (tde != NULL) {
2223 tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp);
2224 KASSERT(tvp != NULL);
2225 KASSERT(tde->td_node != NULL);
2226 KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR));
2227 if (tde->td_node->tn_type == VDIR) {
2228 KASSERT(tde->td_node->tn_size == 0);
2229 KASSERT(tde->td_node->tn_links == 2);
2230 /* Decrement the extra link count for `.' so
2231 * the vnode will be recycled when released. */
2232 tde->td_node->tn_links--;
2233 }
2234 tmpfs_dir_detach(tdnode, tde);
2235 tmpfs_free_dirent(tmpfs, tde);
2236 }
2237 }
2238
2239 /*
2240 * Remove the entry de for the non-directory vp from the directory dvp.
2241 *
2242 * Everything must be locked and referenced.
2243 */
2244 int
tmpfs_do_remove(struct tmpfs_mount * tmpfs,struct vnode * dvp,struct tmpfs_node * dnode,struct tmpfs_dirent * de,struct vnode * vp,struct ucred * cred)2245 tmpfs_do_remove(struct tmpfs_mount *tmpfs, struct vnode *dvp,
2246 struct tmpfs_node *dnode, struct tmpfs_dirent *de, struct vnode *vp,
2247 struct ucred *cred)
2248 {
2249 int error;
2250
2251 KASSERT(tmpfs != NULL);
2252 KASSERT(dvp != NULL);
2253 KASSERT(dnode != NULL);
2254 KASSERT(de != NULL);
2255 KASSERT(vp != NULL);
2256 KASSERT(dnode->tn_vnode == dvp);
2257 KASSERT(de->td_node != NULL);
2258 KASSERT(de->td_node->tn_vnode == vp);
2259 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
2260 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
2261
2262 error = tmpfs_remove_check_possible(dnode, de->td_node);
2263 if (error)
2264 return error;
2265
2266 error = tmpfs_remove_check_permitted(cred, dnode, de->td_node);
2267 if (error)
2268 return error;
2269
2270 /*
2271 * If not root and directory is sticky, check for permission on
2272 * directory or on file. This implements append-only directories.
2273 */
2274 if ((dnode->tn_mode & S_ISTXT) != 0)
2275 if (cred->cr_uid != 0 && cred->cr_uid != dnode->tn_uid &&
2276 cred->cr_uid != de->td_node->tn_uid)
2277 return EPERM;
2278
2279 tmpfs_dir_detach(dnode, de);
2280 tmpfs_free_dirent(tmpfs, de);
2281
2282 return 0;
2283 }
2284
2285 /*
2286 * Check whether a rename is possible independent of credentials.
2287 *
2288 * Everything must be locked and referenced.
2289 */
2290 int
tmpfs_rename_check_possible(struct tmpfs_node * fdnode,struct tmpfs_node * fnode,struct tmpfs_node * tdnode,struct tmpfs_node * tnode)2291 tmpfs_rename_check_possible(
2292 struct tmpfs_node *fdnode, struct tmpfs_node *fnode,
2293 struct tmpfs_node *tdnode, struct tmpfs_node *tnode)
2294 {
2295
2296 KASSERT(fdnode != NULL);
2297 KASSERT(fnode != NULL);
2298 KASSERT(tdnode != NULL);
2299 KASSERT(fdnode != fnode);
2300 KASSERT(tdnode != tnode);
2301 KASSERT(fnode != tnode);
2302 KASSERT(fdnode->tn_vnode != NULL);
2303 KASSERT(fnode->tn_vnode != NULL);
2304 KASSERT(tdnode->tn_vnode != NULL);
2305 KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL));
2306 KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE);
2307 KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE);
2308 KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE);
2309 KASSERT((tnode == NULL) ||
2310 (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE));
2311
2312 /*
2313 * If fdnode is immutable, we can't write to it. If fdnode is
2314 * append-only, the only change we can make is to add entries
2315 * to it. If fnode is immutable, we can't change the links to
2316 * it. If fnode is append-only...well, this is what UFS does.
2317 */
2318 if ((fdnode->tn_flags | fnode->tn_flags) & (IMMUTABLE | APPEND))
2319 return EPERM;
2320
2321 /*
2322 * If tdnode is immutable, we can't write to it. If tdnode is
2323 * append-only, we can add entries, but we can't change
2324 * existing entries.
2325 */
2326 if (tdnode->tn_flags & (IMMUTABLE | (tnode? APPEND : 0)))
2327 return EPERM;
2328
2329 /*
2330 * If tnode is immutable, we can't replace links to it. If
2331 * tnode is append-only...well, this is what UFS does.
2332 */
2333 if (tnode != NULL) {
2334 KASSERT(tnode != NULL);
2335 if ((tnode->tn_flags & (IMMUTABLE | APPEND)) != 0)
2336 return EPERM;
2337 }
2338
2339 return 0;
2340 }
2341
2342 /*
2343 * Check whether a rename is permitted given our credentials.
2344 *
2345 * Everything must be locked and referenced.
2346 */
2347 int
tmpfs_rename_check_permitted(struct ucred * cred,struct tmpfs_node * fdnode,struct tmpfs_node * fnode,struct tmpfs_node * tdnode,struct tmpfs_node * tnode)2348 tmpfs_rename_check_permitted(struct ucred *cred,
2349 struct tmpfs_node *fdnode, struct tmpfs_node *fnode,
2350 struct tmpfs_node *tdnode, struct tmpfs_node *tnode)
2351 {
2352 int error;
2353
2354 KASSERT(fdnode != NULL);
2355 KASSERT(fnode != NULL);
2356 KASSERT(tdnode != NULL);
2357 KASSERT(fdnode != fnode);
2358 KASSERT(tdnode != tnode);
2359 KASSERT(fnode != tnode);
2360 KASSERT(fdnode->tn_vnode != NULL);
2361 KASSERT(fnode->tn_vnode != NULL);
2362 KASSERT(tdnode->tn_vnode != NULL);
2363 KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL));
2364 KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE);
2365 KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE);
2366 KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE);
2367 KASSERT((tnode == NULL) ||
2368 (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE));
2369
2370 /*
2371 * We need to remove or change an entry in the source directory.
2372 */
2373 error = VOP_ACCESS(fdnode->tn_vnode, VWRITE, cred, curproc);
2374 if (error)
2375 return error;
2376
2377 /*
2378 * If we are changing directories, then we need to write to the
2379 * target directory to add or change an entry. Also, if fnode
2380 * is a directory, we need to write to it to change its `..'
2381 * entry.
2382 */
2383 if (fdnode != tdnode) {
2384 error = VOP_ACCESS(tdnode->tn_vnode, VWRITE, cred, curproc);
2385 if (error)
2386 return error;
2387 if (fnode->tn_type == VDIR) {
2388 error = VOP_ACCESS(fnode->tn_vnode, VWRITE, cred,
2389 curproc);
2390 if (error)
2391 return error;
2392 }
2393 }
2394
2395 error = tmpfs_check_sticky(cred, fdnode, fnode);
2396 if (error)
2397 return error;
2398
2399 if (TMPFS_DIRSEQ_FULL(tdnode))
2400 return (ENOSPC);
2401
2402 error = tmpfs_check_sticky(cred, tdnode, tnode);
2403 if (error)
2404 return error;
2405
2406 return 0;
2407 }
2408
2409 /*
2410 * Check whether removing node's entry in dnode is possible independent
2411 * of credentials.
2412 *
2413 * Everything must be locked and referenced.
2414 */
2415 int
tmpfs_remove_check_possible(struct tmpfs_node * dnode,struct tmpfs_node * node)2416 tmpfs_remove_check_possible(struct tmpfs_node *dnode, struct tmpfs_node *node)
2417 {
2418
2419 KASSERT(dnode != NULL);
2420 KASSERT(dnode->tn_vnode != NULL);
2421 KASSERT(node != NULL);
2422 KASSERT(dnode != node);
2423 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE);
2424 KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE);
2425
2426 /*
2427 * We want to delete the entry. If dnode is immutable, we
2428 * can't write to it to delete the entry. If dnode is
2429 * append-only, the only change we can make is to add entries,
2430 * so we can't delete entries. If node is immutable, we can't
2431 * change the links to it, so we can't delete the entry. If
2432 * node is append-only...well, this is what UFS does.
2433 */
2434 if ((dnode->tn_flags | node->tn_flags) & (IMMUTABLE | APPEND))
2435 return EPERM;
2436
2437 return 0;
2438 }
2439
2440 /*
2441 * Check whether removing node's entry in dnode is permitted given our
2442 * credentials.
2443 *
2444 * Everything must be locked and referenced.
2445 */
2446 int
tmpfs_remove_check_permitted(struct ucred * cred,struct tmpfs_node * dnode,struct tmpfs_node * node)2447 tmpfs_remove_check_permitted(struct ucred *cred,
2448 struct tmpfs_node *dnode, struct tmpfs_node *node)
2449 {
2450 int error;
2451
2452 KASSERT(dnode != NULL);
2453 KASSERT(dnode->tn_vnode != NULL);
2454 KASSERT(node != NULL);
2455 KASSERT(dnode != node);
2456 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE);
2457 KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE);
2458
2459 /*
2460 * Check whether we are permitted to write to the source
2461 * directory in order to delete an entry from it.
2462 */
2463 error = VOP_ACCESS(dnode->tn_vnode, VWRITE, cred, curproc);
2464 if (error)
2465 return error;
2466
2467 error = tmpfs_check_sticky(cred, dnode, node);
2468 if (error)
2469 return error;
2470
2471 return 0;
2472 }
2473
2474 /*
2475 * Check whether we may change an entry in a sticky directory. If the
2476 * directory is sticky, the user must own either the directory or, if
2477 * it exists, the node, in order to change the entry.
2478 *
2479 * Everything must be locked and referenced.
2480 */
2481 int
tmpfs_check_sticky(struct ucred * cred,struct tmpfs_node * dnode,struct tmpfs_node * node)2482 tmpfs_check_sticky(struct ucred *cred,
2483 struct tmpfs_node *dnode, struct tmpfs_node *node)
2484 {
2485
2486 KASSERT(dnode != NULL);
2487 KASSERT(dnode->tn_vnode != NULL);
2488 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE);
2489 KASSERT((node == NULL) || (node->tn_vnode != NULL));
2490 KASSERT((node == NULL) ||
2491 (VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE));
2492
2493 if (node == NULL)
2494 return 0;
2495
2496 if (dnode->tn_mode & S_ISTXT) {
2497 if (cred->cr_uid != 0 &&
2498 cred->cr_uid != dnode->tn_uid &&
2499 cred->cr_uid != node->tn_uid)
2500 return EPERM;
2501 }
2502
2503 return 0;
2504 }
2505
2506 void
tmpfs_rename_cache_purge(struct vnode * fdvp,struct vnode * fvp,struct vnode * tdvp,struct vnode * tvp)2507 tmpfs_rename_cache_purge(struct vnode *fdvp, struct vnode *fvp,
2508 struct vnode *tdvp, struct vnode *tvp)
2509 {
2510
2511 KASSERT(fdvp != NULL);
2512 KASSERT(fvp != NULL);
2513 KASSERT(tdvp != NULL);
2514 KASSERT(fdvp != fvp);
2515 KASSERT(fdvp != tvp);
2516 KASSERT(tdvp != fvp);
2517 KASSERT(tdvp != tvp);
2518 KASSERT(fvp != tvp);
2519 KASSERT(fdvp->v_type == VDIR);
2520 KASSERT(tdvp->v_type == VDIR);
2521
2522 /*
2523 * XXX What actually needs to be purged?
2524 */
2525
2526 cache_purge(fdvp);
2527
2528 if (fvp->v_type == VDIR)
2529 cache_purge(fvp);
2530
2531 if (tdvp != fdvp)
2532 cache_purge(tdvp);
2533
2534 if ((tvp != NULL) && (tvp->v_type == VDIR))
2535 cache_purge(tvp);
2536 }
2537
2538 void
tmpfs_rename_abort(void * v)2539 tmpfs_rename_abort(void *v)
2540 {
2541 struct vop_rename_args *ap = v;
2542 struct vnode *fdvp = ap->a_fdvp;
2543 struct vnode *fvp = ap->a_fvp;
2544 struct componentname *fcnp = ap->a_fcnp;
2545 struct vnode *tdvp = ap->a_tdvp;
2546 struct vnode *tvp = ap->a_tvp;
2547 struct componentname *tcnp = ap->a_tcnp;
2548
2549 VOP_ABORTOP(tdvp, tcnp);
2550 if (tdvp == tvp)
2551 vrele(tdvp);
2552 else
2553 vput(tdvp);
2554 if (tvp != NULL)
2555 vput(tvp);
2556 VOP_ABORTOP(fdvp, fcnp);
2557 vrele(fdvp);
2558 vrele(fvp);
2559 }
2560
2561 void filt_tmpfsdetach(struct knote *kn);
2562 int filt_tmpfsread(struct knote *kn, long hint);
2563 int filt_tmpfswrite(struct knote *kn, long hint);
2564 int filt_tmpfsvnode(struct knote *kn, long hint);
2565
2566 const struct filterops tmpfsread_filtops = {
2567 .f_flags = FILTEROP_ISFD,
2568 .f_attach = NULL,
2569 .f_detach = filt_tmpfsdetach,
2570 .f_event = filt_tmpfsread,
2571 };
2572
2573 const struct filterops tmpfswrite_filtops = {
2574 .f_flags = FILTEROP_ISFD,
2575 .f_attach = NULL,
2576 .f_detach = filt_tmpfsdetach,
2577 .f_event = filt_tmpfswrite,
2578 };
2579
2580 const struct filterops tmpfsvnode_filtops = {
2581 .f_flags = FILTEROP_ISFD,
2582 .f_attach = NULL,
2583 .f_detach = filt_tmpfsdetach,
2584 .f_event = filt_tmpfsvnode,
2585 };
2586
2587 int
tmpfs_kqfilter(void * v)2588 tmpfs_kqfilter(void *v)
2589 {
2590 struct vop_kqfilter_args *ap = v;
2591 struct vnode *vp = ap->a_vp;
2592 struct knote *kn = ap->a_kn;
2593
2594 switch (kn->kn_filter) {
2595 case EVFILT_READ:
2596 kn->kn_fop = &tmpfsread_filtops;
2597 break;
2598 case EVFILT_WRITE:
2599 kn->kn_fop = &tmpfswrite_filtops;
2600 break;
2601 case EVFILT_VNODE:
2602 kn->kn_fop = &tmpfsvnode_filtops;
2603 break;
2604 default:
2605 return (EINVAL);
2606 }
2607
2608 kn->kn_hook = (caddr_t)vp;
2609
2610 klist_insert_locked(&vp->v_klist, kn);
2611
2612 return (0);
2613 }
2614
2615 void
filt_tmpfsdetach(struct knote * kn)2616 filt_tmpfsdetach(struct knote *kn)
2617 {
2618 struct vnode *vp = (struct vnode *)kn->kn_hook;
2619
2620 klist_remove_locked(&vp->v_klist, kn);
2621 }
2622
2623 int
filt_tmpfsread(struct knote * kn,long hint)2624 filt_tmpfsread(struct knote *kn, long hint)
2625 {
2626 struct vnode *vp = (struct vnode *)kn->kn_hook;
2627 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
2628
2629 /*
2630 * filesystem is gone, so set the EOF flag and schedule
2631 * the knote for deletion.
2632 */
2633 if (hint == NOTE_REVOKE) {
2634 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
2635 return (1);
2636 }
2637
2638 kn->kn_data = node->tn_size - foffset(kn->kn_fp);
2639 if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) {
2640 kn->kn_fflags |= NOTE_EOF;
2641 return (1);
2642 }
2643
2644 if (kn->kn_flags & (__EV_POLL | __EV_SELECT))
2645 return (1);
2646
2647 return (kn->kn_data != 0);
2648 }
2649
2650 int
filt_tmpfswrite(struct knote * kn,long hint)2651 filt_tmpfswrite(struct knote *kn, long hint)
2652 {
2653 /*
2654 * filesystem is gone, so set the EOF flag and schedule
2655 * the knote for deletion.
2656 */
2657 if (hint == NOTE_REVOKE) {
2658 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
2659 return (1);
2660 }
2661
2662 kn->kn_data = 0;
2663 return (1);
2664 }
2665
2666 int
filt_tmpfsvnode(struct knote * kn,long hint)2667 filt_tmpfsvnode(struct knote *kn, long hint)
2668 {
2669 if (kn->kn_sfflags & hint)
2670 kn->kn_fflags |= hint;
2671 if (hint == NOTE_REVOKE) {
2672 kn->kn_flags |= EV_EOF;
2673 return (1);
2674 }
2675 return (kn->kn_fflags != 0);
2676 }
2677