]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/tmpfs/tmpfs_vnops.c
Merge commit 'acb089b983171667467adc66f56a723b609ed22e' into kbsd/vis
[FreeBSD/FreeBSD.git] / sys / fs / tmpfs / tmpfs_vnops.c
1 /*      $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $    */
2
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
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.
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 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/dirent.h>
44 #include <sys/extattr.h>
45 #include <sys/fcntl.h>
46 #include <sys/file.h>
47 #include <sys/filio.h>
48 #include <sys/limits.h>
49 #include <sys/lockf.h>
50 #include <sys/lock.h>
51 #include <sys/mount.h>
52 #include <sys/namei.h>
53 #include <sys/priv.h>
54 #include <sys/proc.h>
55 #include <sys/rwlock.h>
56 #include <sys/sched.h>
57 #include <sys/smr.h>
58 #include <sys/stat.h>
59 #include <sys/sysctl.h>
60 #include <sys/unistd.h>
61 #include <sys/vnode.h>
62 #include <security/audit/audit.h>
63 #include <security/mac/mac_framework.h>
64
65 #include <vm/vm.h>
66 #include <vm/vm_param.h>
67 #include <vm/vm_object.h>
68 #include <vm/vm_page.h>
69 #include <vm/vm_pager.h>
70 #include <vm/swap_pager.h>
71
72 #include <fs/tmpfs/tmpfs_vnops.h>
73 #include <fs/tmpfs/tmpfs.h>
74
75 SYSCTL_DECL(_vfs_tmpfs);
76 VFS_SMR_DECLARE;
77
78 static volatile int tmpfs_rename_restarts;
79 SYSCTL_INT(_vfs_tmpfs, OID_AUTO, rename_restarts, CTLFLAG_RD,
80     __DEVOLATILE(int *, &tmpfs_rename_restarts), 0,
81     "Times rename had to restart due to lock contention");
82
83 MALLOC_DEFINE(M_TMPFSEA, "tmpfs extattr", "tmpfs extattr structure");
84
85 static int
86 tmpfs_vn_get_ino_alloc(struct mount *mp, void *arg, int lkflags,
87     struct vnode **rvp)
88 {
89
90         return (tmpfs_alloc_vp(mp, arg, lkflags, rvp));
91 }
92
93 static int
94 tmpfs_lookup1(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
95 {
96         struct tmpfs_dirent *de;
97         struct tmpfs_node *dnode, *pnode;
98         struct tmpfs_mount *tm;
99         int error;
100
101         /* Caller assumes responsibility for ensuring access (VEXEC). */
102         dnode = VP_TO_TMPFS_DIR(dvp);
103         *vpp = NULLVP;
104
105         /* We cannot be requesting the parent directory of the root node. */
106         MPASS(IMPLIES(dnode->tn_type == VDIR &&
107             dnode->tn_dir.tn_parent == dnode,
108             !(cnp->cn_flags & ISDOTDOT)));
109
110         TMPFS_ASSERT_LOCKED(dnode);
111         if (dnode->tn_dir.tn_parent == NULL) {
112                 error = ENOENT;
113                 goto out;
114         }
115         if (cnp->cn_flags & ISDOTDOT) {
116                 tm = VFS_TO_TMPFS(dvp->v_mount);
117                 pnode = dnode->tn_dir.tn_parent;
118                 tmpfs_ref_node(pnode);
119                 error = vn_vget_ino_gen(dvp, tmpfs_vn_get_ino_alloc,
120                     pnode, cnp->cn_lkflags, vpp);
121                 tmpfs_free_node(tm, pnode);
122                 if (error != 0)
123                         goto out;
124         } else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
125                 VREF(dvp);
126                 *vpp = dvp;
127                 error = 0;
128         } else {
129                 de = tmpfs_dir_lookup(dnode, NULL, cnp);
130                 if (de != NULL && de->td_node == NULL)
131                         cnp->cn_flags |= ISWHITEOUT;
132                 if (de == NULL || de->td_node == NULL) {
133                         /*
134                          * The entry was not found in the directory.
135                          * This is OK if we are creating or renaming an
136                          * entry and are working on the last component of
137                          * the path name.
138                          */
139                         if ((cnp->cn_flags & ISLASTCN) &&
140                             (cnp->cn_nameiop == CREATE || \
141                             cnp->cn_nameiop == RENAME ||
142                             (cnp->cn_nameiop == DELETE &&
143                             cnp->cn_flags & DOWHITEOUT &&
144                             cnp->cn_flags & ISWHITEOUT))) {
145                                 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred,
146                                     curthread);
147                                 if (error != 0)
148                                         goto out;
149
150                                 error = EJUSTRETURN;
151                         } else
152                                 error = ENOENT;
153                 } else {
154                         struct tmpfs_node *tnode;
155
156                         /*
157                          * The entry was found, so get its associated
158                          * tmpfs_node.
159                          */
160                         tnode = de->td_node;
161
162                         /*
163                          * If we are not at the last path component and
164                          * found a non-directory or non-link entry (which
165                          * may itself be pointing to a directory), raise
166                          * an error.
167                          */
168                         if ((tnode->tn_type != VDIR &&
169                             tnode->tn_type != VLNK) &&
170                             !(cnp->cn_flags & ISLASTCN)) {
171                                 error = ENOTDIR;
172                                 goto out;
173                         }
174
175                         /*
176                          * If we are deleting or renaming the entry, keep
177                          * track of its tmpfs_dirent so that it can be
178                          * easily deleted later.
179                          */
180                         if ((cnp->cn_flags & ISLASTCN) &&
181                             (cnp->cn_nameiop == DELETE ||
182                             cnp->cn_nameiop == RENAME)) {
183                                 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred,
184                                     curthread);
185                                 if (error != 0)
186                                         goto out;
187
188                                 /* Allocate a new vnode on the matching entry. */
189                                 error = tmpfs_alloc_vp(dvp->v_mount, tnode,
190                                     cnp->cn_lkflags, vpp);
191                                 if (error != 0)
192                                         goto out;
193
194                                 if ((dnode->tn_mode & S_ISTXT) &&
195                                   VOP_ACCESS(dvp, VADMIN, cnp->cn_cred,
196                                   curthread) && VOP_ACCESS(*vpp, VADMIN,
197                                   cnp->cn_cred, curthread)) {
198                                         error = EPERM;
199                                         vput(*vpp);
200                                         *vpp = NULL;
201                                         goto out;
202                                 }
203                         } else {
204                                 error = tmpfs_alloc_vp(dvp->v_mount, tnode,
205                                     cnp->cn_lkflags, vpp);
206                                 if (error != 0)
207                                         goto out;
208                         }
209                 }
210         }
211
212         /*
213          * Store the result of this lookup in the cache.  Avoid this if the
214          * request was for creation, as it does not improve timings on
215          * emprical tests.
216          */
217         if ((cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp))
218                 cache_enter(dvp, *vpp, cnp);
219
220 out:
221 #ifdef INVARIANTS
222         /*
223          * If there were no errors, *vpp cannot be null and it must be
224          * locked.
225          */
226         if (error == 0) {
227                 MPASS(*vpp != NULLVP);
228                 ASSERT_VOP_LOCKED(*vpp, __func__);
229         } else {
230                 MPASS(*vpp == NULL);
231         }
232 #endif
233
234         return (error);
235 }
236
237 static int
238 tmpfs_cached_lookup(struct vop_cachedlookup_args *v)
239 {
240
241         return (tmpfs_lookup1(v->a_dvp, v->a_vpp, v->a_cnp));
242 }
243
244 static int
245 tmpfs_lookup(struct vop_lookup_args *v)
246 {
247         struct vnode *dvp = v->a_dvp;
248         struct vnode **vpp = v->a_vpp;
249         struct componentname *cnp = v->a_cnp;
250         int error;
251
252         /* Check accessibility of requested node as a first step. */
253         error = vn_dir_check_exec(dvp, cnp);
254         if (error != 0)
255                 return (error);
256
257         return (tmpfs_lookup1(dvp, vpp, cnp));
258 }
259
260 static int
261 tmpfs_create(struct vop_create_args *v)
262 {
263         struct vnode *dvp = v->a_dvp;
264         struct vnode **vpp = v->a_vpp;
265         struct componentname *cnp = v->a_cnp;
266         struct vattr *vap = v->a_vap;
267         int error;
268
269         MPASS(vap->va_type == VREG || vap->va_type == VSOCK);
270
271         error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
272         if (error == 0 && (cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp))
273                 cache_enter(dvp, *vpp, cnp);
274         return (error);
275 }
276
277 static int
278 tmpfs_mknod(struct vop_mknod_args *v)
279 {
280         struct vnode *dvp = v->a_dvp;
281         struct vnode **vpp = v->a_vpp;
282         struct componentname *cnp = v->a_cnp;
283         struct vattr *vap = v->a_vap;
284
285         if (vap->va_type != VBLK && vap->va_type != VCHR &&
286             vap->va_type != VFIFO)
287                 return (EINVAL);
288
289         return (tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL));
290 }
291
292 struct fileops tmpfs_fnops;
293
294 static int
295 tmpfs_open(struct vop_open_args *v)
296 {
297         struct vnode *vp;
298         struct tmpfs_node *node;
299         struct file *fp;
300         int error, mode;
301
302         vp = v->a_vp;
303         mode = v->a_mode;
304         node = VP_TO_TMPFS_NODE(vp);
305
306         /*
307          * The file is still active but all its names have been removed
308          * (e.g. by a "rmdir $(pwd)").  It cannot be opened any more as
309          * it is about to die.
310          */
311         if (node->tn_links < 1)
312                 return (ENOENT);
313
314         /* If the file is marked append-only, deny write requests. */
315         if (node->tn_flags & APPEND && (mode & (FWRITE | O_APPEND)) == FWRITE)
316                 error = EPERM;
317         else {
318                 error = 0;
319                 /* For regular files, the call below is nop. */
320                 KASSERT(vp->v_type != VREG || (node->tn_reg.tn_aobj->flags &
321                     OBJ_DEAD) == 0, ("dead object"));
322                 vnode_create_vobject(vp, node->tn_size, v->a_td);
323         }
324
325         fp = v->a_fp;
326         MPASS(fp == NULL || fp->f_data == NULL);
327         if (error == 0 && fp != NULL && vp->v_type == VREG) {
328                 tmpfs_ref_node(node);
329                 finit_vnode(fp, mode, node, &tmpfs_fnops);
330         }
331
332         return (error);
333 }
334
335 static int
336 tmpfs_close(struct vop_close_args *v)
337 {
338         struct vnode *vp = v->a_vp;
339
340         /* Update node times. */
341         tmpfs_update(vp);
342
343         return (0);
344 }
345
346 int
347 tmpfs_fo_close(struct file *fp, struct thread *td)
348 {
349         struct tmpfs_node *node;
350
351         node = fp->f_data;
352         if (node != NULL) {
353                 MPASS(node->tn_type == VREG);
354                 tmpfs_free_node(node->tn_reg.tn_tmp, node);
355         }
356         return (vnops.fo_close(fp, td));
357 }
358
359 /*
360  * VOP_FPLOOKUP_VEXEC routines are subject to special circumstances, see
361  * the comment above cache_fplookup for details.
362  */
363 int
364 tmpfs_fplookup_vexec(struct vop_fplookup_vexec_args *v)
365 {
366         struct vnode *vp;
367         struct tmpfs_node *node;
368         struct ucred *cred;
369         mode_t all_x, mode;
370
371         vp = v->a_vp;
372         node = VP_TO_TMPFS_NODE_SMR(vp);
373         if (__predict_false(node == NULL))
374                 return (EAGAIN);
375
376         all_x = S_IXUSR | S_IXGRP | S_IXOTH;
377         mode = atomic_load_short(&node->tn_mode);
378         if (__predict_true((mode & all_x) == all_x))
379                 return (0);
380
381         cred = v->a_cred;
382         return (vaccess_vexec_smr(mode, node->tn_uid, node->tn_gid, cred));
383 }
384
385 static int
386 tmpfs_access_locked(struct vnode *vp, struct tmpfs_node *node,
387     accmode_t accmode, struct ucred *cred)
388 {
389 #ifdef DEBUG_VFS_LOCKS
390         if (!mtx_owned(TMPFS_NODE_MTX(node))) {
391                 ASSERT_VOP_LOCKED(vp,
392                     "tmpfs_access_locked needs locked vnode or node");
393         }
394 #endif
395
396         if ((accmode & VWRITE) != 0 && (node->tn_flags & IMMUTABLE) != 0)
397                 return (EPERM);
398         return (vaccess(vp->v_type, node->tn_mode, node->tn_uid, node->tn_gid,
399             accmode, cred));
400 }
401
402 int
403 tmpfs_access(struct vop_access_args *v)
404 {
405         struct vnode *vp = v->a_vp;
406         struct ucred *cred = v->a_cred;
407         struct tmpfs_node *node = VP_TO_TMPFS_NODE(vp);
408         mode_t all_x = S_IXUSR | S_IXGRP | S_IXOTH;
409         accmode_t accmode = v->a_accmode;
410
411         /*
412          * Common case path lookup.
413          */
414         if (__predict_true(accmode == VEXEC &&
415             (node->tn_mode & all_x) == all_x))
416                 return (0);
417
418         switch (vp->v_type) {
419         case VDIR:
420                 /* FALLTHROUGH */
421         case VLNK:
422                 /* FALLTHROUGH */
423         case VREG:
424                 if ((accmode & VWRITE) != 0 &&
425                     (vp->v_mount->mnt_flag & MNT_RDONLY) != 0)
426                         return (EROFS);
427                 break;
428
429         case VBLK:
430                 /* FALLTHROUGH */
431         case VCHR:
432                 /* FALLTHROUGH */
433         case VSOCK:
434                 /* FALLTHROUGH */
435         case VFIFO:
436                 break;
437
438         default:
439                 return (EINVAL);
440         }
441
442         return (tmpfs_access_locked(vp, node, accmode, cred));
443 }
444
445 int
446 tmpfs_stat(struct vop_stat_args *v)
447 {
448         struct vnode *vp = v->a_vp;
449         struct stat *sb = v->a_sb;
450         struct tmpfs_node *node;
451         int error;
452
453         node = VP_TO_TMPFS_NODE(vp);
454
455         tmpfs_update_getattr(vp);
456
457         error = vop_stat_helper_pre(v);
458         if (__predict_false(error))
459                 return (error);
460
461         sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0];
462         sb->st_ino = node->tn_id;
463         sb->st_mode = node->tn_mode | VTTOIF(vp->v_type);
464         sb->st_nlink = node->tn_links;
465         sb->st_uid = node->tn_uid;
466         sb->st_gid = node->tn_gid;
467         sb->st_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ?
468                 node->tn_rdev : NODEV;
469         sb->st_size = node->tn_size;
470         sb->st_atim.tv_sec = node->tn_atime.tv_sec;
471         sb->st_atim.tv_nsec = node->tn_atime.tv_nsec;
472         sb->st_mtim.tv_sec = node->tn_mtime.tv_sec;
473         sb->st_mtim.tv_nsec = node->tn_mtime.tv_nsec;
474         sb->st_ctim.tv_sec = node->tn_ctime.tv_sec;
475         sb->st_ctim.tv_nsec = node->tn_ctime.tv_nsec;
476         sb->st_birthtim.tv_sec = node->tn_birthtime.tv_sec;
477         sb->st_birthtim.tv_nsec = node->tn_birthtime.tv_nsec;
478         sb->st_blksize = PAGE_SIZE;
479         sb->st_flags = node->tn_flags;
480         sb->st_gen = node->tn_gen;
481         if (vp->v_type == VREG) {
482 #ifdef __ILP32__
483                 vm_object_t obj = node->tn_reg.tn_aobj;
484
485                 /* Handle torn read */
486                 VM_OBJECT_RLOCK(obj);
487 #endif
488                 sb->st_blocks = ptoa(node->tn_reg.tn_pages);
489 #ifdef __ILP32__
490                 VM_OBJECT_RUNLOCK(obj);
491 #endif
492         } else {
493                 sb->st_blocks = node->tn_size;
494         }
495         sb->st_blocks /= S_BLKSIZE;
496         return (vop_stat_helper_post(v, error));
497 }
498
499 int
500 tmpfs_getattr(struct vop_getattr_args *v)
501 {
502         struct vnode *vp = v->a_vp;
503         struct vattr *vap = v->a_vap;
504         struct tmpfs_node *node;
505
506         node = VP_TO_TMPFS_NODE(vp);
507
508         tmpfs_update_getattr(vp);
509
510         vap->va_type = vp->v_type;
511         vap->va_mode = node->tn_mode;
512         vap->va_nlink = node->tn_links;
513         vap->va_uid = node->tn_uid;
514         vap->va_gid = node->tn_gid;
515         vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
516         vap->va_fileid = node->tn_id;
517         vap->va_size = node->tn_size;
518         vap->va_blocksize = PAGE_SIZE;
519         vap->va_atime = node->tn_atime;
520         vap->va_mtime = node->tn_mtime;
521         vap->va_ctime = node->tn_ctime;
522         vap->va_birthtime = node->tn_birthtime;
523         vap->va_gen = node->tn_gen;
524         vap->va_flags = node->tn_flags;
525         vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ?
526             node->tn_rdev : NODEV;
527         if (vp->v_type == VREG) {
528 #ifdef __ILP32__
529                 vm_object_t obj = node->tn_reg.tn_aobj;
530
531                 VM_OBJECT_RLOCK(obj);
532 #endif
533                 vap->va_bytes = ptoa(node->tn_reg.tn_pages);
534 #ifdef __ILP32__
535                 VM_OBJECT_RUNLOCK(obj);
536 #endif
537         } else {
538                 vap->va_bytes = node->tn_size;
539         }
540         vap->va_filerev = 0;
541
542         return (0);
543 }
544
545 int
546 tmpfs_setattr(struct vop_setattr_args *v)
547 {
548         struct vnode *vp = v->a_vp;
549         struct vattr *vap = v->a_vap;
550         struct ucred *cred = v->a_cred;
551         struct thread *td = curthread;
552
553         int error;
554
555         ASSERT_VOP_IN_SEQC(vp);
556
557         error = 0;
558
559         /* Abort if any unsettable attribute is given. */
560         if (vap->va_type != VNON ||
561             vap->va_nlink != VNOVAL ||
562             vap->va_fsid != VNOVAL ||
563             vap->va_fileid != VNOVAL ||
564             vap->va_blocksize != VNOVAL ||
565             vap->va_gen != VNOVAL ||
566             vap->va_rdev != VNOVAL ||
567             vap->va_bytes != VNOVAL)
568                 error = EINVAL;
569
570         if (error == 0 && (vap->va_flags != VNOVAL))
571                 error = tmpfs_chflags(vp, vap->va_flags, cred, td);
572
573         if (error == 0 && (vap->va_size != VNOVAL))
574                 error = tmpfs_chsize(vp, vap->va_size, cred, td);
575
576         if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL))
577                 error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred, td);
578
579         if (error == 0 && (vap->va_mode != (mode_t)VNOVAL))
580                 error = tmpfs_chmod(vp, vap->va_mode, cred, td);
581
582         if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL &&
583             vap->va_atime.tv_nsec != VNOVAL) ||
584             (vap->va_mtime.tv_sec != VNOVAL &&
585             vap->va_mtime.tv_nsec != VNOVAL) ||
586             (vap->va_birthtime.tv_sec != VNOVAL &&
587             vap->va_birthtime.tv_nsec != VNOVAL)))
588                 error = tmpfs_chtimes(vp, vap, cred, td);
589
590         /*
591          * Update the node times.  We give preference to the error codes
592          * generated by this function rather than the ones that may arise
593          * from tmpfs_update.
594          */
595         tmpfs_update(vp);
596
597         return (error);
598 }
599
600 static int
601 tmpfs_read(struct vop_read_args *v)
602 {
603         struct vnode *vp;
604         struct uio *uio;
605         struct tmpfs_node *node;
606
607         vp = v->a_vp;
608         if (vp->v_type != VREG)
609                 return (EISDIR);
610         uio = v->a_uio;
611         if (uio->uio_offset < 0)
612                 return (EINVAL);
613         node = VP_TO_TMPFS_NODE(vp);
614         tmpfs_set_accessed(VFS_TO_TMPFS(vp->v_mount), node);
615         return (uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio));
616 }
617
618 static int
619 tmpfs_read_pgcache(struct vop_read_pgcache_args *v)
620 {
621         struct vnode *vp;
622         struct tmpfs_node *node;
623         vm_object_t object;
624         off_t size;
625         int error;
626
627         vp = v->a_vp;
628         VNPASS((vn_irflag_read(vp) & VIRF_PGREAD) != 0, vp);
629
630         if (v->a_uio->uio_offset < 0)
631                 return (EINVAL);
632
633         error = EJUSTRETURN;
634         vfs_smr_enter();
635
636         node = VP_TO_TMPFS_NODE_SMR(vp);
637         if (node == NULL)
638                 goto out_smr;
639         MPASS(node->tn_type == VREG);
640         MPASS(node->tn_refcount >= 1);
641         object = node->tn_reg.tn_aobj;
642         if (object == NULL)
643                 goto out_smr;
644
645         MPASS(object->type == tmpfs_pager_type);
646         MPASS((object->flags & (OBJ_ANON | OBJ_DEAD | OBJ_SWAP)) ==
647             OBJ_SWAP);
648         if (!VN_IS_DOOMED(vp)) {
649                 /* size cannot become shorter due to rangelock. */
650                 size = node->tn_size;
651                 tmpfs_set_accessed(node->tn_reg.tn_tmp, node);
652                 vfs_smr_exit();
653                 error = uiomove_object(object, size, v->a_uio);
654                 return (error);
655         }
656 out_smr:
657         vfs_smr_exit();
658         return (error);
659 }
660
661 static int
662 tmpfs_write(struct vop_write_args *v)
663 {
664         struct vnode *vp;
665         struct uio *uio;
666         struct tmpfs_node *node;
667         off_t oldsize;
668         ssize_t r;
669         int error, ioflag;
670         mode_t newmode;
671
672         vp = v->a_vp;
673         uio = v->a_uio;
674         ioflag = v->a_ioflag;
675         error = 0;
676         node = VP_TO_TMPFS_NODE(vp);
677         oldsize = node->tn_size;
678
679         if (uio->uio_offset < 0 || vp->v_type != VREG)
680                 return (EINVAL);
681         if (uio->uio_resid == 0)
682                 return (0);
683         if (ioflag & IO_APPEND)
684                 uio->uio_offset = node->tn_size;
685         error = vn_rlimit_fsizex(vp, uio, VFS_TO_TMPFS(vp->v_mount)->
686             tm_maxfilesize, &r, uio->uio_td);
687         if (error != 0) {
688                 vn_rlimit_fsizex_res(uio, r);
689                 return (error);
690         }
691
692         if (uio->uio_offset + uio->uio_resid > node->tn_size) {
693                 error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid,
694                     FALSE);
695                 if (error != 0)
696                         goto out;
697         }
698
699         error = uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio);
700         node->tn_status |= TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED;
701         node->tn_accessed = true;
702         if (node->tn_mode & (S_ISUID | S_ISGID)) {
703                 if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID)) {
704                         newmode = node->tn_mode & ~(S_ISUID | S_ISGID);
705                         vn_seqc_write_begin(vp);
706                         atomic_store_short(&node->tn_mode, newmode);
707                         vn_seqc_write_end(vp);
708                 }
709         }
710         if (error != 0)
711                 (void)tmpfs_reg_resize(vp, oldsize, TRUE);
712
713 out:
714         MPASS(IMPLIES(error == 0, uio->uio_resid == 0));
715         MPASS(IMPLIES(error != 0, oldsize == node->tn_size));
716
717         vn_rlimit_fsizex_res(uio, r);
718         return (error);
719 }
720
721 static int
722 tmpfs_deallocate(struct vop_deallocate_args *v)
723 {
724         return (tmpfs_reg_punch_hole(v->a_vp, v->a_offset, v->a_len));
725 }
726
727 static int
728 tmpfs_fsync(struct vop_fsync_args *v)
729 {
730         struct vnode *vp = v->a_vp;
731
732         tmpfs_check_mtime(vp);
733         tmpfs_update(vp);
734
735         return (0);
736 }
737
738 static int
739 tmpfs_remove(struct vop_remove_args *v)
740 {
741         struct vnode *dvp = v->a_dvp;
742         struct vnode *vp = v->a_vp;
743
744         int error;
745         struct tmpfs_dirent *de;
746         struct tmpfs_mount *tmp;
747         struct tmpfs_node *dnode;
748         struct tmpfs_node *node;
749
750         if (vp->v_type == VDIR) {
751                 error = EISDIR;
752                 goto out;
753         }
754
755         dnode = VP_TO_TMPFS_DIR(dvp);
756         node = VP_TO_TMPFS_NODE(vp);
757         tmp = VFS_TO_TMPFS(vp->v_mount);
758         de = tmpfs_dir_lookup(dnode, node, v->a_cnp);
759         MPASS(de != NULL);
760
761         /* Files marked as immutable or append-only cannot be deleted. */
762         if ((node->tn_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
763             (dnode->tn_flags & APPEND)) {
764                 error = EPERM;
765                 goto out;
766         }
767
768         /* Remove the entry from the directory; as it is a file, we do not
769          * have to change the number of hard links of the directory. */
770         tmpfs_dir_detach(dvp, de);
771         if (v->a_cnp->cn_flags & DOWHITEOUT)
772                 tmpfs_dir_whiteout_add(dvp, v->a_cnp);
773
774         /* Free the directory entry we just deleted.  Note that the node
775          * referred by it will not be removed until the vnode is really
776          * reclaimed. */
777         tmpfs_free_dirent(tmp, de);
778
779         node->tn_status |= TMPFS_NODE_CHANGED;
780         node->tn_accessed = true;
781         error = 0;
782
783 out:
784         return (error);
785 }
786
787 static int
788 tmpfs_link(struct vop_link_args *v)
789 {
790         struct vnode *dvp = v->a_tdvp;
791         struct vnode *vp = v->a_vp;
792         struct componentname *cnp = v->a_cnp;
793
794         int error;
795         struct tmpfs_dirent *de;
796         struct tmpfs_node *node;
797
798         MPASS(dvp != vp); /* XXX When can this be false? */
799         node = VP_TO_TMPFS_NODE(vp);
800
801         /* Ensure that we do not overflow the maximum number of links imposed
802          * by the system. */
803         MPASS(node->tn_links <= TMPFS_LINK_MAX);
804         if (node->tn_links == TMPFS_LINK_MAX) {
805                 error = EMLINK;
806                 goto out;
807         }
808
809         /* We cannot create links of files marked immutable or append-only. */
810         if (node->tn_flags & (IMMUTABLE | APPEND)) {
811                 error = EPERM;
812                 goto out;
813         }
814
815         /* Allocate a new directory entry to represent the node. */
816         error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), node,
817             cnp->cn_nameptr, cnp->cn_namelen, &de);
818         if (error != 0)
819                 goto out;
820
821         /* Insert the new directory entry into the appropriate directory. */
822         if (cnp->cn_flags & ISWHITEOUT)
823                 tmpfs_dir_whiteout_remove(dvp, cnp);
824         tmpfs_dir_attach(dvp, de);
825
826         /* vp link count has changed, so update node times. */
827         node->tn_status |= TMPFS_NODE_CHANGED;
828         tmpfs_update(vp);
829
830         error = 0;
831
832 out:
833         return (error);
834 }
835
836 /*
837  * We acquire all but fdvp locks using non-blocking acquisitions.  If we
838  * fail to acquire any lock in the path we will drop all held locks,
839  * acquire the new lock in a blocking fashion, and then release it and
840  * restart the rename.  This acquire/release step ensures that we do not
841  * spin on a lock waiting for release.  On error release all vnode locks
842  * and decrement references the way tmpfs_rename() would do.
843  */
844 static int
845 tmpfs_rename_relock(struct vnode *fdvp, struct vnode **fvpp,
846     struct vnode *tdvp, struct vnode **tvpp,
847     struct componentname *fcnp, struct componentname *tcnp)
848 {
849         struct vnode *nvp;
850         struct mount *mp;
851         struct tmpfs_dirent *de;
852         int error, restarts = 0;
853
854         VOP_UNLOCK(tdvp);
855         if (*tvpp != NULL && *tvpp != tdvp)
856                 VOP_UNLOCK(*tvpp);
857         mp = fdvp->v_mount;
858
859 relock:
860         restarts += 1;
861         error = vn_lock(fdvp, LK_EXCLUSIVE);
862         if (error)
863                 goto releout;
864         if (vn_lock(tdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
865                 VOP_UNLOCK(fdvp);
866                 error = vn_lock(tdvp, LK_EXCLUSIVE);
867                 if (error)
868                         goto releout;
869                 VOP_UNLOCK(tdvp);
870                 goto relock;
871         }
872         /*
873          * Re-resolve fvp to be certain it still exists and fetch the
874          * correct vnode.
875          */
876         de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(fdvp), NULL, fcnp);
877         if (de == NULL) {
878                 VOP_UNLOCK(fdvp);
879                 VOP_UNLOCK(tdvp);
880                 if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
881                     (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
882                         error = EINVAL;
883                 else
884                         error = ENOENT;
885                 goto releout;
886         }
887         error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE | LK_NOWAIT, &nvp);
888         if (error != 0) {
889                 VOP_UNLOCK(fdvp);
890                 VOP_UNLOCK(tdvp);
891                 if (error != EBUSY)
892                         goto releout;
893                 error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE, &nvp);
894                 if (error != 0)
895                         goto releout;
896                 VOP_UNLOCK(nvp);
897                 /*
898                  * Concurrent rename race.
899                  */
900                 if (nvp == tdvp) {
901                         vrele(nvp);
902                         error = EINVAL;
903                         goto releout;
904                 }
905                 vrele(*fvpp);
906                 *fvpp = nvp;
907                 goto relock;
908         }
909         vrele(*fvpp);
910         *fvpp = nvp;
911         VOP_UNLOCK(*fvpp);
912         /*
913          * Re-resolve tvp and acquire the vnode lock if present.
914          */
915         de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(tdvp), NULL, tcnp);
916         /*
917          * If tvp disappeared we just carry on.
918          */
919         if (de == NULL && *tvpp != NULL) {
920                 vrele(*tvpp);
921                 *tvpp = NULL;
922         }
923         /*
924          * Get the tvp ino if the lookup succeeded.  We may have to restart
925          * if the non-blocking acquire fails.
926          */
927         if (de != NULL) {
928                 nvp = NULL;
929                 error = tmpfs_alloc_vp(mp, de->td_node,
930                     LK_EXCLUSIVE | LK_NOWAIT, &nvp);
931                 if (*tvpp != NULL)
932                         vrele(*tvpp);
933                 *tvpp = nvp;
934                 if (error != 0) {
935                         VOP_UNLOCK(fdvp);
936                         VOP_UNLOCK(tdvp);
937                         if (error != EBUSY)
938                                 goto releout;
939                         error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE,
940                             &nvp);
941                         if (error != 0)
942                                 goto releout;
943                         VOP_UNLOCK(nvp);
944                         /*
945                          * fdvp contains fvp, thus tvp (=fdvp) is not empty.
946                          */
947                         if (nvp == fdvp) {
948                                 error = ENOTEMPTY;
949                                 goto releout;
950                         }
951                         goto relock;
952                 }
953         }
954         tmpfs_rename_restarts += restarts;
955
956         return (0);
957
958 releout:
959         vrele(fdvp);
960         vrele(*fvpp);
961         vrele(tdvp);
962         if (*tvpp != NULL)
963                 vrele(*tvpp);
964         tmpfs_rename_restarts += restarts;
965
966         return (error);
967 }
968
969 static int
970 tmpfs_rename(struct vop_rename_args *v)
971 {
972         struct vnode *fdvp = v->a_fdvp;
973         struct vnode *fvp = v->a_fvp;
974         struct componentname *fcnp = v->a_fcnp;
975         struct vnode *tdvp = v->a_tdvp;
976         struct vnode *tvp = v->a_tvp;
977         struct componentname *tcnp = v->a_tcnp;
978         char *newname;
979         struct tmpfs_dirent *de;
980         struct tmpfs_mount *tmp;
981         struct tmpfs_node *fdnode;
982         struct tmpfs_node *fnode;
983         struct tmpfs_node *tnode;
984         struct tmpfs_node *tdnode;
985         int error;
986         bool want_seqc_end;
987
988         want_seqc_end = false;
989
990         /*
991          * Disallow cross-device renames.
992          * XXX Why isn't this done by the caller?
993          */
994         if (fvp->v_mount != tdvp->v_mount ||
995             (tvp != NULL && fvp->v_mount != tvp->v_mount)) {
996                 error = EXDEV;
997                 goto out;
998         }
999
1000         /* If source and target are the same file, there is nothing to do. */
1001         if (fvp == tvp) {
1002                 error = 0;
1003                 goto out;
1004         }
1005
1006         /*
1007          * If we need to move the directory between entries, lock the
1008          * source so that we can safely operate on it.
1009          */
1010         if (fdvp != tdvp && fdvp != tvp) {
1011                 if (vn_lock(fdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
1012                         error = tmpfs_rename_relock(fdvp, &fvp, tdvp, &tvp,
1013                             fcnp, tcnp);
1014                         if (error != 0)
1015                                 return (error);
1016                         ASSERT_VOP_ELOCKED(fdvp,
1017                             "tmpfs_rename: fdvp not locked");
1018                         ASSERT_VOP_ELOCKED(tdvp,
1019                             "tmpfs_rename: tdvp not locked");
1020                         if (tvp != NULL)
1021                                 ASSERT_VOP_ELOCKED(tvp,
1022                                     "tmpfs_rename: tvp not locked");
1023                         if (fvp == tvp) {
1024                                 error = 0;
1025                                 goto out_locked;
1026                         }
1027                 }
1028         }
1029
1030         /*
1031          * Avoid manipulating '.' and '..' entries.
1032          */
1033         if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
1034             (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')) {
1035                 error = EINVAL;
1036                 goto out_locked;
1037         }
1038
1039         if (tvp != NULL)
1040                 vn_seqc_write_begin(tvp);
1041         vn_seqc_write_begin(tdvp);
1042         vn_seqc_write_begin(fvp);
1043         vn_seqc_write_begin(fdvp);
1044         want_seqc_end = true;
1045
1046         tmp = VFS_TO_TMPFS(tdvp->v_mount);
1047         tdnode = VP_TO_TMPFS_DIR(tdvp);
1048         tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
1049         fdnode = VP_TO_TMPFS_DIR(fdvp);
1050         fnode = VP_TO_TMPFS_NODE(fvp);
1051         de = tmpfs_dir_lookup(fdnode, fnode, fcnp);
1052
1053         /*
1054          * Entry can disappear before we lock fdvp.
1055          */
1056         if (de == NULL) {
1057                 if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
1058                     (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
1059                         error = EINVAL;
1060                 else
1061                         error = ENOENT;
1062                 goto out_locked;
1063         }
1064         MPASS(de->td_node == fnode);
1065
1066         /*
1067          * If re-naming a directory to another preexisting directory
1068          * ensure that the target directory is empty so that its
1069          * removal causes no side effects.
1070          * Kern_rename guarantees the destination to be a directory
1071          * if the source is one.
1072          */
1073         if (tvp != NULL) {
1074                 MPASS(tnode != NULL);
1075
1076                 if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
1077                     (tdnode->tn_flags & (APPEND | IMMUTABLE))) {
1078                         error = EPERM;
1079                         goto out_locked;
1080                 }
1081
1082                 if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) {
1083                         if (tnode->tn_size > 0) {
1084                                 error = ENOTEMPTY;
1085                                 goto out_locked;
1086                         }
1087                 } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) {
1088                         error = ENOTDIR;
1089                         goto out_locked;
1090                 } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) {
1091                         error = EISDIR;
1092                         goto out_locked;
1093                 } else {
1094                         MPASS(fnode->tn_type != VDIR &&
1095                                 tnode->tn_type != VDIR);
1096                 }
1097         }
1098
1099         if ((fnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))
1100             || (fdnode->tn_flags & (APPEND | IMMUTABLE))) {
1101                 error = EPERM;
1102                 goto out_locked;
1103         }
1104
1105         /*
1106          * Ensure that we have enough memory to hold the new name, if it
1107          * has to be changed.
1108          */
1109         if (fcnp->cn_namelen != tcnp->cn_namelen ||
1110             bcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fcnp->cn_namelen) != 0) {
1111                 newname = malloc(tcnp->cn_namelen, M_TMPFSNAME, M_WAITOK);
1112         } else
1113                 newname = NULL;
1114
1115         /*
1116          * If the node is being moved to another directory, we have to do
1117          * the move.
1118          */
1119         if (fdnode != tdnode) {
1120                 /*
1121                  * In case we are moving a directory, we have to adjust its
1122                  * parent to point to the new parent.
1123                  */
1124                 if (de->td_node->tn_type == VDIR) {
1125                         struct tmpfs_node *n;
1126
1127                         TMPFS_NODE_LOCK(fnode);
1128                         error = tmpfs_access_locked(fvp, fnode, VWRITE,
1129                             tcnp->cn_cred);
1130                         TMPFS_NODE_UNLOCK(fnode);
1131                         if (error) {
1132                                 if (newname != NULL)
1133                                         free(newname, M_TMPFSNAME);
1134                                 goto out_locked;
1135                         }
1136
1137                         /*
1138                          * Ensure the target directory is not a child of the
1139                          * directory being moved.  Otherwise, we'd end up
1140                          * with stale nodes.
1141                          */
1142                         n = tdnode;
1143                         /*
1144                          * TMPFS_LOCK guaranties that no nodes are freed while
1145                          * traversing the list. Nodes can only be marked as
1146                          * removed: tn_parent == NULL.
1147                          */
1148                         TMPFS_LOCK(tmp);
1149                         TMPFS_NODE_LOCK(n);
1150                         while (n != n->tn_dir.tn_parent) {
1151                                 struct tmpfs_node *parent;
1152
1153                                 if (n == fnode) {
1154                                         TMPFS_NODE_UNLOCK(n);
1155                                         TMPFS_UNLOCK(tmp);
1156                                         error = EINVAL;
1157                                         if (newname != NULL)
1158                                                 free(newname, M_TMPFSNAME);
1159                                         goto out_locked;
1160                                 }
1161                                 parent = n->tn_dir.tn_parent;
1162                                 TMPFS_NODE_UNLOCK(n);
1163                                 if (parent == NULL) {
1164                                         n = NULL;
1165                                         break;
1166                                 }
1167                                 TMPFS_NODE_LOCK(parent);
1168                                 if (parent->tn_dir.tn_parent == NULL) {
1169                                         TMPFS_NODE_UNLOCK(parent);
1170                                         n = NULL;
1171                                         break;
1172                                 }
1173                                 n = parent;
1174                         }
1175                         TMPFS_UNLOCK(tmp);
1176                         if (n == NULL) {
1177                                 error = EINVAL;
1178                                 if (newname != NULL)
1179                                             free(newname, M_TMPFSNAME);
1180                                 goto out_locked;
1181                         }
1182                         TMPFS_NODE_UNLOCK(n);
1183
1184                         /* Adjust the parent pointer. */
1185                         TMPFS_VALIDATE_DIR(fnode);
1186                         TMPFS_NODE_LOCK(de->td_node);
1187                         de->td_node->tn_dir.tn_parent = tdnode;
1188                         TMPFS_NODE_UNLOCK(de->td_node);
1189
1190                         /*
1191                          * As a result of changing the target of the '..'
1192                          * entry, the link count of the source and target
1193                          * directories has to be adjusted.
1194                          */
1195                         TMPFS_NODE_LOCK(tdnode);
1196                         TMPFS_ASSERT_LOCKED(tdnode);
1197                         tdnode->tn_links++;
1198                         TMPFS_NODE_UNLOCK(tdnode);
1199
1200                         TMPFS_NODE_LOCK(fdnode);
1201                         TMPFS_ASSERT_LOCKED(fdnode);
1202                         fdnode->tn_links--;
1203                         TMPFS_NODE_UNLOCK(fdnode);
1204                 }
1205         }
1206
1207         /*
1208          * Do the move: just remove the entry from the source directory
1209          * and insert it into the target one.
1210          */
1211         tmpfs_dir_detach(fdvp, de);
1212
1213         if (fcnp->cn_flags & DOWHITEOUT)
1214                 tmpfs_dir_whiteout_add(fdvp, fcnp);
1215         if (tcnp->cn_flags & ISWHITEOUT)
1216                 tmpfs_dir_whiteout_remove(tdvp, tcnp);
1217
1218         /*
1219          * If the name has changed, we need to make it effective by changing
1220          * it in the directory entry.
1221          */
1222         if (newname != NULL) {
1223                 MPASS(tcnp->cn_namelen <= MAXNAMLEN);
1224
1225                 free(de->ud.td_name, M_TMPFSNAME);
1226                 de->ud.td_name = newname;
1227                 tmpfs_dirent_init(de, tcnp->cn_nameptr, tcnp->cn_namelen);
1228
1229                 fnode->tn_status |= TMPFS_NODE_CHANGED;
1230                 tdnode->tn_status |= TMPFS_NODE_MODIFIED;
1231         }
1232
1233         /*
1234          * If we are overwriting an entry, we have to remove the old one
1235          * from the target directory.
1236          */
1237         if (tvp != NULL) {
1238                 struct tmpfs_dirent *tde;
1239
1240                 /* Remove the old entry from the target directory. */
1241                 tde = tmpfs_dir_lookup(tdnode, tnode, tcnp);
1242                 tmpfs_dir_detach(tdvp, tde);
1243
1244                 /* Update node's ctime because of possible hardlinks. */
1245                 tnode->tn_status |= TMPFS_NODE_CHANGED;
1246                 tmpfs_update(tvp);
1247
1248                 /*
1249                  * Free the directory entry we just deleted.  Note that the
1250                  * node referred by it will not be removed until the vnode is
1251                  * really reclaimed.
1252                  */
1253                 tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), tde);
1254         }
1255
1256         tmpfs_dir_attach(tdvp, de);
1257
1258         if (tmpfs_use_nc(fvp)) {
1259                 cache_vop_rename(fdvp, fvp, tdvp, tvp, fcnp, tcnp);
1260         }
1261
1262         error = 0;
1263
1264 out_locked:
1265         if (fdvp != tdvp && fdvp != tvp)
1266                 VOP_UNLOCK(fdvp);
1267
1268 out:
1269         if (want_seqc_end) {
1270                 if (tvp != NULL)
1271                         vn_seqc_write_end(tvp);
1272                 vn_seqc_write_end(tdvp);
1273                 vn_seqc_write_end(fvp);
1274                 vn_seqc_write_end(fdvp);
1275         }
1276
1277         /*
1278          * Release target nodes.
1279          * XXX: I don't understand when tdvp can be the same as tvp, but
1280          * other code takes care of this...
1281          */
1282         if (tdvp == tvp)
1283                 vrele(tdvp);
1284         else
1285                 vput(tdvp);
1286         if (tvp != NULL)
1287                 vput(tvp);
1288
1289         /* Release source nodes. */
1290         vrele(fdvp);
1291         vrele(fvp);
1292
1293         return (error);
1294 }
1295
1296 static int
1297 tmpfs_mkdir(struct vop_mkdir_args *v)
1298 {
1299         struct vnode *dvp = v->a_dvp;
1300         struct vnode **vpp = v->a_vpp;
1301         struct componentname *cnp = v->a_cnp;
1302         struct vattr *vap = v->a_vap;
1303
1304         MPASS(vap->va_type == VDIR);
1305
1306         return (tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL));
1307 }
1308
1309 static int
1310 tmpfs_rmdir(struct vop_rmdir_args *v)
1311 {
1312         struct vnode *dvp = v->a_dvp;
1313         struct vnode *vp = v->a_vp;
1314
1315         int error;
1316         struct tmpfs_dirent *de;
1317         struct tmpfs_mount *tmp;
1318         struct tmpfs_node *dnode;
1319         struct tmpfs_node *node;
1320
1321         tmp = VFS_TO_TMPFS(dvp->v_mount);
1322         dnode = VP_TO_TMPFS_DIR(dvp);
1323         node = VP_TO_TMPFS_DIR(vp);
1324
1325         /* Directories with more than two entries ('.' and '..') cannot be
1326          * removed. */
1327          if (node->tn_size > 0) {
1328                  error = ENOTEMPTY;
1329                  goto out;
1330          }
1331
1332         if ((dnode->tn_flags & APPEND)
1333             || (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
1334                 error = EPERM;
1335                 goto out;
1336         }
1337
1338         /* This invariant holds only if we are not trying to remove "..".
1339           * We checked for that above so this is safe now. */
1340         MPASS(node->tn_dir.tn_parent == dnode);
1341
1342         /* Get the directory entry associated with node (vp).  This was
1343          * filled by tmpfs_lookup while looking up the entry. */
1344         de = tmpfs_dir_lookup(dnode, node, v->a_cnp);
1345         MPASS(TMPFS_DIRENT_MATCHES(de,
1346             v->a_cnp->cn_nameptr,
1347             v->a_cnp->cn_namelen));
1348
1349         /* Check flags to see if we are allowed to remove the directory. */
1350         if ((dnode->tn_flags & APPEND) != 0 ||
1351             (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) != 0) {
1352                 error = EPERM;
1353                 goto out;
1354         }
1355
1356         /* Detach the directory entry from the directory (dnode). */
1357         tmpfs_dir_detach(dvp, de);
1358         if (v->a_cnp->cn_flags & DOWHITEOUT)
1359                 tmpfs_dir_whiteout_add(dvp, v->a_cnp);
1360
1361         /* No vnode should be allocated for this entry from this point */
1362         TMPFS_NODE_LOCK(node);
1363         node->tn_links--;
1364         node->tn_dir.tn_parent = NULL;
1365         node->tn_status |= TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED;
1366         node->tn_accessed = true;
1367
1368         TMPFS_NODE_UNLOCK(node);
1369
1370         TMPFS_NODE_LOCK(dnode);
1371         dnode->tn_links--;
1372         dnode->tn_status |= TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED;
1373         dnode->tn_accessed = true;
1374         TMPFS_NODE_UNLOCK(dnode);
1375
1376         if (tmpfs_use_nc(dvp)) {
1377                 cache_vop_rmdir(dvp, vp);
1378         }
1379
1380         /* Free the directory entry we just deleted.  Note that the node
1381          * referred by it will not be removed until the vnode is really
1382          * reclaimed. */
1383         tmpfs_free_dirent(tmp, de);
1384
1385         /* Release the deleted vnode (will destroy the node, notify
1386          * interested parties and clean it from the cache). */
1387
1388         dnode->tn_status |= TMPFS_NODE_CHANGED;
1389         tmpfs_update(dvp);
1390
1391         error = 0;
1392
1393 out:
1394         return (error);
1395 }
1396
1397 static int
1398 tmpfs_symlink(struct vop_symlink_args *v)
1399 {
1400         struct vnode *dvp = v->a_dvp;
1401         struct vnode **vpp = v->a_vpp;
1402         struct componentname *cnp = v->a_cnp;
1403         struct vattr *vap = v->a_vap;
1404         const char *target = v->a_target;
1405
1406 #ifdef notyet /* XXX FreeBSD BUG: kern_symlink is not setting VLNK */
1407         MPASS(vap->va_type == VLNK);
1408 #else
1409         vap->va_type = VLNK;
1410 #endif
1411
1412         return (tmpfs_alloc_file(dvp, vpp, vap, cnp, target));
1413 }
1414
1415 static int
1416 tmpfs_readdir(struct vop_readdir_args *va)
1417 {
1418         struct vnode *vp;
1419         struct uio *uio;
1420         struct tmpfs_mount *tm;
1421         struct tmpfs_node *node;
1422         uint64_t **cookies;
1423         int *eofflag, *ncookies;
1424         ssize_t startresid;
1425         int error, maxcookies;
1426
1427         vp = va->a_vp;
1428         uio = va->a_uio;
1429         eofflag = va->a_eofflag;
1430         cookies = va->a_cookies;
1431         ncookies = va->a_ncookies;
1432
1433         /* This operation only makes sense on directory nodes. */
1434         if (vp->v_type != VDIR)
1435                 return (ENOTDIR);
1436
1437         maxcookies = 0;
1438         node = VP_TO_TMPFS_DIR(vp);
1439         tm = VFS_TO_TMPFS(vp->v_mount);
1440
1441         startresid = uio->uio_resid;
1442
1443         /* Allocate cookies for NFS and compat modules. */
1444         if (cookies != NULL && ncookies != NULL) {
1445                 maxcookies = howmany(node->tn_size,
1446                     sizeof(struct tmpfs_dirent)) + 2;
1447                 *cookies = malloc(maxcookies * sizeof(**cookies), M_TEMP,
1448                     M_WAITOK);
1449                 *ncookies = 0;
1450         }
1451
1452         if (cookies == NULL)
1453                 error = tmpfs_dir_getdents(tm, node, uio, 0, NULL, NULL);
1454         else
1455                 error = tmpfs_dir_getdents(tm, node, uio, maxcookies, *cookies,
1456                     ncookies);
1457
1458         /* Buffer was filled without hitting EOF. */
1459         if (error == EJUSTRETURN)
1460                 error = (uio->uio_resid != startresid) ? 0 : EINVAL;
1461
1462         if (error != 0 && cookies != NULL && ncookies != NULL) {
1463                 free(*cookies, M_TEMP);
1464                 *cookies = NULL;
1465                 *ncookies = 0;
1466         }
1467
1468         if (eofflag != NULL)
1469                 *eofflag =
1470                     (error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF);
1471
1472         return (error);
1473 }
1474
1475 static int
1476 tmpfs_readlink(struct vop_readlink_args *v)
1477 {
1478         struct vnode *vp = v->a_vp;
1479         struct uio *uio = v->a_uio;
1480
1481         int error;
1482         struct tmpfs_node *node;
1483
1484         MPASS(uio->uio_offset == 0);
1485         MPASS(vp->v_type == VLNK);
1486
1487         node = VP_TO_TMPFS_NODE(vp);
1488
1489         error = uiomove(node->tn_link_target, MIN(node->tn_size, uio->uio_resid),
1490             uio);
1491         tmpfs_set_accessed(VFS_TO_TMPFS(vp->v_mount), node);
1492
1493         return (error);
1494 }
1495
1496 /*
1497  * VOP_FPLOOKUP_SYMLINK routines are subject to special circumstances, see
1498  * the comment above cache_fplookup for details.
1499  *
1500  * Check tmpfs_alloc_node for tmpfs-specific synchronisation notes.
1501  */
1502 static int
1503 tmpfs_fplookup_symlink(struct vop_fplookup_symlink_args *v)
1504 {
1505         struct vnode *vp;
1506         struct tmpfs_node *node;
1507         char *symlink;
1508
1509         vp = v->a_vp;
1510         node = VP_TO_TMPFS_NODE_SMR(vp);
1511         if (__predict_false(node == NULL))
1512                 return (EAGAIN);
1513         if (!atomic_load_char(&node->tn_link_smr))
1514                 return (EAGAIN);
1515         symlink = atomic_load_ptr(&node->tn_link_target);
1516         if (symlink == NULL)
1517                 return (EAGAIN);
1518
1519         return (cache_symlink_resolve(v->a_fpl, symlink, node->tn_size));
1520 }
1521
1522 static int
1523 tmpfs_inactive(struct vop_inactive_args *v)
1524 {
1525         struct vnode *vp;
1526         struct tmpfs_node *node;
1527
1528         vp = v->a_vp;
1529         node = VP_TO_TMPFS_NODE(vp);
1530         if (node->tn_links == 0)
1531                 vrecycle(vp);
1532         else
1533                 tmpfs_check_mtime(vp);
1534         return (0);
1535 }
1536
1537 static int
1538 tmpfs_need_inactive(struct vop_need_inactive_args *ap)
1539 {
1540         struct vnode *vp;
1541         struct tmpfs_node *node;
1542         struct vm_object *obj;
1543
1544         vp = ap->a_vp;
1545         node = VP_TO_TMPFS_NODE(vp);
1546         if (node->tn_links == 0)
1547                 goto need;
1548         if (vp->v_type == VREG) {
1549                 obj = vp->v_object;
1550                 if (obj->generation != obj->cleangeneration)
1551                         goto need;
1552         }
1553         return (0);
1554 need:
1555         return (1);
1556 }
1557
1558 int
1559 tmpfs_reclaim(struct vop_reclaim_args *v)
1560 {
1561         struct vnode *vp;
1562         struct tmpfs_mount *tmp;
1563         struct tmpfs_node *node;
1564         bool unlock;
1565
1566         vp = v->a_vp;
1567         node = VP_TO_TMPFS_NODE(vp);
1568         tmp = VFS_TO_TMPFS(vp->v_mount);
1569
1570         if (vp->v_type == VREG)
1571                 tmpfs_destroy_vobject(vp, node->tn_reg.tn_aobj);
1572         vp->v_object = NULL;
1573
1574         TMPFS_LOCK(tmp);
1575         TMPFS_NODE_LOCK(node);
1576         tmpfs_free_vp(vp);
1577
1578         /*
1579          * If the node referenced by this vnode was deleted by the user,
1580          * we must free its associated data structures (now that the vnode
1581          * is being reclaimed).
1582          */
1583         unlock = true;
1584         if (node->tn_links == 0 &&
1585             (node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0) {
1586                 node->tn_vpstate = TMPFS_VNODE_DOOMED;
1587                 unlock = !tmpfs_free_node_locked(tmp, node, true);
1588         }
1589
1590         if (unlock) {
1591                 TMPFS_NODE_UNLOCK(node);
1592                 TMPFS_UNLOCK(tmp);
1593         }
1594
1595         MPASS(vp->v_data == NULL);
1596         return (0);
1597 }
1598
1599 int
1600 tmpfs_print(struct vop_print_args *v)
1601 {
1602         struct vnode *vp = v->a_vp;
1603
1604         struct tmpfs_node *node;
1605
1606         node = VP_TO_TMPFS_NODE(vp);
1607
1608         printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%lx, links %jd\n",
1609             node, node->tn_flags, (uintmax_t)node->tn_links);
1610         printf("\tmode 0%o, owner %d, group %d, size %jd, status 0x%x\n",
1611             node->tn_mode, node->tn_uid, node->tn_gid,
1612             (intmax_t)node->tn_size, node->tn_status);
1613
1614         if (vp->v_type == VFIFO)
1615                 fifo_printinfo(vp);
1616
1617         printf("\n");
1618
1619         return (0);
1620 }
1621
1622 int
1623 tmpfs_pathconf(struct vop_pathconf_args *v)
1624 {
1625         struct vnode *vp = v->a_vp;
1626         int name = v->a_name;
1627         long *retval = v->a_retval;
1628
1629         int error;
1630
1631         error = 0;
1632
1633         switch (name) {
1634         case _PC_LINK_MAX:
1635                 *retval = TMPFS_LINK_MAX;
1636                 break;
1637
1638         case _PC_SYMLINK_MAX:
1639                 *retval = MAXPATHLEN;
1640                 break;
1641
1642         case _PC_NAME_MAX:
1643                 *retval = NAME_MAX;
1644                 break;
1645
1646         case _PC_PIPE_BUF:
1647                 if (vp->v_type == VDIR || vp->v_type == VFIFO)
1648                         *retval = PIPE_BUF;
1649                 else
1650                         error = EINVAL;
1651                 break;
1652
1653         case _PC_CHOWN_RESTRICTED:
1654                 *retval = 1;
1655                 break;
1656
1657         case _PC_NO_TRUNC:
1658                 *retval = 1;
1659                 break;
1660
1661         case _PC_SYNC_IO:
1662                 *retval = 1;
1663                 break;
1664
1665         case _PC_FILESIZEBITS:
1666                 *retval = 64;
1667                 break;
1668
1669         case _PC_MIN_HOLE_SIZE:
1670                 *retval = PAGE_SIZE;
1671                 break;
1672
1673         default:
1674                 error = vop_stdpathconf(v);
1675         }
1676
1677         return (error);
1678 }
1679
1680 static int
1681 tmpfs_vptofh(struct vop_vptofh_args *ap)
1682 /*
1683 vop_vptofh {
1684         IN struct vnode *a_vp;
1685         IN struct fid *a_fhp;
1686 };
1687 */
1688 {
1689         struct tmpfs_fid_data tfd;
1690         struct tmpfs_node *node;
1691         struct fid *fhp;
1692
1693         node = VP_TO_TMPFS_NODE(ap->a_vp);
1694         fhp = ap->a_fhp;
1695         fhp->fid_len = sizeof(tfd);
1696
1697         /*
1698          * Copy into fid_data from the stack to avoid unaligned pointer use.
1699          * See the comment in sys/mount.h on struct fid for details.
1700          */
1701         tfd.tfd_id = node->tn_id;
1702         tfd.tfd_gen = node->tn_gen;
1703         memcpy(fhp->fid_data, &tfd, fhp->fid_len);
1704
1705         return (0);
1706 }
1707
1708 static int
1709 tmpfs_whiteout(struct vop_whiteout_args *ap)
1710 {
1711         struct vnode *dvp = ap->a_dvp;
1712         struct componentname *cnp = ap->a_cnp;
1713         struct tmpfs_dirent *de;
1714
1715         switch (ap->a_flags) {
1716         case LOOKUP:
1717                 return (0);
1718         case CREATE:
1719                 de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(dvp), NULL, cnp);
1720                 if (de != NULL)
1721                         return (de->td_node == NULL ? 0 : EEXIST);
1722                 return (tmpfs_dir_whiteout_add(dvp, cnp));
1723         case DELETE:
1724                 tmpfs_dir_whiteout_remove(dvp, cnp);
1725                 return (0);
1726         default:
1727                 panic("tmpfs_whiteout: unknown op");
1728         }
1729 }
1730
1731 static int
1732 tmpfs_vptocnp_dir(struct tmpfs_node *tn, struct tmpfs_node *tnp,
1733     struct tmpfs_dirent **pde)
1734 {
1735         struct tmpfs_dir_cursor dc;
1736         struct tmpfs_dirent *de;
1737
1738         for (de = tmpfs_dir_first(tnp, &dc); de != NULL;
1739              de = tmpfs_dir_next(tnp, &dc)) {
1740                 if (de->td_node == tn) {
1741                         *pde = de;
1742                         return (0);
1743                 }
1744         }
1745         return (ENOENT);
1746 }
1747
1748 static int
1749 tmpfs_vptocnp_fill(struct vnode *vp, struct tmpfs_node *tn,
1750     struct tmpfs_node *tnp, char *buf, size_t *buflen, struct vnode **dvp)
1751 {
1752         struct tmpfs_dirent *de;
1753         int error, i;
1754
1755         error = vn_vget_ino_gen(vp, tmpfs_vn_get_ino_alloc, tnp, LK_SHARED,
1756             dvp);
1757         if (error != 0)
1758                 return (error);
1759         error = tmpfs_vptocnp_dir(tn, tnp, &de);
1760         if (error == 0) {
1761                 i = *buflen;
1762                 i -= de->td_namelen;
1763                 if (i < 0) {
1764                         error = ENOMEM;
1765                 } else {
1766                         bcopy(de->ud.td_name, buf + i, de->td_namelen);
1767                         *buflen = i;
1768                 }
1769         }
1770         if (error == 0) {
1771                 if (vp != *dvp)
1772                         VOP_UNLOCK(*dvp);
1773         } else {
1774                 if (vp != *dvp)
1775                         vput(*dvp);
1776                 else
1777                         vrele(vp);
1778         }
1779         return (error);
1780 }
1781
1782 static int
1783 tmpfs_vptocnp(struct vop_vptocnp_args *ap)
1784 {
1785         struct vnode *vp, **dvp;
1786         struct tmpfs_node *tn, *tnp, *tnp1;
1787         struct tmpfs_dirent *de;
1788         struct tmpfs_mount *tm;
1789         char *buf;
1790         size_t *buflen;
1791         int error;
1792
1793         vp = ap->a_vp;
1794         dvp = ap->a_vpp;
1795         buf = ap->a_buf;
1796         buflen = ap->a_buflen;
1797
1798         tm = VFS_TO_TMPFS(vp->v_mount);
1799         tn = VP_TO_TMPFS_NODE(vp);
1800         if (tn->tn_type == VDIR) {
1801                 tnp = tn->tn_dir.tn_parent;
1802                 if (tnp == NULL)
1803                         return (ENOENT);
1804                 tmpfs_ref_node(tnp);
1805                 error = tmpfs_vptocnp_fill(vp, tn, tn->tn_dir.tn_parent, buf,
1806                     buflen, dvp);
1807                 tmpfs_free_node(tm, tnp);
1808                 return (error);
1809         }
1810 restart:
1811         TMPFS_LOCK(tm);
1812 restart_locked:
1813         LIST_FOREACH_SAFE(tnp, &tm->tm_nodes_used, tn_entries, tnp1) {
1814                 if (tnp->tn_type != VDIR)
1815                         continue;
1816                 TMPFS_NODE_LOCK(tnp);
1817                 tmpfs_ref_node(tnp);
1818
1819                 /*
1820                  * tn_vnode cannot be instantiated while we hold the
1821                  * node lock, so the directory cannot be changed while
1822                  * we iterate over it.  Do this to avoid instantiating
1823                  * vnode for directories which cannot point to our
1824                  * node.
1825                  */
1826                 error = tnp->tn_vnode == NULL ? tmpfs_vptocnp_dir(tn, tnp,
1827                     &de) : 0;
1828
1829                 if (error == 0) {
1830                         TMPFS_NODE_UNLOCK(tnp);
1831                         TMPFS_UNLOCK(tm);
1832                         error = tmpfs_vptocnp_fill(vp, tn, tnp, buf, buflen,
1833                             dvp);
1834                         if (error == 0) {
1835                                 tmpfs_free_node(tm, tnp);
1836                                 return (0);
1837                         }
1838                         if (VN_IS_DOOMED(vp)) {
1839                                 tmpfs_free_node(tm, tnp);
1840                                 return (ENOENT);
1841                         }
1842                         TMPFS_LOCK(tm);
1843                         TMPFS_NODE_LOCK(tnp);
1844                 }
1845                 if (tmpfs_free_node_locked(tm, tnp, false)) {
1846                         goto restart;
1847                 } else {
1848                         KASSERT(tnp->tn_refcount > 0,
1849                             ("node %p refcount zero", tnp));
1850                         if (tnp->tn_attached) {
1851                                 tnp1 = LIST_NEXT(tnp, tn_entries);
1852                                 TMPFS_NODE_UNLOCK(tnp);
1853                         } else {
1854                                 TMPFS_NODE_UNLOCK(tnp);
1855                                 goto restart_locked;
1856                         }
1857                 }
1858         }
1859         TMPFS_UNLOCK(tm);
1860         return (ENOENT);
1861 }
1862
1863 void
1864 tmpfs_extattr_free(struct tmpfs_extattr *ea)
1865 {
1866         free(ea->ea_name, M_TMPFSEA);
1867         free(ea->ea_value, M_TMPFSEA);
1868         free(ea, M_TMPFSEA);
1869 }
1870
1871 static bool
1872 tmpfs_extattr_update_mem(struct tmpfs_mount *tmp, ssize_t size)
1873 {
1874         TMPFS_LOCK(tmp);
1875         if (size > 0 &&
1876             !tmpfs_pages_check_avail(tmp, howmany(size, PAGE_SIZE))) {
1877                 TMPFS_UNLOCK(tmp);
1878                 return (false);
1879         }
1880         if (tmp->tm_ea_memory_inuse + size > tmp->tm_ea_memory_max) {
1881                 TMPFS_UNLOCK(tmp);
1882                 return (false);
1883         }
1884         tmp->tm_ea_memory_inuse += size;
1885         TMPFS_UNLOCK(tmp);
1886         return (true);
1887 }
1888
1889 static int
1890 tmpfs_deleteextattr(struct vop_deleteextattr_args *ap)
1891 {
1892         struct vnode *vp = ap->a_vp;
1893         struct tmpfs_mount *tmp;
1894         struct tmpfs_node *node;
1895         struct tmpfs_extattr *ea;
1896         size_t namelen;
1897         ssize_t diff;
1898         int error;
1899
1900         node = VP_TO_TMPFS_NODE(vp);
1901         tmp = VFS_TO_TMPFS(vp->v_mount);
1902         if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
1903                 return (EOPNOTSUPP);
1904         error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
1905             ap->a_cred, ap->a_td, VWRITE);
1906         if (error != 0)
1907                 return (error);
1908         if (ap->a_name == NULL || ap->a_name[0] == '\0')
1909                 return (EINVAL);
1910         namelen = strlen(ap->a_name);
1911         if (namelen > EXTATTR_MAXNAMELEN)
1912                 return (EINVAL);
1913
1914         LIST_FOREACH(ea, &node->tn_extattrs, ea_extattrs) {
1915                 if (ea->ea_namespace == ap->a_attrnamespace &&
1916                     namelen == ea->ea_namelen &&
1917                     memcmp(ap->a_name, ea->ea_name, namelen) == 0)
1918                         break;
1919         }
1920
1921         if (ea == NULL)
1922                 return (ENOATTR);
1923         LIST_REMOVE(ea, ea_extattrs);
1924         diff = -(sizeof(struct tmpfs_extattr) + namelen + ea->ea_size);
1925         tmpfs_extattr_update_mem(tmp, diff);
1926         tmpfs_extattr_free(ea);
1927         return (0);
1928 }
1929
1930 static int
1931 tmpfs_getextattr(struct vop_getextattr_args *ap)
1932 {
1933         struct vnode *vp = ap->a_vp;
1934         struct tmpfs_node *node;
1935         struct tmpfs_extattr *ea;
1936         size_t namelen;
1937         int error;
1938
1939         node = VP_TO_TMPFS_NODE(vp);
1940         if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
1941                 return (EOPNOTSUPP);
1942         error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
1943             ap->a_cred, ap->a_td, VREAD);
1944         if (error != 0)
1945                 return (error);
1946         if (ap->a_name == NULL || ap->a_name[0] == '\0')
1947                 return (EINVAL);
1948         namelen = strlen(ap->a_name);
1949         if (namelen > EXTATTR_MAXNAMELEN)
1950                 return (EINVAL);
1951
1952         LIST_FOREACH(ea, &node->tn_extattrs, ea_extattrs) {
1953                 if (ea->ea_namespace == ap->a_attrnamespace &&
1954                     namelen == ea->ea_namelen &&
1955                     memcmp(ap->a_name, ea->ea_name, namelen) == 0)
1956                         break;
1957         }
1958
1959         if (ea == NULL)
1960                 return (ENOATTR);
1961         if (ap->a_size != NULL)
1962                 *ap->a_size = ea->ea_size;
1963         if (ap->a_uio != NULL && ea->ea_size != 0)
1964                 error = uiomove(ea->ea_value, ea->ea_size, ap->a_uio);
1965         return (error);
1966 }
1967
1968 static int
1969 tmpfs_listextattr(struct vop_listextattr_args *ap)
1970 {
1971         struct vnode *vp = ap->a_vp;
1972         struct tmpfs_node *node;
1973         struct tmpfs_extattr *ea;
1974         int error;
1975
1976         node = VP_TO_TMPFS_NODE(vp);
1977         if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
1978                 return (EOPNOTSUPP);
1979         error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
1980             ap->a_cred, ap->a_td, VREAD);
1981         if (error != 0)
1982                 return (error);
1983         if (ap->a_size != NULL)
1984                 *ap->a_size = 0;
1985
1986         LIST_FOREACH(ea, &node->tn_extattrs, ea_extattrs) {
1987                 if (ea->ea_namespace != ap->a_attrnamespace)
1988                         continue;
1989                 if (ap->a_size != NULL)
1990                         *ap->a_size += ea->ea_namelen + 1;
1991                 if (ap->a_uio != NULL) {
1992                         error = uiomove(&ea->ea_namelen, 1, ap->a_uio);
1993                         if (error != 0)
1994                                 break;
1995                         error = uiomove(ea->ea_name, ea->ea_namelen, ap->a_uio);
1996                         if (error != 0)
1997                                 break;
1998                 }
1999         }
2000
2001         return (error);
2002 }
2003
2004 static int
2005 tmpfs_setextattr(struct vop_setextattr_args *ap)
2006 {
2007         struct vnode *vp = ap->a_vp;
2008         struct tmpfs_mount *tmp;
2009         struct tmpfs_node *node;
2010         struct tmpfs_extattr *ea;
2011         struct tmpfs_extattr *new_ea;
2012         size_t attr_size;
2013         size_t namelen;
2014         ssize_t diff;
2015         int error;
2016
2017         node = VP_TO_TMPFS_NODE(vp);
2018         tmp = VFS_TO_TMPFS(vp->v_mount);
2019         attr_size = ap->a_uio->uio_resid;
2020         diff = 0;
2021         if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
2022                 return (EOPNOTSUPP);
2023         error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
2024             ap->a_cred, ap->a_td, VWRITE);
2025         if (error != 0)
2026                 return (error);
2027         if (ap->a_name == NULL || ap->a_name[0] == '\0')
2028                 return (EINVAL);
2029         namelen = strlen(ap->a_name);
2030         if (namelen > EXTATTR_MAXNAMELEN)
2031                 return (EINVAL);
2032
2033         LIST_FOREACH(ea, &node->tn_extattrs, ea_extattrs) {
2034                 if (ea->ea_namespace == ap->a_attrnamespace &&
2035                     namelen == ea->ea_namelen &&
2036                     memcmp(ap->a_name, ea->ea_name, namelen) == 0) {
2037                         diff -= sizeof(struct tmpfs_extattr) + ea->ea_namelen +
2038                             ea->ea_size;
2039                         break;
2040                 }
2041         }
2042
2043         diff += sizeof(struct tmpfs_extattr) + namelen + attr_size;
2044         if (!tmpfs_extattr_update_mem(tmp, diff))
2045                 return (ENOSPC);
2046         new_ea = malloc(sizeof(struct tmpfs_extattr), M_TMPFSEA, M_WAITOK);
2047         new_ea->ea_namespace = ap->a_attrnamespace;
2048         new_ea->ea_name = malloc(namelen, M_TMPFSEA, M_WAITOK);
2049         new_ea->ea_namelen = namelen;
2050         memcpy(new_ea->ea_name, ap->a_name, namelen);
2051         if (attr_size != 0) {
2052                 new_ea->ea_value = malloc(attr_size, M_TMPFSEA, M_WAITOK);
2053                 new_ea->ea_size = attr_size;
2054                 error = uiomove(new_ea->ea_value, attr_size, ap->a_uio);
2055         } else {
2056                 new_ea->ea_value = NULL;
2057                 new_ea->ea_size = 0;
2058         }
2059         if (error != 0) {
2060                 tmpfs_extattr_update_mem(tmp, -diff);
2061                 tmpfs_extattr_free(new_ea);
2062                 return (error);
2063         }
2064         if (ea != NULL) {
2065                 LIST_REMOVE(ea, ea_extattrs);
2066                 tmpfs_extattr_free(ea);
2067         }
2068         LIST_INSERT_HEAD(&node->tn_extattrs, new_ea, ea_extattrs);
2069         return (0);
2070 }
2071
2072 static off_t
2073 tmpfs_seek_data_locked(vm_object_t obj, off_t noff)
2074 {
2075         vm_page_t m;
2076         vm_pindex_t p, p_m, p_swp;
2077
2078         p = OFF_TO_IDX(noff);
2079         m = vm_page_find_least(obj, p);
2080
2081         /*
2082          * Microoptimize the most common case for SEEK_DATA, where
2083          * there is no hole and the page is resident.
2084          */
2085         if (m != NULL && vm_page_any_valid(m) && m->pindex == p)
2086                 return (noff);
2087
2088         p_swp = swap_pager_find_least(obj, p);
2089         if (p_swp == p)
2090                 return (noff);
2091
2092         p_m = m == NULL ? obj->size : m->pindex;
2093         return (IDX_TO_OFF(MIN(p_m, p_swp)));
2094 }
2095
2096 static off_t
2097 tmpfs_seek_next(off_t noff)
2098 {
2099         return (noff + PAGE_SIZE - (noff & PAGE_MASK));
2100 }
2101
2102 static int
2103 tmpfs_seek_clamp(struct tmpfs_node *tn, off_t *noff, bool seekdata)
2104 {
2105         if (*noff < tn->tn_size)
2106                 return (0);
2107         if (seekdata)
2108                 return (ENXIO);
2109         *noff = tn->tn_size;
2110         return (0);
2111 }
2112
2113 static off_t
2114 tmpfs_seek_hole_locked(vm_object_t obj, off_t noff)
2115 {
2116         vm_page_t m;
2117         vm_pindex_t p, p_swp;
2118
2119         for (;; noff = tmpfs_seek_next(noff)) {
2120                 /*
2121                  * Walk over the largest sequential run of the valid pages.
2122                  */
2123                 for (m = vm_page_lookup(obj, OFF_TO_IDX(noff));
2124                     m != NULL && vm_page_any_valid(m);
2125                     m = vm_page_next(m), noff = tmpfs_seek_next(noff))
2126                         ;
2127
2128                 /*
2129                  * Found a hole in the object's page queue.  Check if
2130                  * there is a hole in the swap at the same place.
2131                  */
2132                 p = OFF_TO_IDX(noff);
2133                 p_swp = swap_pager_find_least(obj, p);
2134                 if (p_swp != p) {
2135                         noff = IDX_TO_OFF(p);
2136                         break;
2137                 }
2138         }
2139         return (noff);
2140 }
2141
2142 static int
2143 tmpfs_seek_datahole(struct vnode *vp, off_t *off, bool seekdata)
2144 {
2145         struct tmpfs_node *tn;
2146         vm_object_t obj;
2147         off_t noff;
2148         int error;
2149
2150         if (vp->v_type != VREG)
2151                 return (ENOTTY);
2152         tn = VP_TO_TMPFS_NODE(vp);
2153         noff = *off;
2154         if (noff < 0)
2155                 return (ENXIO);
2156         error = tmpfs_seek_clamp(tn, &noff, seekdata);
2157         if (error != 0)
2158                 return (error);
2159         obj = tn->tn_reg.tn_aobj;
2160
2161         VM_OBJECT_RLOCK(obj);
2162         noff = seekdata ? tmpfs_seek_data_locked(obj, noff) :
2163             tmpfs_seek_hole_locked(obj, noff);
2164         VM_OBJECT_RUNLOCK(obj);
2165
2166         error = tmpfs_seek_clamp(tn, &noff, seekdata);
2167         if (error == 0)
2168                 *off = noff;
2169         return (error);
2170 }
2171
2172 static int
2173 tmpfs_ioctl(struct vop_ioctl_args *ap)
2174 {
2175         struct vnode *vp = ap->a_vp;
2176         int error = 0;
2177
2178         switch (ap->a_command) {
2179         case FIOSEEKDATA:
2180         case FIOSEEKHOLE:
2181                 error = vn_lock(vp, LK_SHARED);
2182                 if (error != 0) {
2183                         error = EBADF;
2184                         break;
2185                 }
2186                 error = tmpfs_seek_datahole(vp, (off_t *)ap->a_data,
2187                     ap->a_command == FIOSEEKDATA);
2188                 VOP_UNLOCK(vp);
2189                 break;
2190         default:
2191                 error = ENOTTY;
2192                 break;
2193         }
2194         return (error);
2195 }
2196
2197 /*
2198  * Vnode operations vector used for files stored in a tmpfs file system.
2199  */
2200 struct vop_vector tmpfs_vnodeop_entries = {
2201         .vop_default =                  &default_vnodeops,
2202         .vop_lookup =                   vfs_cache_lookup,
2203         .vop_cachedlookup =             tmpfs_cached_lookup,
2204         .vop_create =                   tmpfs_create,
2205         .vop_mknod =                    tmpfs_mknod,
2206         .vop_open =                     tmpfs_open,
2207         .vop_close =                    tmpfs_close,
2208         .vop_fplookup_vexec =           tmpfs_fplookup_vexec,
2209         .vop_fplookup_symlink =         tmpfs_fplookup_symlink,
2210         .vop_access =                   tmpfs_access,
2211         .vop_stat =                     tmpfs_stat,
2212         .vop_getattr =                  tmpfs_getattr,
2213         .vop_setattr =                  tmpfs_setattr,
2214         .vop_read =                     tmpfs_read,
2215         .vop_read_pgcache =             tmpfs_read_pgcache,
2216         .vop_write =                    tmpfs_write,
2217         .vop_deallocate =               tmpfs_deallocate,
2218         .vop_fsync =                    tmpfs_fsync,
2219         .vop_remove =                   tmpfs_remove,
2220         .vop_link =                     tmpfs_link,
2221         .vop_rename =                   tmpfs_rename,
2222         .vop_mkdir =                    tmpfs_mkdir,
2223         .vop_rmdir =                    tmpfs_rmdir,
2224         .vop_symlink =                  tmpfs_symlink,
2225         .vop_readdir =                  tmpfs_readdir,
2226         .vop_readlink =                 tmpfs_readlink,
2227         .vop_inactive =                 tmpfs_inactive,
2228         .vop_need_inactive =            tmpfs_need_inactive,
2229         .vop_reclaim =                  tmpfs_reclaim,
2230         .vop_print =                    tmpfs_print,
2231         .vop_pathconf =                 tmpfs_pathconf,
2232         .vop_vptofh =                   tmpfs_vptofh,
2233         .vop_whiteout =                 tmpfs_whiteout,
2234         .vop_bmap =                     VOP_EOPNOTSUPP,
2235         .vop_vptocnp =                  tmpfs_vptocnp,
2236         .vop_lock1 =                    vop_lock,
2237         .vop_unlock =                   vop_unlock,
2238         .vop_islocked =                 vop_islocked,
2239         .vop_deleteextattr =            tmpfs_deleteextattr,
2240         .vop_getextattr =               tmpfs_getextattr,
2241         .vop_listextattr =              tmpfs_listextattr,
2242         .vop_setextattr =               tmpfs_setextattr,
2243         .vop_add_writecount =           vop_stdadd_writecount_nomsync,
2244         .vop_ioctl =                    tmpfs_ioctl,
2245 };
2246 VFS_VOP_VECTOR_REGISTER(tmpfs_vnodeop_entries);
2247
2248 /*
2249  * Same vector for mounts which do not use namecache.
2250  */
2251 struct vop_vector tmpfs_vnodeop_nonc_entries = {
2252         .vop_default =                  &tmpfs_vnodeop_entries,
2253         .vop_lookup =                   tmpfs_lookup,
2254 };
2255 VFS_VOP_VECTOR_REGISTER(tmpfs_vnodeop_nonc_entries);