1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2010-2012 Semihalf
5  * Copyright (c) 2008, 2009 Reinoud Zandijk
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * From: NetBSD: nilfs_vnops.c,v 1.2 2009/08/26 03:40:48 elad
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: stable/12/sys/fs/nandfs/nandfs_vnops.c 345972 2019-04-05 23:34:46Z sjg $");
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/lockf.h>
40 #include <sys/malloc.h>
41 #include <sys/mount.h>
42 #include <sys/mutex.h>
43 #include <sys/namei.h>
44 #include <sys/sysctl.h>
45 #include <sys/unistd.h>
46 #include <sys/vnode.h>
47 #include <sys/buf.h>
48 #include <sys/bio.h>
49 #include <sys/fcntl.h>
50 #include <sys/dirent.h>
51 #include <sys/rwlock.h>
52 #include <sys/stat.h>
53 #include <sys/priv.h>
54 
55 #include <vm/vm.h>
56 #include <vm/vm_extern.h>
57 #include <vm/vm_object.h>
58 #include <vm/vnode_pager.h>
59 
60 #include <machine/_inttypes.h>
61 
62 #include <fs/nandfs/nandfs_mount.h>
63 #include <fs/nandfs/nandfs.h>
64 #include <fs/nandfs/nandfs_subr.h>
65 
66 extern uma_zone_t nandfs_node_zone;
67 static void nandfs_read_filebuf(struct nandfs_node *, struct buf *);
68 static void nandfs_itimes_locked(struct vnode *);
69 static int nandfs_truncate(struct vnode *, uint64_t);
70 
71 static vop_pathconf_t	nandfs_pathconf;
72 
73 #define UPDATE_CLOSE 0
74 #define UPDATE_WAIT 0
75 
76 static int
nandfs_inactive(struct vop_inactive_args * ap)77 nandfs_inactive(struct vop_inactive_args *ap)
78 {
79 	struct vnode *vp = ap->a_vp;
80 	struct nandfs_node *node = VTON(vp);
81 	int error = 0;
82 
83 	DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, node));
84 
85 	if (node == NULL) {
86 		DPRINTF(NODE, ("%s: inactive NULL node\n", __func__));
87 		return (0);
88 	}
89 
90 	if (node->nn_inode.i_mode != 0 && !(node->nn_inode.i_links_count)) {
91 		nandfs_truncate(vp, 0);
92 		error = nandfs_node_destroy(node);
93 		if (error)
94 			nandfs_error("%s: destroy node: %p\n", __func__, node);
95 		node->nn_flags = 0;
96 		vrecycle(vp);
97 	}
98 
99 	return (error);
100 }
101 
102 static int
nandfs_reclaim(struct vop_reclaim_args * ap)103 nandfs_reclaim(struct vop_reclaim_args *ap)
104 {
105 	struct vnode *vp = ap->a_vp;
106 	struct nandfs_node *nandfs_node = VTON(vp);
107 	struct nandfs_device *fsdev = nandfs_node->nn_nandfsdev;
108 	uint64_t ino = nandfs_node->nn_ino;
109 
110 	DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, nandfs_node));
111 
112 	/* Invalidate all entries to a particular vnode. */
113 	cache_purge(vp);
114 
115 	/* Destroy the vm object and flush associated pages. */
116 	vnode_destroy_vobject(vp);
117 
118 	/* Remove from vfs hash if not system vnode */
119 	if (!NANDFS_SYS_NODE(nandfs_node->nn_ino))
120 		vfs_hash_remove(vp);
121 
122 	/* Dispose all node knowledge */
123 	nandfs_dispose_node(&nandfs_node);
124 
125 	if (!NANDFS_SYS_NODE(ino))
126 		NANDFS_WRITEUNLOCK(fsdev);
127 
128 	return (0);
129 }
130 
131 static int
nandfs_read(struct vop_read_args * ap)132 nandfs_read(struct vop_read_args *ap)
133 {
134 	struct vnode *vp = ap->a_vp;
135 	struct nandfs_node *node = VTON(vp);
136 	struct nandfs_device *nandfsdev = node->nn_nandfsdev;
137 	struct uio *uio = ap->a_uio;
138 	struct buf *bp;
139 	uint64_t size;
140 	uint32_t blocksize;
141 	off_t bytesinfile;
142 	ssize_t toread, off;
143 	daddr_t lbn;
144 	ssize_t resid;
145 	int error = 0;
146 
147 	if (uio->uio_resid == 0)
148 		return (0);
149 
150 	size = node->nn_inode.i_size;
151 	if (uio->uio_offset >= size)
152 		return (0);
153 
154 	blocksize = nandfsdev->nd_blocksize;
155 	bytesinfile = size - uio->uio_offset;
156 
157 	resid = omin(uio->uio_resid, bytesinfile);
158 
159 	while (resid) {
160 		lbn = uio->uio_offset / blocksize;
161 		off = uio->uio_offset & (blocksize - 1);
162 
163 		toread = omin(resid, blocksize - off);
164 
165 		DPRINTF(READ, ("nandfs_read bn: 0x%jx toread: 0x%zx (0x%x)\n",
166 		    (uintmax_t)lbn, toread, blocksize));
167 
168 		error = nandfs_bread(node, lbn, NOCRED, 0, &bp);
169 		if (error) {
170 			brelse(bp);
171 			break;
172 		}
173 
174 		error = uiomove(bp->b_data + off, toread, uio);
175 		if (error) {
176 			brelse(bp);
177 			break;
178 		}
179 
180 		brelse(bp);
181 		resid -= toread;
182 	}
183 
184 	return (error);
185 }
186 
187 static int
nandfs_write(struct vop_write_args * ap)188 nandfs_write(struct vop_write_args *ap)
189 {
190 	struct nandfs_device *fsdev;
191 	struct nandfs_node *node;
192 	struct vnode *vp;
193 	struct uio *uio;
194 	struct buf *bp;
195 	uint64_t file_size, vblk;
196 	uint32_t blocksize;
197 	ssize_t towrite, off;
198 	daddr_t lbn;
199 	ssize_t resid;
200 	int error, ioflag, modified;
201 
202 	vp = ap->a_vp;
203 	uio = ap->a_uio;
204 	ioflag = ap->a_ioflag;
205 	node = VTON(vp);
206 	fsdev = node->nn_nandfsdev;
207 
208 	if (nandfs_fs_full(fsdev))
209 		return (ENOSPC);
210 
211 	DPRINTF(WRITE, ("nandfs_write called %#zx at %#jx\n",
212 	    uio->uio_resid, (uintmax_t)uio->uio_offset));
213 
214 	if (uio->uio_offset < 0)
215 		return (EINVAL);
216 	if (uio->uio_resid == 0)
217 		return (0);
218 
219 	blocksize = fsdev->nd_blocksize;
220 	file_size = node->nn_inode.i_size;
221 
222 	switch (vp->v_type) {
223 	case VREG:
224 		if (ioflag & IO_APPEND)
225 			uio->uio_offset = file_size;
226 		break;
227 	case VDIR:
228 		return (EISDIR);
229 	case VLNK:
230 		break;
231 	default:
232 		panic("%s: bad file type vp: %p", __func__, vp);
233 	}
234 
235 	/* If explicitly asked to append, uio_offset can be wrong? */
236 	if (ioflag & IO_APPEND)
237 		uio->uio_offset = file_size;
238 
239 	resid = uio->uio_resid;
240 	modified = error = 0;
241 
242 	while (uio->uio_resid) {
243 		lbn = uio->uio_offset / blocksize;
244 		off = uio->uio_offset & (blocksize - 1);
245 
246 		towrite = omin(uio->uio_resid, blocksize - off);
247 
248 		DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x)\n",
249 		    __func__, (uintmax_t)lbn, towrite, blocksize));
250 
251 		error = nandfs_bmap_lookup(node, lbn, &vblk);
252 		if (error)
253 			break;
254 
255 		DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x) "
256 		    "vblk=%jx\n", __func__, (uintmax_t)lbn, towrite, blocksize,
257 		    vblk));
258 
259 		if (vblk != 0)
260 			error = nandfs_bread(node, lbn, NOCRED, 0, &bp);
261 		else
262 			error = nandfs_bcreate(node, lbn, NOCRED, 0, &bp);
263 
264 		DPRINTF(WRITE, ("%s: vp %p bread bp %p lbn %#jx\n", __func__,
265 		    vp, bp, (uintmax_t)lbn));
266 		if (error) {
267 			if (bp)
268 				brelse(bp);
269 			break;
270 		}
271 
272 		error = uiomove((char *)bp->b_data + off, (int)towrite, uio);
273 		if (error)
274 			break;
275 
276 		error = nandfs_dirty_buf(bp, 0);
277 		if (error)
278 			break;
279 
280 		modified++;
281 	}
282 
283 	/* XXX proper handling when only part of file was properly written */
284 	if (modified) {
285 		if (resid > uio->uio_resid && ap->a_cred &&
286 		    ap->a_cred->cr_uid != 0)
287 			node->nn_inode.i_mode &= ~(ISUID | ISGID);
288 
289 		if (file_size < uio->uio_offset + uio->uio_resid) {
290 			node->nn_inode.i_size = uio->uio_offset +
291 			    uio->uio_resid;
292 			node->nn_flags |= IN_CHANGE | IN_UPDATE;
293 			vnode_pager_setsize(vp, uio->uio_offset +
294 			    uio->uio_resid);
295 			nandfs_itimes(vp);
296 		}
297 	}
298 
299 	DPRINTF(WRITE, ("%s: return:%d\n", __func__, error));
300 
301 	return (error);
302 }
303 
304 static int
nandfs_lookup(struct vop_cachedlookup_args * ap)305 nandfs_lookup(struct vop_cachedlookup_args *ap)
306 {
307 	struct vnode *dvp, **vpp;
308 	struct componentname *cnp;
309 	struct ucred *cred;
310 	struct thread *td;
311 	struct nandfs_node *dir_node, *node;
312 	struct nandfsmount *nmp;
313 	uint64_t ino, off;
314 	const char *name;
315 	int namelen, nameiop, islastcn, mounted_ro;
316 	int error, found;
317 
318 	DPRINTF(VNCALL, ("%s\n", __func__));
319 
320 	dvp = ap->a_dvp;
321 	vpp = ap->a_vpp;
322 	*vpp = NULL;
323 
324 	cnp = ap->a_cnp;
325 	cred = cnp->cn_cred;
326 	td = cnp->cn_thread;
327 
328 	dir_node = VTON(dvp);
329 	nmp = dir_node->nn_nmp;
330 
331 	/* Simplify/clarification flags */
332 	nameiop = cnp->cn_nameiop;
333 	islastcn = cnp->cn_flags & ISLASTCN;
334 	mounted_ro = dvp->v_mount->mnt_flag & MNT_RDONLY;
335 
336 	/*
337 	 * If requesting a modify on the last path element on a read-only
338 	 * filingsystem, reject lookup;
339 	 */
340 	if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME))
341 		return (EROFS);
342 
343 	if (dir_node->nn_inode.i_links_count == 0)
344 		return (ENOENT);
345 
346 	/*
347 	 * Obviously, the file is not (anymore) in the namecache, we have to
348 	 * search for it. There are three basic cases: '.', '..' and others.
349 	 *
350 	 * Following the guidelines of VOP_LOOKUP manpage and tmpfs.
351 	 */
352 	error = 0;
353 	if ((cnp->cn_namelen == 1) && (cnp->cn_nameptr[0] == '.')) {
354 		DPRINTF(LOOKUP, ("\tlookup '.'\n"));
355 		/* Special case 1 '.' */
356 		VREF(dvp);
357 		*vpp = dvp;
358 		/* Done */
359 	} else if (cnp->cn_flags & ISDOTDOT) {
360 		/* Special case 2 '..' */
361 		DPRINTF(LOOKUP, ("\tlookup '..'\n"));
362 
363 		/* Get our node */
364 		name = "..";
365 		namelen = 2;
366 		error = nandfs_lookup_name_in_dir(dvp, name, namelen, &ino,
367 		    &found, &off);
368 		if (error)
369 			goto out;
370 		if (!found)
371 			error = ENOENT;
372 
373 		/* First unlock parent */
374 		VOP_UNLOCK(dvp, 0);
375 
376 		if (error == 0) {
377 			DPRINTF(LOOKUP, ("\tfound '..'\n"));
378 			/* Try to create/reuse the node */
379 			error = nandfs_get_node(nmp, ino, &node);
380 
381 			if (!error) {
382 				DPRINTF(LOOKUP,
383 				    ("\tnode retrieved/created OK\n"));
384 				*vpp = NTOV(node);
385 			}
386 		}
387 
388 		/* Try to relock parent */
389 		vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
390 	} else {
391 		DPRINTF(LOOKUP, ("\tlookup file\n"));
392 		/* All other files */
393 		/* Look up filename in the directory returning its inode */
394 		name = cnp->cn_nameptr;
395 		namelen = cnp->cn_namelen;
396 		error = nandfs_lookup_name_in_dir(dvp, name, namelen,
397 		    &ino, &found, &off);
398 		if (error)
399 			goto out;
400 		if (!found) {
401 			DPRINTF(LOOKUP, ("\tNOT found\n"));
402 			/*
403 			 * UGH, didn't find name. If we're creating or
404 			 * renaming on the last name this is OK and we ought
405 			 * to return EJUSTRETURN if its allowed to be created.
406 			 */
407 			error = ENOENT;
408 			if ((nameiop == CREATE || nameiop == RENAME) &&
409 			    islastcn) {
410 				error = VOP_ACCESS(dvp, VWRITE, cred, td);
411 				if (!error) {
412 					/* keep the component name */
413 					cnp->cn_flags |= SAVENAME;
414 					error = EJUSTRETURN;
415 				}
416 			}
417 			/* Done */
418 		} else {
419 			if (ino == NANDFS_WHT_INO)
420 				cnp->cn_flags |= ISWHITEOUT;
421 
422 			if ((cnp->cn_flags & ISWHITEOUT) &&
423 			    (nameiop == LOOKUP))
424 				return (ENOENT);
425 
426 			if ((nameiop == DELETE) && islastcn) {
427 				if ((cnp->cn_flags & ISWHITEOUT) &&
428 				    (cnp->cn_flags & DOWHITEOUT)) {
429 					cnp->cn_flags |= SAVENAME;
430 					dir_node->nn_diroff = off;
431 					return (EJUSTRETURN);
432 				}
433 
434 				error = VOP_ACCESS(dvp, VWRITE, cred,
435 				    cnp->cn_thread);
436 				if (error)
437 					return (error);
438 
439 				/* Try to create/reuse the node */
440 				error = nandfs_get_node(nmp, ino, &node);
441 				if (!error) {
442 					*vpp = NTOV(node);
443 					node->nn_diroff = off;
444 				}
445 
446 				if ((dir_node->nn_inode.i_mode & ISVTX) &&
447 				    cred->cr_uid != 0 &&
448 				    cred->cr_uid != dir_node->nn_inode.i_uid &&
449 				    node->nn_inode.i_uid != cred->cr_uid) {
450 					vput(*vpp);
451 					*vpp = NULL;
452 					return (EPERM);
453 				}
454 			} else if ((nameiop == RENAME) && islastcn) {
455 				error = VOP_ACCESS(dvp, VWRITE, cred,
456 				    cnp->cn_thread);
457 				if (error)
458 					return (error);
459 
460 				/* Try to create/reuse the node */
461 				error = nandfs_get_node(nmp, ino, &node);
462 				if (!error) {
463 					*vpp = NTOV(node);
464 					node->nn_diroff = off;
465 				}
466 			} else {
467 				/* Try to create/reuse the node */
468 				error = nandfs_get_node(nmp, ino, &node);
469 				if (!error) {
470 					*vpp = NTOV(node);
471 					node->nn_diroff = off;
472 				}
473 			}
474 		}
475 	}
476 
477 out:
478 	/*
479 	 * Store result in the cache if requested. If we are creating a file,
480 	 * the file might not be found and thus putting it into the namecache
481 	 * might be seen as negative caching.
482 	 */
483 	if ((cnp->cn_flags & MAKEENTRY) != 0)
484 		cache_enter(dvp, *vpp, cnp);
485 
486 	return (error);
487 
488 }
489 
490 static int
nandfs_getattr(struct vop_getattr_args * ap)491 nandfs_getattr(struct vop_getattr_args *ap)
492 {
493 	struct vnode *vp = ap->a_vp;
494 	struct vattr *vap = ap->a_vap;
495 	struct nandfs_node *node = VTON(vp);
496 	struct nandfs_inode *inode = &node->nn_inode;
497 
498 	DPRINTF(VNCALL, ("%s: vp: %p\n", __func__, vp));
499 	nandfs_itimes(vp);
500 
501 	/* Basic info */
502 	VATTR_NULL(vap);
503 	vap->va_atime.tv_sec = inode->i_mtime;
504 	vap->va_atime.tv_nsec = inode->i_mtime_nsec;
505 	vap->va_mtime.tv_sec = inode->i_mtime;
506 	vap->va_mtime.tv_nsec = inode->i_mtime_nsec;
507 	vap->va_ctime.tv_sec = inode->i_ctime;
508 	vap->va_ctime.tv_nsec = inode->i_ctime_nsec;
509 	vap->va_type = IFTOVT(inode->i_mode);
510 	vap->va_mode = inode->i_mode & ~S_IFMT;
511 	vap->va_nlink = inode->i_links_count;
512 	vap->va_uid = inode->i_uid;
513 	vap->va_gid = inode->i_gid;
514 	vap->va_rdev = inode->i_special;
515 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
516 	vap->va_fileid = node->nn_ino;
517 	vap->va_size = inode->i_size;
518 	vap->va_blocksize = node->nn_nandfsdev->nd_blocksize;
519 	vap->va_gen = 0;
520 	vap->va_flags = inode->i_flags;
521 	vap->va_bytes = inode->i_blocks * vap->va_blocksize;
522 	vap->va_filerev = 0;
523 	vap->va_vaflags = 0;
524 
525 	return (0);
526 }
527 
528 static int
nandfs_vtruncbuf(struct vnode * vp,uint64_t nblks)529 nandfs_vtruncbuf(struct vnode *vp, uint64_t nblks)
530 {
531 	struct nandfs_device *nffsdev;
532 	struct bufobj *bo;
533 	struct buf *bp, *nbp;
534 
535 	bo = &vp->v_bufobj;
536 	nffsdev = VTON(vp)->nn_nandfsdev;
537 
538 	ASSERT_VOP_LOCKED(vp, "nandfs_truncate");
539 restart:
540 	BO_LOCK(bo);
541 restart_locked:
542 	TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, nbp) {
543 		if (bp->b_lblkno < nblks)
544 			continue;
545 		if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL))
546 			goto restart_locked;
547 
548 		bremfree(bp);
549 		bp->b_flags |= (B_INVAL | B_RELBUF);
550 		bp->b_flags &= ~(B_ASYNC | B_MANAGED);
551 		BO_UNLOCK(bo);
552 		brelse(bp);
553 		BO_LOCK(bo);
554 	}
555 
556 	TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
557 		if (bp->b_lblkno < nblks)
558 			continue;
559 		if (BUF_LOCK(bp,
560 		    LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
561 		    BO_LOCKPTR(bo)) == ENOLCK)
562 			goto restart;
563 		bp->b_flags |= (B_INVAL | B_RELBUF);
564 		bp->b_flags &= ~(B_ASYNC | B_MANAGED);
565 		brelse(bp);
566 		nandfs_dirty_bufs_decrement(nffsdev);
567 		BO_LOCK(bo);
568 	}
569 
570 	BO_UNLOCK(bo);
571 
572 	return (0);
573 }
574 
575 static int
nandfs_truncate(struct vnode * vp,uint64_t newsize)576 nandfs_truncate(struct vnode *vp, uint64_t newsize)
577 {
578 	struct nandfs_device *nffsdev;
579 	struct nandfs_node *node;
580 	struct nandfs_inode *inode;
581 	struct buf *bp = NULL;
582 	uint64_t oblks, nblks, vblk, size, rest;
583 	int error;
584 
585 	node = VTON(vp);
586 	nffsdev = node->nn_nandfsdev;
587 	inode = &node->nn_inode;
588 
589 	/* Calculate end of file */
590 	size = inode->i_size;
591 
592 	if (newsize == size) {
593 		node->nn_flags |= IN_CHANGE | IN_UPDATE;
594 		nandfs_itimes(vp);
595 		return (0);
596 	}
597 
598 	if (newsize > size) {
599 		inode->i_size = newsize;
600 		vnode_pager_setsize(vp, newsize);
601 		node->nn_flags |= IN_CHANGE | IN_UPDATE;
602 		nandfs_itimes(vp);
603 		return (0);
604 	}
605 
606 	nblks = howmany(newsize, nffsdev->nd_blocksize);
607 	oblks = howmany(size, nffsdev->nd_blocksize);
608 	rest = newsize % nffsdev->nd_blocksize;
609 
610 	if (rest) {
611 		error = nandfs_bmap_lookup(node, nblks - 1, &vblk);
612 		if (error)
613 			return (error);
614 
615 		if (vblk != 0)
616 			error = nandfs_bread(node, nblks - 1, NOCRED, 0, &bp);
617 		else
618 			error = nandfs_bcreate(node, nblks - 1, NOCRED, 0, &bp);
619 
620 		if (error) {
621 			if (bp)
622 				brelse(bp);
623 			return (error);
624 		}
625 
626 		bzero((char *)bp->b_data + rest,
627 		    (u_int)(nffsdev->nd_blocksize - rest));
628 		error = nandfs_dirty_buf(bp, 0);
629 		if (error)
630 			return (error);
631 	}
632 
633 	DPRINTF(VNCALL, ("%s: vp %p oblks %jx nblks %jx\n", __func__, vp, oblks,
634 	    nblks));
635 
636 	error = nandfs_bmap_truncate_mapping(node, oblks - 1, nblks - 1);
637 	if (error) {
638 		if (bp)
639 			nandfs_undirty_buf(bp);
640 		return (error);
641 	}
642 
643 	error = nandfs_vtruncbuf(vp, nblks);
644 	if (error) {
645 		if (bp)
646 			nandfs_undirty_buf(bp);
647 		return (error);
648 	}
649 
650 	inode->i_size = newsize;
651 	vnode_pager_setsize(vp, newsize);
652 	node->nn_flags |= IN_CHANGE | IN_UPDATE;
653 	nandfs_itimes(vp);
654 
655 	return (error);
656 }
657 
658 static void
nandfs_itimes_locked(struct vnode * vp)659 nandfs_itimes_locked(struct vnode *vp)
660 {
661 	struct nandfs_node *node;
662 	struct nandfs_inode *inode;
663 	struct timespec ts;
664 
665 	ASSERT_VI_LOCKED(vp, __func__);
666 
667 	node = VTON(vp);
668 	inode = &node->nn_inode;
669 
670 	if ((node->nn_flags & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
671 		return;
672 
673 	if (((vp->v_mount->mnt_kern_flag &
674 	    (MNTK_SUSPENDED | MNTK_SUSPEND)) == 0) ||
675 	    (node->nn_flags & (IN_CHANGE | IN_UPDATE)))
676 		node->nn_flags |= IN_MODIFIED;
677 
678 	vfs_timestamp(&ts);
679 	if (node->nn_flags & IN_UPDATE) {
680 		inode->i_mtime = ts.tv_sec;
681 		inode->i_mtime_nsec = ts.tv_nsec;
682 	}
683 	if (node->nn_flags & IN_CHANGE) {
684 		inode->i_ctime = ts.tv_sec;
685 		inode->i_ctime_nsec = ts.tv_nsec;
686 	}
687 
688 	node->nn_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
689 }
690 
691 void
nandfs_itimes(struct vnode * vp)692 nandfs_itimes(struct vnode *vp)
693 {
694 
695 	VI_LOCK(vp);
696 	nandfs_itimes_locked(vp);
697 	VI_UNLOCK(vp);
698 }
699 
700 static int
nandfs_chmod(struct vnode * vp,int mode,struct ucred * cred,struct thread * td)701 nandfs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct thread *td)
702 {
703 	struct nandfs_node *node = VTON(vp);
704 	struct nandfs_inode *inode = &node->nn_inode;
705 	uint16_t nmode;
706 	int error = 0;
707 
708 	DPRINTF(VNCALL, ("%s: vp %p, mode %x, cred %p, td %p\n", __func__, vp,
709 	    mode, cred, td));
710 	/*
711 	 * To modify the permissions on a file, must possess VADMIN
712 	 * for that file.
713 	 */
714 	if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
715 		return (error);
716 
717 	/*
718 	 * Privileged processes may set the sticky bit on non-directories,
719 	 * as well as set the setgid bit on a file with a group that the
720 	 * process is not a member of. Both of these are allowed in
721 	 * jail(8).
722 	 */
723 	if (vp->v_type != VDIR && (mode & S_ISTXT)) {
724 		if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0))
725 			return (EFTYPE);
726 	}
727 	if (!groupmember(inode->i_gid, cred) && (mode & ISGID)) {
728 		error = priv_check_cred(cred, PRIV_VFS_SETGID, 0);
729 		if (error)
730 			return (error);
731 	}
732 
733 	/*
734 	 * Deny setting setuid if we are not the file owner.
735 	 */
736 	if ((mode & ISUID) && inode->i_uid != cred->cr_uid) {
737 		error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0);
738 		if (error)
739 			return (error);
740 	}
741 
742 	nmode = inode->i_mode;
743 	nmode &= ~ALLPERMS;
744 	nmode |= (mode & ALLPERMS);
745 	inode->i_mode = nmode;
746 	node->nn_flags |= IN_CHANGE;
747 
748 	DPRINTF(VNCALL, ("%s: to mode %x\n", __func__, nmode));
749 
750 	return (error);
751 }
752 
753 static int
nandfs_chown(struct vnode * vp,uid_t uid,gid_t gid,struct ucred * cred,struct thread * td)754 nandfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
755     struct thread *td)
756 {
757 	struct nandfs_node *node = VTON(vp);
758 	struct nandfs_inode *inode = &node->nn_inode;
759 	uid_t ouid;
760 	gid_t ogid;
761 	int error = 0;
762 
763 	if (uid == (uid_t)VNOVAL)
764 		uid = inode->i_uid;
765 	if (gid == (gid_t)VNOVAL)
766 		gid = inode->i_gid;
767 	/*
768 	 * To modify the ownership of a file, must possess VADMIN for that
769 	 * file.
770 	 */
771 	if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred, td)))
772 		return (error);
773 	/*
774 	 * To change the owner of a file, or change the group of a file to a
775 	 * group of which we are not a member, the caller must have
776 	 * privilege.
777 	 */
778 	if (((uid != inode->i_uid && uid != cred->cr_uid) ||
779 	    (gid != inode->i_gid && !groupmember(gid, cred))) &&
780 	    (error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0)))
781 		return (error);
782 	ogid = inode->i_gid;
783 	ouid = inode->i_uid;
784 
785 	inode->i_gid = gid;
786 	inode->i_uid = uid;
787 
788 	node->nn_flags |= IN_CHANGE;
789 	if ((inode->i_mode & (ISUID | ISGID)) &&
790 	    (ouid != uid || ogid != gid)) {
791 		if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0))
792 			inode->i_mode &= ~(ISUID | ISGID);
793 	}
794 	DPRINTF(VNCALL, ("%s: vp %p, cred %p, td %p - ret OK\n", __func__, vp,
795 	    cred, td));
796 	return (0);
797 }
798 
799 static int
nandfs_setattr(struct vop_setattr_args * ap)800 nandfs_setattr(struct vop_setattr_args *ap)
801 {
802 	struct vnode *vp = ap->a_vp;
803 	struct nandfs_node *node = VTON(vp);
804 	struct nandfs_inode *inode = &node->nn_inode;
805 	struct vattr *vap = ap->a_vap;
806 	struct ucred *cred = ap->a_cred;
807 	struct thread *td = curthread;
808 	uint32_t flags;
809 	int error = 0;
810 
811 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
812 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
813 	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
814 	    (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
815 		DPRINTF(VNCALL, ("%s: unsettable attribute\n", __func__));
816 		return (EINVAL);
817 	}
818 
819 	if (vap->va_flags != VNOVAL) {
820 		DPRINTF(VNCALL, ("%s: vp:%p td:%p flags:%lx\n", __func__, vp,
821 		    td, vap->va_flags));
822 
823 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
824 			return (EROFS);
825 		/*
826 		 * Callers may only modify the file flags on objects they
827 		 * have VADMIN rights for.
828 		 */
829 		if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
830 			return (error);
831 		/*
832 		 * Unprivileged processes are not permitted to unset system
833 		 * flags, or modify flags if any system flags are set.
834 		 * Privileged non-jail processes may not modify system flags
835 		 * if securelevel > 0 and any existing system flags are set.
836 		 * Privileged jail processes behave like privileged non-jail
837 		 * processes if the PR_ALLOW_CHFLAGS permission bit is set;
838 		 * otherwise, they behave like unprivileged processes.
839 		 */
840 
841 		flags = inode->i_flags;
842 		if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
843 			if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
844 				error = securelevel_gt(cred, 0);
845 				if (error)
846 					return (error);
847 			}
848 			/* Snapshot flag cannot be set or cleared */
849 			if (((vap->va_flags & SF_SNAPSHOT) != 0 &&
850 			    (flags & SF_SNAPSHOT) == 0) ||
851 			    ((vap->va_flags & SF_SNAPSHOT) == 0 &&
852 			    (flags & SF_SNAPSHOT) != 0))
853 				return (EPERM);
854 
855 			inode->i_flags = vap->va_flags;
856 		} else {
857 			if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
858 			    (vap->va_flags & UF_SETTABLE) != vap->va_flags)
859 				return (EPERM);
860 
861 			flags &= SF_SETTABLE;
862 			flags |= (vap->va_flags & UF_SETTABLE);
863 			inode->i_flags = flags;
864 		}
865 		node->nn_flags |= IN_CHANGE;
866 		if (vap->va_flags & (IMMUTABLE | APPEND))
867 			return (0);
868 	}
869 	if (inode->i_flags & (IMMUTABLE | APPEND))
870 		return (EPERM);
871 
872 	if (vap->va_size != (u_quad_t)VNOVAL) {
873 		DPRINTF(VNCALL, ("%s: vp:%p td:%p size:%jx\n", __func__, vp, td,
874 		    (uintmax_t)vap->va_size));
875 
876 		switch (vp->v_type) {
877 		case VDIR:
878 			return (EISDIR);
879 		case VLNK:
880 		case VREG:
881 			if (vp->v_mount->mnt_flag & MNT_RDONLY)
882 				return (EROFS);
883 			if ((inode->i_flags & SF_SNAPSHOT) != 0)
884 				return (EPERM);
885 			break;
886 		default:
887 			return (0);
888 		}
889 
890 		if (vap->va_size > node->nn_nandfsdev->nd_maxfilesize)
891 			return (EFBIG);
892 
893 		KASSERT((vp->v_type == VREG), ("Set size %d", vp->v_type));
894 		nandfs_truncate(vp, vap->va_size);
895 		node->nn_flags |= IN_CHANGE;
896 
897 		return (0);
898 	}
899 
900 	if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
901 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
902 			return (EROFS);
903 		DPRINTF(VNCALL, ("%s: vp:%p td:%p uid/gid %x/%x\n", __func__,
904 		    vp, td, vap->va_uid, vap->va_gid));
905 		error = nandfs_chown(vp, vap->va_uid, vap->va_gid, cred, td);
906 		if (error)
907 			return (error);
908 	}
909 
910 	if (vap->va_mode != (mode_t)VNOVAL) {
911 		if (vp->v_mount->mnt_flag & MNT_RDONLY)
912 			return (EROFS);
913 		DPRINTF(VNCALL, ("%s: vp:%p td:%p mode %x\n", __func__, vp, td,
914 		    vap->va_mode));
915 
916 		error = nandfs_chmod(vp, (int)vap->va_mode, cred, td);
917 		if (error)
918 			return (error);
919 	}
920 	if (vap->va_atime.tv_sec != VNOVAL ||
921 	    vap->va_mtime.tv_sec != VNOVAL ||
922 	    vap->va_birthtime.tv_sec != VNOVAL) {
923 		DPRINTF(VNCALL, ("%s: vp:%p td:%p time a/m/b %jx/%jx/%jx\n",
924 		    __func__, vp, td, (uintmax_t)vap->va_atime.tv_sec,
925 		    (uintmax_t)vap->va_mtime.tv_sec,
926 		    (uintmax_t)vap->va_birthtime.tv_sec));
927 
928 		if (vap->va_atime.tv_sec != VNOVAL)
929 			node->nn_flags |= IN_ACCESS;
930 		if (vap->va_mtime.tv_sec != VNOVAL)
931 			node->nn_flags |= IN_CHANGE | IN_UPDATE;
932 		if (vap->va_birthtime.tv_sec != VNOVAL)
933 			node->nn_flags |= IN_MODIFIED;
934 		nandfs_itimes(vp);
935 		return (0);
936 	}
937 
938 	return (0);
939 }
940 
941 static int
nandfs_open(struct vop_open_args * ap)942 nandfs_open(struct vop_open_args *ap)
943 {
944 	struct nandfs_node *node = VTON(ap->a_vp);
945 	uint64_t filesize;
946 
947 	DPRINTF(VNCALL, ("nandfs_open called ap->a_mode %x\n", ap->a_mode));
948 
949 	if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
950 		return (EOPNOTSUPP);
951 
952 	if ((node->nn_inode.i_flags & APPEND) &&
953 	    (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
954 		return (EPERM);
955 
956 	filesize = node->nn_inode.i_size;
957 	vnode_create_vobject(ap->a_vp, filesize, ap->a_td);
958 
959 	return (0);
960 }
961 
962 static int
nandfs_close(struct vop_close_args * ap)963 nandfs_close(struct vop_close_args *ap)
964 {
965 	struct vnode *vp = ap->a_vp;
966 	struct nandfs_node *node = VTON(vp);
967 
968 	DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node));
969 
970 	mtx_lock(&vp->v_interlock);
971 	if (vp->v_usecount > 1)
972 		nandfs_itimes_locked(vp);
973 	mtx_unlock(&vp->v_interlock);
974 
975 	return (0);
976 }
977 
978 static int
nandfs_check_possible(struct vnode * vp,struct vattr * vap,mode_t mode)979 nandfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
980 {
981 
982 	/* Check if we are allowed to write */
983 	switch (vap->va_type) {
984 	case VDIR:
985 	case VLNK:
986 	case VREG:
987 		/*
988 		 * Normal nodes: check if we're on a read-only mounted
989 		 * filingsystem and bomb out if we're trying to write.
990 		 */
991 		if ((mode & VMODIFY_PERMS) && (vp->v_mount->mnt_flag & MNT_RDONLY))
992 			return (EROFS);
993 		break;
994 	case VBLK:
995 	case VCHR:
996 	case VSOCK:
997 	case VFIFO:
998 		/*
999 		 * Special nodes: even on read-only mounted filingsystems
1000 		 * these are allowed to be written to if permissions allow.
1001 		 */
1002 		break;
1003 	default:
1004 		/* No idea what this is */
1005 		return (EINVAL);
1006 	}
1007 
1008 	/* No one may write immutable files */
1009 	if ((mode & VWRITE) && (VTON(vp)->nn_inode.i_flags & IMMUTABLE))
1010 		return (EPERM);
1011 
1012 	return (0);
1013 }
1014 
1015 static int
nandfs_check_permitted(struct vnode * vp,struct vattr * vap,mode_t mode,struct ucred * cred)1016 nandfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode,
1017     struct ucred *cred)
1018 {
1019 
1020 	return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, mode,
1021 	    cred, NULL));
1022 }
1023 
1024 static int
nandfs_advlock(struct vop_advlock_args * ap)1025 nandfs_advlock(struct vop_advlock_args *ap)
1026 {
1027 	struct nandfs_node *nvp;
1028 	quad_t size;
1029 
1030 	nvp = VTON(ap->a_vp);
1031 	size = nvp->nn_inode.i_size;
1032 	return (lf_advlock(ap, &(nvp->nn_lockf), size));
1033 }
1034 
1035 static int
nandfs_access(struct vop_access_args * ap)1036 nandfs_access(struct vop_access_args *ap)
1037 {
1038 	struct vnode *vp = ap->a_vp;
1039 	accmode_t accmode = ap->a_accmode;
1040 	struct ucred *cred = ap->a_cred;
1041 	struct vattr vap;
1042 	int error;
1043 
1044 	DPRINTF(VNCALL, ("%s: vp:%p mode: %x\n", __func__, vp, accmode));
1045 
1046 	error = VOP_GETATTR(vp, &vap, NULL);
1047 	if (error)
1048 		return (error);
1049 
1050 	error = nandfs_check_possible(vp, &vap, accmode);
1051 	if (error)
1052 		return (error);
1053 
1054 	error = nandfs_check_permitted(vp, &vap, accmode, cred);
1055 
1056 	return (error);
1057 }
1058 
1059 static int
nandfs_print(struct vop_print_args * ap)1060 nandfs_print(struct vop_print_args *ap)
1061 {
1062 	struct vnode *vp = ap->a_vp;
1063 	struct nandfs_node *nvp = VTON(vp);
1064 
1065 	printf("\tvp=%p, nandfs_node=%p\n", vp, nvp);
1066 	printf("nandfs inode %#jx\n", (uintmax_t)nvp->nn_ino);
1067 	printf("flags = 0x%b\n", (u_int)nvp->nn_flags, PRINT_NODE_FLAGS);
1068 
1069 	return (0);
1070 }
1071 
1072 static void
nandfs_read_filebuf(struct nandfs_node * node,struct buf * bp)1073 nandfs_read_filebuf(struct nandfs_node *node, struct buf *bp)
1074 {
1075 	struct nandfs_device *nandfsdev = node->nn_nandfsdev;
1076 	struct buf *nbp;
1077 	nandfs_daddr_t vblk, pblk;
1078 	nandfs_lbn_t from;
1079 	uint32_t blocksize;
1080 	int error = 0;
1081 	int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
1082 
1083 	/*
1084 	 * Translate all the block sectors into a series of buffers to read
1085 	 * asynchronously from the nandfs device. Note that this lookup may
1086 	 * induce readin's too.
1087 	 */
1088 
1089 	blocksize = nandfsdev->nd_blocksize;
1090 	if (bp->b_bcount / blocksize != 1)
1091 		panic("invalid b_count in bp %p\n", bp);
1092 
1093 	from = bp->b_blkno;
1094 
1095 	DPRINTF(READ, ("\tread in from inode %#jx blkno %#jx"
1096 	    " count %#lx\n", (uintmax_t)node->nn_ino, from,
1097 	    bp->b_bcount));
1098 
1099 	/* Get virtual block numbers for the vnode's buffer span */
1100 	error = nandfs_bmap_lookup(node, from, &vblk);
1101 	if (error) {
1102 		bp->b_error = EINVAL;
1103 		bp->b_ioflags |= BIO_ERROR;
1104 		bufdone(bp);
1105 		return;
1106 	}
1107 
1108 	/* Translate virtual block numbers to physical block numbers */
1109 	error = nandfs_vtop(node, vblk, &pblk);
1110 	if (error) {
1111 		bp->b_error = EINVAL;
1112 		bp->b_ioflags |= BIO_ERROR;
1113 		bufdone(bp);
1114 		return;
1115 	}
1116 
1117 	/* Issue translated blocks */
1118 	bp->b_resid = bp->b_bcount;
1119 
1120 	/* Note virtual block 0 marks not mapped */
1121 	if (vblk == 0) {
1122 		vfs_bio_clrbuf(bp);
1123 		bufdone(bp);
1124 		return;
1125 	}
1126 
1127 	nbp = bp;
1128 	nbp->b_blkno = pblk * blk2dev;
1129 	bp->b_iooffset = dbtob(nbp->b_blkno);
1130 	MPASS(bp->b_iooffset >= 0);
1131 	BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, nbp);
1132 	nandfs_vblk_set(bp, vblk);
1133 	DPRINTF(READ, ("read_filebuf : ino %#jx blk %#jx -> "
1134 	    "%#jx -> %#jx [bp %p]\n", (uintmax_t)node->nn_ino,
1135 	    (uintmax_t)(from), (uintmax_t)vblk,
1136 	    (uintmax_t)pblk, nbp));
1137 }
1138 
1139 static void
nandfs_write_filebuf(struct nandfs_node * node,struct buf * bp)1140 nandfs_write_filebuf(struct nandfs_node *node, struct buf *bp)
1141 {
1142 	struct nandfs_device *nandfsdev = node->nn_nandfsdev;
1143 
1144 	bp->b_iooffset = dbtob(bp->b_blkno);
1145 	MPASS(bp->b_iooffset >= 0);
1146 	BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, bp);
1147 }
1148 
1149 static int
nandfs_strategy(struct vop_strategy_args * ap)1150 nandfs_strategy(struct vop_strategy_args *ap)
1151 {
1152 	struct vnode *vp = ap->a_vp;
1153 	struct buf *bp = ap->a_bp;
1154 	struct nandfs_node *node = VTON(vp);
1155 
1156 
1157 	/* check if we ought to be here */
1158 	KASSERT((vp->v_type != VBLK && vp->v_type != VCHR),
1159 	    ("nandfs_strategy on type %d", vp->v_type));
1160 
1161 	/* Translate if needed and pass on */
1162 	if (bp->b_iocmd == BIO_READ) {
1163 		nandfs_read_filebuf(node, bp);
1164 		return (0);
1165 	}
1166 
1167 	/* Send to segment collector */
1168 	nandfs_write_filebuf(node, bp);
1169 	return (0);
1170 }
1171 
1172 static int
nandfs_readdir(struct vop_readdir_args * ap)1173 nandfs_readdir(struct vop_readdir_args *ap)
1174 {
1175 	struct uio *uio = ap->a_uio;
1176 	struct vnode *vp = ap->a_vp;
1177 	struct nandfs_node *node = VTON(vp);
1178 	struct nandfs_dir_entry *ndirent;
1179 	struct dirent dirent;
1180 	struct buf *bp;
1181 	uint64_t file_size, diroffset, transoffset, blkoff;
1182 	uint64_t blocknr;
1183 	uint32_t blocksize = node->nn_nandfsdev->nd_blocksize;
1184 	uint8_t *pos, name_len;
1185 	int error;
1186 
1187 	DPRINTF(READDIR, ("nandfs_readdir called\n"));
1188 
1189 	if (vp->v_type != VDIR)
1190 		return (ENOTDIR);
1191 
1192 	file_size = node->nn_inode.i_size;
1193 	DPRINTF(READDIR, ("nandfs_readdir filesize %jd resid %zd\n",
1194 	    (uintmax_t)file_size, uio->uio_resid ));
1195 
1196 	/* We are called just as long as we keep on pushing data in */
1197 	error = 0;
1198 	if ((uio->uio_offset < file_size) &&
1199 	    (uio->uio_resid >= sizeof(struct dirent))) {
1200 		diroffset = uio->uio_offset;
1201 		transoffset = diroffset;
1202 
1203 		blocknr = diroffset / blocksize;
1204 		blkoff = diroffset % blocksize;
1205 		error = nandfs_bread(node, blocknr, NOCRED, 0, &bp);
1206 		if (error) {
1207 			brelse(bp);
1208 			return (EIO);
1209 		}
1210 		while (diroffset < file_size) {
1211 			DPRINTF(READDIR, ("readdir : offset = %"PRIu64"\n",
1212 			    diroffset));
1213 			if (blkoff >= blocksize) {
1214 				blkoff = 0; blocknr++;
1215 				brelse(bp);
1216 				error = nandfs_bread(node, blocknr, NOCRED, 0,
1217 				    &bp);
1218 				if (error) {
1219 					brelse(bp);
1220 					return (EIO);
1221 				}
1222 			}
1223 
1224 			/* Read in one dirent */
1225 			pos = (uint8_t *)bp->b_data + blkoff;
1226 			ndirent = (struct nandfs_dir_entry *)pos;
1227 
1228 			name_len = ndirent->name_len;
1229 			memset(&dirent, 0, sizeof(dirent));
1230 			dirent.d_fileno = ndirent->inode;
1231 			if (dirent.d_fileno) {
1232 				dirent.d_type = ndirent->file_type;
1233 				dirent.d_namlen = name_len;
1234 				strncpy(dirent.d_name, ndirent->name, name_len);
1235 				dirent.d_reclen = GENERIC_DIRSIZ(&dirent);
1236 				/* NOTE: d_off is the offset of the *next* entry. */
1237 				dirent.d_off = diroffset + ndirent->rec_len;
1238 				dirent_terminate(&dirent);
1239 				DPRINTF(READDIR, ("copying `%*.*s`\n", name_len,
1240 				    name_len, dirent.d_name));
1241 			}
1242 
1243 			/*
1244 			 * If there isn't enough space in the uio to return a
1245 			 * whole dirent, break off read
1246 			 */
1247 			if (uio->uio_resid < GENERIC_DIRSIZ(&dirent))
1248 				break;
1249 
1250 			/* Transfer */
1251 			if (dirent.d_fileno)
1252 				uiomove(&dirent, dirent.d_reclen, uio);
1253 
1254 			/* Advance */
1255 			diroffset += ndirent->rec_len;
1256 			blkoff += ndirent->rec_len;
1257 
1258 			/* Remember the last entry we transferred */
1259 			transoffset = diroffset;
1260 		}
1261 		brelse(bp);
1262 
1263 		/* Pass on last transferred offset */
1264 		uio->uio_offset = transoffset;
1265 	}
1266 
1267 	if (ap->a_eofflag)
1268 		*ap->a_eofflag = (uio->uio_offset >= file_size);
1269 
1270 	return (error);
1271 }
1272 
1273 static int
nandfs_dirempty(struct vnode * dvp,uint64_t parentino,struct ucred * cred)1274 nandfs_dirempty(struct vnode *dvp, uint64_t parentino, struct ucred *cred)
1275 {
1276 	struct nandfs_node *dnode = VTON(dvp);
1277 	struct nandfs_dir_entry *dirent;
1278 	uint64_t file_size = dnode->nn_inode.i_size;
1279 	uint64_t blockcount = dnode->nn_inode.i_blocks;
1280 	uint64_t blocknr;
1281 	uint32_t blocksize = dnode->nn_nandfsdev->nd_blocksize;
1282 	uint32_t limit;
1283 	uint32_t off;
1284 	uint8_t	*pos;
1285 	struct buf *bp;
1286 	int error;
1287 
1288 	DPRINTF(LOOKUP, ("%s: dvp %p parentino %#jx cred %p\n", __func__, dvp,
1289 	    (uintmax_t)parentino, cred));
1290 
1291 	KASSERT((file_size != 0), ("nandfs_dirempty for NULL dir %p", dvp));
1292 
1293 	blocknr = 0;
1294 	while (blocknr < blockcount) {
1295 		error = nandfs_bread(dnode, blocknr, NOCRED, 0, &bp);
1296 		if (error) {
1297 			brelse(bp);
1298 			return (0);
1299 		}
1300 
1301 		pos = (uint8_t *)bp->b_data;
1302 		off = 0;
1303 
1304 		if (blocknr == (blockcount - 1))
1305 			limit = file_size % blocksize;
1306 		else
1307 			limit = blocksize;
1308 
1309 		while (off < limit) {
1310 			dirent = (struct nandfs_dir_entry *)(pos + off);
1311 			off += dirent->rec_len;
1312 
1313 			if (dirent->inode == 0)
1314 				continue;
1315 
1316 			switch (dirent->name_len) {
1317 			case 0:
1318 				break;
1319 			case 1:
1320 				if (dirent->name[0] != '.')
1321 					goto notempty;
1322 
1323 				KASSERT(dirent->inode == dnode->nn_ino,
1324 				    (".'s inode does not match dir"));
1325 				break;
1326 			case 2:
1327 				if (dirent->name[0] != '.' &&
1328 				    dirent->name[1] != '.')
1329 					goto notempty;
1330 
1331 				KASSERT(dirent->inode == parentino,
1332 				    ("..'s inode does not match parent"));
1333 				break;
1334 			default:
1335 				goto notempty;
1336 			}
1337 		}
1338 
1339 		brelse(bp);
1340 		blocknr++;
1341 	}
1342 
1343 	return (1);
1344 notempty:
1345 	brelse(bp);
1346 	return (0);
1347 }
1348 
1349 static int
nandfs_link(struct vop_link_args * ap)1350 nandfs_link(struct vop_link_args *ap)
1351 {
1352 	struct vnode *tdvp = ap->a_tdvp;
1353 	struct vnode *vp = ap->a_vp;
1354 	struct componentname *cnp = ap->a_cnp;
1355 	struct nandfs_node *node = VTON(vp);
1356 	struct nandfs_inode *inode = &node->nn_inode;
1357 	int error;
1358 
1359 	if (inode->i_links_count >= NANDFS_LINK_MAX)
1360 		return (EMLINK);
1361 
1362 	if (inode->i_flags & (IMMUTABLE | APPEND))
1363 		return (EPERM);
1364 
1365 	/* Update link count */
1366 	inode->i_links_count++;
1367 
1368 	/* Add dir entry */
1369 	error = nandfs_add_dirent(tdvp, node->nn_ino, cnp->cn_nameptr,
1370 	    cnp->cn_namelen, IFTODT(inode->i_mode));
1371 	if (error) {
1372 		inode->i_links_count--;
1373 	}
1374 
1375 	node->nn_flags |= IN_CHANGE;
1376 	nandfs_itimes(vp);
1377 	DPRINTF(VNCALL, ("%s: tdvp %p vp %p cnp %p\n",
1378 	    __func__, tdvp, vp, cnp));
1379 
1380 	return (0);
1381 }
1382 
1383 static int
nandfs_create(struct vop_create_args * ap)1384 nandfs_create(struct vop_create_args *ap)
1385 {
1386 	struct vnode *dvp = ap->a_dvp;
1387 	struct vnode **vpp = ap->a_vpp;
1388 	struct componentname *cnp = ap->a_cnp;
1389 	uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
1390 	struct nandfs_node *dir_node = VTON(dvp);
1391 	struct nandfsmount *nmp = dir_node->nn_nmp;
1392 	struct nandfs_node *node;
1393 	int error;
1394 
1395 	DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp));
1396 
1397 	if (nandfs_fs_full(dir_node->nn_nandfsdev))
1398 		return (ENOSPC);
1399 
1400 	/* Create new vnode/inode */
1401 	error = nandfs_node_create(nmp, &node, mode);
1402 	if (error)
1403 		return (error);
1404 	node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
1405 	node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
1406 
1407 	/* Add new dir entry */
1408 	error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
1409 	    cnp->cn_namelen, IFTODT(mode));
1410 	if (error) {
1411 		if (nandfs_node_destroy(node)) {
1412 			nandfs_error("%s: error destroying node %p\n",
1413 			    __func__, node);
1414 		}
1415 		return (error);
1416 	}
1417 	*vpp = NTOV(node);
1418 	if ((cnp->cn_flags & MAKEENTRY) != 0)
1419 		cache_enter(dvp, *vpp, cnp);
1420 
1421 	DPRINTF(VNCALL, ("created file vp %p nandnode %p ino %jx\n", *vpp, node,
1422 	    (uintmax_t)node->nn_ino));
1423 	return (0);
1424 }
1425 
1426 static int
nandfs_remove(struct vop_remove_args * ap)1427 nandfs_remove(struct vop_remove_args *ap)
1428 {
1429 	struct vnode *vp = ap->a_vp;
1430 	struct vnode *dvp = ap->a_dvp;
1431 	struct nandfs_node *node = VTON(vp);
1432 	struct nandfs_node *dnode = VTON(dvp);
1433 	struct componentname *cnp = ap->a_cnp;
1434 
1435 	DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx link %d\n",
1436 	    __func__, dvp, vp, node, (uintmax_t)node->nn_ino,
1437 	    node->nn_inode.i_links_count));
1438 
1439 	if (vp->v_type == VDIR)
1440 		return (EISDIR);
1441 
1442 	/* Files marked as immutable or append-only cannot be deleted. */
1443 	if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
1444 	    (dnode->nn_inode.i_flags & APPEND))
1445 		return (EPERM);
1446 
1447 	nandfs_remove_dirent(dvp, node, cnp);
1448 	node->nn_inode.i_links_count--;
1449 	node->nn_flags |= IN_CHANGE;
1450 
1451 	return (0);
1452 }
1453 
1454 /*
1455  * Check if source directory is in the path of the target directory.
1456  * Target is supplied locked, source is unlocked.
1457  * The target is always vput before returning.
1458  */
1459 static int
nandfs_checkpath(struct nandfs_node * src,struct nandfs_node * dest,struct ucred * cred)1460 nandfs_checkpath(struct nandfs_node *src, struct nandfs_node *dest,
1461     struct ucred *cred)
1462 {
1463 	struct vnode *vp;
1464 	int error, rootino;
1465 	struct nandfs_dir_entry dirent;
1466 
1467 	vp = NTOV(dest);
1468 	if (src->nn_ino == dest->nn_ino) {
1469 		error = EEXIST;
1470 		goto out;
1471 	}
1472 	rootino = NANDFS_ROOT_INO;
1473 	error = 0;
1474 	if (dest->nn_ino == rootino)
1475 		goto out;
1476 
1477 	for (;;) {
1478 		if (vp->v_type != VDIR) {
1479 			error = ENOTDIR;
1480 			break;
1481 		}
1482 
1483 		error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirent,
1484 		    NANDFS_DIR_REC_LEN(2), (off_t)0, UIO_SYSSPACE,
1485 		    IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED,
1486 		    NULL, NULL);
1487 		if (error != 0)
1488 			break;
1489 		if (dirent.name_len != 2 ||
1490 		    dirent.name[0] != '.' ||
1491 		    dirent.name[1] != '.') {
1492 			error = ENOTDIR;
1493 			break;
1494 		}
1495 		if (dirent.inode == src->nn_ino) {
1496 			error = EINVAL;
1497 			break;
1498 		}
1499 		if (dirent.inode == rootino)
1500 			break;
1501 		vput(vp);
1502 		if ((error = VFS_VGET(vp->v_mount, dirent.inode,
1503 		    LK_EXCLUSIVE, &vp)) != 0) {
1504 			vp = NULL;
1505 			break;
1506 		}
1507 	}
1508 
1509 out:
1510 	if (error == ENOTDIR)
1511 		printf("checkpath: .. not a directory\n");
1512 	if (vp != NULL)
1513 		vput(vp);
1514 	return (error);
1515 }
1516 
1517 static int
nandfs_rename(struct vop_rename_args * ap)1518 nandfs_rename(struct vop_rename_args *ap)
1519 {
1520 	struct vnode *tvp = ap->a_tvp;
1521 	struct vnode *tdvp = ap->a_tdvp;
1522 	struct vnode *fvp = ap->a_fvp;
1523 	struct vnode *fdvp = ap->a_fdvp;
1524 	struct componentname *tcnp = ap->a_tcnp;
1525 	struct componentname *fcnp = ap->a_fcnp;
1526 	int doingdirectory = 0, oldparent = 0, newparent = 0;
1527 	int error = 0;
1528 
1529 	struct nandfs_node *fdnode, *fnode, *fnode1;
1530 	struct nandfs_node *tdnode = VTON(tdvp);
1531 	struct nandfs_node *tnode;
1532 
1533 	uint32_t tdflags, fflags, fdflags;
1534 	uint16_t mode;
1535 
1536 	DPRINTF(VNCALL, ("%s: fdvp:%p fvp:%p tdvp:%p tdp:%p\n", __func__, fdvp,
1537 	    fvp, tdvp, tvp));
1538 
1539 	/*
1540 	 * Check for cross-device rename.
1541 	 */
1542 	if ((fvp->v_mount != tdvp->v_mount) ||
1543 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
1544 		error = EXDEV;
1545 abortit:
1546 		if (tdvp == tvp)
1547 			vrele(tdvp);
1548 		else
1549 			vput(tdvp);
1550 		if (tvp)
1551 			vput(tvp);
1552 		vrele(fdvp);
1553 		vrele(fvp);
1554 		return (error);
1555 	}
1556 
1557 	tdflags = tdnode->nn_inode.i_flags;
1558 	if (tvp &&
1559 	    ((VTON(tvp)->nn_inode.i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
1560 	    (tdflags & APPEND))) {
1561 		error = EPERM;
1562 		goto abortit;
1563 	}
1564 
1565 	/*
1566 	 * Renaming a file to itself has no effect.  The upper layers should
1567 	 * not call us in that case.  Temporarily just warn if they do.
1568 	 */
1569 	if (fvp == tvp) {
1570 		printf("nandfs_rename: fvp == tvp (can't happen)\n");
1571 		error = 0;
1572 		goto abortit;
1573 	}
1574 
1575 	if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
1576 		goto abortit;
1577 
1578 	fdnode = VTON(fdvp);
1579 	fnode = VTON(fvp);
1580 
1581 	if (fnode->nn_inode.i_links_count >= NANDFS_LINK_MAX) {
1582 		VOP_UNLOCK(fvp, 0);
1583 		error = EMLINK;
1584 		goto abortit;
1585 	}
1586 
1587 	fflags = fnode->nn_inode.i_flags;
1588 	fdflags = fdnode->nn_inode.i_flags;
1589 
1590 	if ((fflags & (NOUNLINK | IMMUTABLE | APPEND)) ||
1591 	    (fdflags & APPEND)) {
1592 		VOP_UNLOCK(fvp, 0);
1593 		error = EPERM;
1594 		goto abortit;
1595 	}
1596 
1597 	mode = fnode->nn_inode.i_mode;
1598 	if ((mode & S_IFMT) == S_IFDIR) {
1599 		/*
1600 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
1601 		 */
1602 
1603 		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1604 		    (fdvp == fvp) ||
1605 		    ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) ||
1606 		    (fnode->nn_flags & IN_RENAME)) {
1607 			VOP_UNLOCK(fvp, 0);
1608 			error = EINVAL;
1609 			goto abortit;
1610 		}
1611 		fnode->nn_flags |= IN_RENAME;
1612 		doingdirectory = 1;
1613 		DPRINTF(VNCALL, ("%s: doingdirectory dvp %p\n", __func__,
1614 		    tdvp));
1615 		oldparent = fdnode->nn_ino;
1616 	}
1617 
1618 	vrele(fdvp);
1619 
1620 	tnode = NULL;
1621 	if (tvp)
1622 		tnode = VTON(tvp);
1623 
1624 	/*
1625 	 * Bump link count on fvp while we are moving stuff around. If we
1626 	 * crash before completing the work, the link count may be wrong
1627 	 * but correctable.
1628 	 */
1629 	fnode->nn_inode.i_links_count++;
1630 
1631 	/* Check for in path moving XXX */
1632 	error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
1633 	VOP_UNLOCK(fvp, 0);
1634 	if (oldparent != tdnode->nn_ino)
1635 		newparent = tdnode->nn_ino;
1636 	if (doingdirectory && newparent) {
1637 		if (error)	/* write access check above */
1638 			goto bad;
1639 		if (tnode != NULL)
1640 			vput(tvp);
1641 
1642 		error = nandfs_checkpath(fnode, tdnode, tcnp->cn_cred);
1643 		if (error)
1644 			goto out;
1645 
1646 		VREF(tdvp);
1647 		error = relookup(tdvp, &tvp, tcnp);
1648 		if (error)
1649 			goto out;
1650 		vrele(tdvp);
1651 		tdnode = VTON(tdvp);
1652 		tnode = NULL;
1653 		if (tvp)
1654 			tnode = VTON(tvp);
1655 	}
1656 
1657 	/*
1658 	 * If the target doesn't exist, link the target to the source and
1659 	 * unlink the source. Otherwise, rewrite the target directory to
1660 	 * reference the source and remove the original entry.
1661 	 */
1662 
1663 	if (tvp == NULL) {
1664 		/*
1665 		 * Account for ".." in new directory.
1666 		 */
1667 		if (doingdirectory && fdvp != tdvp)
1668 			tdnode->nn_inode.i_links_count++;
1669 
1670 		DPRINTF(VNCALL, ("%s: new entry in dvp:%p\n", __func__, tdvp));
1671 		/*
1672 		 * Add name in new directory.
1673 		 */
1674 		error = nandfs_add_dirent(tdvp, fnode->nn_ino, tcnp->cn_nameptr,
1675 		    tcnp->cn_namelen, IFTODT(fnode->nn_inode.i_mode));
1676 		if (error) {
1677 			if (doingdirectory && fdvp != tdvp)
1678 				tdnode->nn_inode.i_links_count--;
1679 			goto bad;
1680 		}
1681 
1682 		vput(tdvp);
1683 	} else {
1684 		/*
1685 		 * If the parent directory is "sticky", then the user must
1686 		 * own the parent directory, or the destination of the rename,
1687 		 * otherwise the destination may not be changed (except by
1688 		 * root). This implements append-only directories.
1689 		 */
1690 		if ((tdnode->nn_inode.i_mode & S_ISTXT) &&
1691 		    tcnp->cn_cred->cr_uid != 0 &&
1692 		    tcnp->cn_cred->cr_uid != tdnode->nn_inode.i_uid &&
1693 		    tnode->nn_inode.i_uid != tcnp->cn_cred->cr_uid) {
1694 			error = EPERM;
1695 			goto bad;
1696 		}
1697 		/*
1698 		 * Target must be empty if a directory and have no links
1699 		 * to it. Also, ensure source and target are compatible
1700 		 * (both directories, or both not directories).
1701 		 */
1702 		mode = tnode->nn_inode.i_mode;
1703 		if ((mode & S_IFMT) == S_IFDIR) {
1704 			if (!nandfs_dirempty(tvp, tdnode->nn_ino,
1705 			    tcnp->cn_cred)) {
1706 				error = ENOTEMPTY;
1707 				goto bad;
1708 			}
1709 			if (!doingdirectory) {
1710 				error = ENOTDIR;
1711 				goto bad;
1712 			}
1713 			/*
1714 			 * Update name cache since directory is going away.
1715 			 */
1716 			cache_purge(tdvp);
1717 		} else if (doingdirectory) {
1718 			error = EISDIR;
1719 			goto bad;
1720 		}
1721 
1722 		DPRINTF(VNCALL, ("%s: update entry dvp:%p\n", __func__, tdvp));
1723 		/*
1724 		 * Change name tcnp in tdvp to point at fvp.
1725 		 */
1726 		error = nandfs_update_dirent(tdvp, fnode, tnode);
1727 		if (error)
1728 			goto bad;
1729 
1730 		if (doingdirectory && !newparent)
1731 			tdnode->nn_inode.i_links_count--;
1732 
1733 		vput(tdvp);
1734 
1735 		tnode->nn_inode.i_links_count--;
1736 		vput(tvp);
1737 		tnode = NULL;
1738 	}
1739 
1740 	/*
1741 	 * Unlink the source.
1742 	 */
1743 	fcnp->cn_flags &= ~MODMASK;
1744 	fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1745 	VREF(fdvp);
1746 	error = relookup(fdvp, &fvp, fcnp);
1747 	if (error == 0)
1748 		vrele(fdvp);
1749 	if (fvp != NULL) {
1750 		fnode1 = VTON(fvp);
1751 		fdnode = VTON(fdvp);
1752 	} else {
1753 		/*
1754 		 * From name has disappeared.
1755 		 */
1756 		if (doingdirectory)
1757 			panic("nandfs_rename: lost dir entry");
1758 		vrele(ap->a_fvp);
1759 		return (0);
1760 	}
1761 
1762 	DPRINTF(VNCALL, ("%s: unlink source fnode:%p\n", __func__, fnode));
1763 
1764 	/*
1765 	 * Ensure that the directory entry still exists and has not
1766 	 * changed while the new name has been entered. If the source is
1767 	 * a file then the entry may have been unlinked or renamed. In
1768 	 * either case there is no further work to be done. If the source
1769 	 * is a directory then it cannot have been rmdir'ed; its link
1770 	 * count of three would cause a rmdir to fail with ENOTEMPTY.
1771 	 * The IN_RENAME flag ensures that it cannot be moved by another
1772 	 * rename.
1773 	 */
1774 	if (fnode != fnode1) {
1775 		if (doingdirectory)
1776 			panic("nandfs: lost dir entry");
1777 	} else {
1778 		/*
1779 		 * If the source is a directory with a
1780 		 * new parent, the link count of the old
1781 		 * parent directory must be decremented
1782 		 * and ".." set to point to the new parent.
1783 		 */
1784 		if (doingdirectory && newparent) {
1785 			DPRINTF(VNCALL, ("%s: new parent %#jx -> %#jx\n",
1786 			    __func__, (uintmax_t) oldparent,
1787 			    (uintmax_t) newparent));
1788 			error = nandfs_update_parent_dir(fvp, newparent);
1789 			if (!error) {
1790 				fdnode->nn_inode.i_links_count--;
1791 				fdnode->nn_flags |= IN_CHANGE;
1792 			}
1793 		}
1794 		error = nandfs_remove_dirent(fdvp, fnode, fcnp);
1795 		if (!error) {
1796 			fnode->nn_inode.i_links_count--;
1797 			fnode->nn_flags |= IN_CHANGE;
1798 		}
1799 		fnode->nn_flags &= ~IN_RENAME;
1800 	}
1801 	if (fdnode)
1802 		vput(fdvp);
1803 	if (fnode)
1804 		vput(fvp);
1805 	vrele(ap->a_fvp);
1806 	return (error);
1807 
1808 bad:
1809 	DPRINTF(VNCALL, ("%s: error:%d\n", __func__, error));
1810 	if (tnode)
1811 		vput(NTOV(tnode));
1812 	vput(NTOV(tdnode));
1813 out:
1814 	if (doingdirectory)
1815 		fnode->nn_flags &= ~IN_RENAME;
1816 	if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
1817 		fnode->nn_inode.i_links_count--;
1818 		fnode->nn_flags |= IN_CHANGE;
1819 		fnode->nn_flags &= ~IN_RENAME;
1820 		vput(fvp);
1821 	} else
1822 		vrele(fvp);
1823 	return (error);
1824 }
1825 
1826 static int
nandfs_mkdir(struct vop_mkdir_args * ap)1827 nandfs_mkdir(struct vop_mkdir_args *ap)
1828 {
1829 	struct vnode *dvp = ap->a_dvp;
1830 	struct vnode **vpp = ap->a_vpp;
1831 	struct componentname *cnp = ap->a_cnp;
1832 	struct nandfs_node *dir_node = VTON(dvp);
1833 	struct nandfs_inode *dir_inode = &dir_node->nn_inode;
1834 	struct nandfs_node *node;
1835 	struct nandfsmount *nmp = dir_node->nn_nmp;
1836 	uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
1837 	int error;
1838 
1839 	DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp));
1840 
1841 	if (nandfs_fs_full(dir_node->nn_nandfsdev))
1842 		return (ENOSPC);
1843 
1844 	if (dir_inode->i_links_count >= NANDFS_LINK_MAX)
1845 		return (EMLINK);
1846 
1847 	error = nandfs_node_create(nmp, &node, mode);
1848 	if (error)
1849 		return (error);
1850 
1851 	node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
1852 	node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
1853 
1854 	*vpp = NTOV(node);
1855 
1856 	error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
1857 	    cnp->cn_namelen, IFTODT(mode));
1858 	if (error) {
1859 		vput(*vpp);
1860 		return (error);
1861 	}
1862 
1863 	dir_node->nn_inode.i_links_count++;
1864 	dir_node->nn_flags |= IN_CHANGE;
1865 
1866 	error = nandfs_init_dir(NTOV(node), node->nn_ino, dir_node->nn_ino);
1867 	if (error) {
1868 		vput(NTOV(node));
1869 		return (error);
1870 	}
1871 
1872 	DPRINTF(VNCALL, ("created dir vp %p nandnode %p ino %jx\n", *vpp, node,
1873 	    (uintmax_t)node->nn_ino));
1874 	return (0);
1875 }
1876 
1877 static int
nandfs_mknod(struct vop_mknod_args * ap)1878 nandfs_mknod(struct vop_mknod_args *ap)
1879 {
1880 	struct vnode *dvp = ap->a_dvp;
1881 	struct vnode **vpp = ap->a_vpp;
1882 	struct vattr *vap = ap->a_vap;
1883 	uint16_t mode = MAKEIMODE(vap->va_type, vap->va_mode);
1884 	struct componentname *cnp = ap->a_cnp;
1885 	struct nandfs_node *dir_node = VTON(dvp);
1886 	struct nandfsmount *nmp = dir_node->nn_nmp;
1887 	struct nandfs_node *node;
1888 	int error;
1889 
1890 	if (nandfs_fs_full(dir_node->nn_nandfsdev))
1891 		return (ENOSPC);
1892 
1893 	error = nandfs_node_create(nmp, &node, mode);
1894 	if (error)
1895 		return (error);
1896 	node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
1897 	node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
1898 	if (vap->va_rdev != VNOVAL)
1899 		node->nn_inode.i_special = vap->va_rdev;
1900 
1901 	*vpp = NTOV(node);
1902 
1903 	if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
1904 	    cnp->cn_namelen, IFTODT(mode))) {
1905 		vput(*vpp);
1906 		return (ENOTDIR);
1907 	}
1908 
1909 	node->nn_flags |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1910 
1911 	return (0);
1912 }
1913 
1914 static int
nandfs_symlink(struct vop_symlink_args * ap)1915 nandfs_symlink(struct vop_symlink_args *ap)
1916 {
1917 	struct vnode **vpp = ap->a_vpp;
1918 	struct vnode *dvp = ap->a_dvp;
1919 	uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
1920 	struct componentname *cnp = ap->a_cnp;
1921 	struct nandfs_node *dir_node = VTON(dvp);
1922 	struct nandfsmount *nmp = dir_node->nn_nmp;
1923 	struct nandfs_node *node;
1924 	int len, error;
1925 
1926 	if (nandfs_fs_full(dir_node->nn_nandfsdev))
1927 		return (ENOSPC);
1928 
1929 	error = nandfs_node_create(nmp, &node, S_IFLNK | mode);
1930 	if (error)
1931 		return (error);
1932 	node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
1933 	node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
1934 
1935 	*vpp = NTOV(node);
1936 
1937 	if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
1938 	    cnp->cn_namelen, IFTODT(mode))) {
1939 		vput(*vpp);
1940 		return (ENOTDIR);
1941 	}
1942 
1943 
1944 	len = strlen(ap->a_target);
1945 	error = vn_rdwr(UIO_WRITE, *vpp, ap->a_target, len, (off_t)0,
1946 	    UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
1947 	    cnp->cn_cred, NOCRED, NULL, NULL);
1948 	if (error)
1949 		vput(*vpp);
1950 
1951 	return (error);
1952 }
1953 
1954 static int
nandfs_readlink(struct vop_readlink_args * ap)1955 nandfs_readlink(struct vop_readlink_args *ap)
1956 {
1957 	struct vnode *vp = ap->a_vp;
1958 
1959 	return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1960 }
1961 
1962 static int
nandfs_rmdir(struct vop_rmdir_args * ap)1963 nandfs_rmdir(struct vop_rmdir_args *ap)
1964 {
1965 	struct vnode *vp = ap->a_vp;
1966 	struct vnode *dvp = ap->a_dvp;
1967 	struct componentname *cnp = ap->a_cnp;
1968 	struct nandfs_node *node, *dnode;
1969 	uint32_t dflag, flag;
1970 	int error = 0;
1971 
1972 	node = VTON(vp);
1973 	dnode = VTON(dvp);
1974 
1975 	/* Files marked as immutable or append-only cannot be deleted. */
1976 	if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
1977 	    (dnode->nn_inode.i_flags & APPEND))
1978 		return (EPERM);
1979 
1980 	DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx\n", __func__,
1981 	    dvp, vp, node, (uintmax_t)node->nn_ino));
1982 
1983 	if (node->nn_inode.i_links_count < 2)
1984 		return (EINVAL);
1985 
1986 	if (!nandfs_dirempty(vp, dnode->nn_ino, cnp->cn_cred))
1987 		return (ENOTEMPTY);
1988 
1989 	/* Files marked as immutable or append-only cannot be deleted. */
1990 	dflag = dnode->nn_inode.i_flags;
1991 	flag = node->nn_inode.i_flags;
1992 	if ((dflag & APPEND) ||
1993 	    (flag & (NOUNLINK | IMMUTABLE | APPEND))) {
1994 		return (EPERM);
1995 	}
1996 
1997 	if (vp->v_mountedhere != 0)
1998 		return (EINVAL);
1999 
2000 	nandfs_remove_dirent(dvp, node, cnp);
2001 	dnode->nn_inode.i_links_count -= 1;
2002 	dnode->nn_flags |= IN_CHANGE;
2003 
2004 	cache_purge(dvp);
2005 
2006 	error = nandfs_truncate(vp, (uint64_t)0);
2007 	if (error)
2008 		return (error);
2009 
2010 	node->nn_inode.i_links_count -= 2;
2011 	node->nn_flags |= IN_CHANGE;
2012 
2013 	cache_purge(vp);
2014 
2015 	return (error);
2016 }
2017 
2018 static int
nandfs_fsync(struct vop_fsync_args * ap)2019 nandfs_fsync(struct vop_fsync_args *ap)
2020 {
2021 	struct vnode *vp = ap->a_vp;
2022 	struct nandfs_node *node = VTON(vp);
2023 	int locked;
2024 
2025 	DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp,
2026 	    node, (uintmax_t)node->nn_ino));
2027 
2028 	/*
2029 	 * Start syncing vnode only if inode was modified or
2030 	 * there are some dirty buffers
2031 	 */
2032 	if (VTON(vp)->nn_flags & IN_MODIFIED ||
2033 	    vp->v_bufobj.bo_dirty.bv_cnt) {
2034 		locked = VOP_ISLOCKED(vp);
2035 		VOP_UNLOCK(vp, 0);
2036 		nandfs_wakeup_wait_sync(node->nn_nandfsdev, SYNCER_FSYNC);
2037 		VOP_LOCK(vp, locked | LK_RETRY);
2038 	}
2039 
2040 	return (0);
2041 }
2042 
2043 static int
nandfs_bmap(struct vop_bmap_args * ap)2044 nandfs_bmap(struct vop_bmap_args *ap)
2045 {
2046 	struct vnode *vp = ap->a_vp;
2047 	struct nandfs_node *nnode = VTON(vp);
2048 	struct nandfs_device *nandfsdev = nnode->nn_nandfsdev;
2049 	nandfs_daddr_t l2vmap, v2pmap;
2050 	int error;
2051 	int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
2052 
2053 	DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp,
2054 	    nnode, (uintmax_t)nnode->nn_ino));
2055 
2056 	if (ap->a_bop != NULL)
2057 		*ap->a_bop = &nandfsdev->nd_devvp->v_bufobj;
2058 	if (ap->a_bnp == NULL)
2059 		return (0);
2060 	if (ap->a_runp != NULL)
2061 		*ap->a_runp = 0;
2062 	if (ap->a_runb != NULL)
2063 		*ap->a_runb = 0;
2064 
2065 	/*
2066 	 * Translate all the block sectors into a series of buffers to read
2067 	 * asynchronously from the nandfs device. Note that this lookup may
2068 	 * induce readin's too.
2069 	 */
2070 
2071 	/* Get virtual block numbers for the vnode's buffer span */
2072 	error = nandfs_bmap_lookup(nnode, ap->a_bn, &l2vmap);
2073 	if (error)
2074 		return (-1);
2075 
2076 	/* Translate virtual block numbers to physical block numbers */
2077 	error = nandfs_vtop(nnode, l2vmap, &v2pmap);
2078 	if (error)
2079 		return (-1);
2080 
2081 	/* Note virtual block 0 marks not mapped */
2082 	if (l2vmap == 0)
2083 		*ap->a_bnp = -1;
2084 	else
2085 		*ap->a_bnp = v2pmap * blk2dev;	/* in DEV_BSIZE */
2086 
2087 	DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx lblk %jx -> blk %jx\n",
2088 	    __func__, vp, nnode, (uintmax_t)nnode->nn_ino, (uintmax_t)ap->a_bn,
2089 	    (uintmax_t)*ap->a_bnp ));
2090 
2091 	return (0);
2092 }
2093 
2094 static void
nandfs_force_syncer(struct nandfsmount * nmp)2095 nandfs_force_syncer(struct nandfsmount *nmp)
2096 {
2097 
2098 	nmp->nm_flags |= NANDFS_FORCE_SYNCER;
2099 	nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_FFORCE);
2100 }
2101 
2102 static int
nandfs_ioctl(struct vop_ioctl_args * ap)2103 nandfs_ioctl(struct vop_ioctl_args *ap)
2104 {
2105 	struct vnode *vp = ap->a_vp;
2106 	u_long command = ap->a_command;
2107 	caddr_t data = ap->a_data;
2108 	struct nandfs_node *node = VTON(vp);
2109 	struct nandfs_device *nandfsdev = node->nn_nandfsdev;
2110 	struct nandfsmount *nmp = node->nn_nmp;
2111 	uint64_t *tab, *cno;
2112 	struct nandfs_seg_stat *nss;
2113 	struct nandfs_cpmode *ncpm;
2114 	struct nandfs_argv *nargv;
2115 	struct nandfs_cpstat *ncp;
2116 	int error;
2117 
2118 	DPRINTF(VNCALL, ("%s: %x\n", __func__, (uint32_t)command));
2119 
2120 	error = priv_check(ap->a_td, PRIV_VFS_MOUNT);
2121 	if (error)
2122 		return (error);
2123 
2124 	if (nmp->nm_ronly) {
2125 		switch (command) {
2126 		case NANDFS_IOCTL_GET_FSINFO:
2127 		case NANDFS_IOCTL_GET_SUSTAT:
2128 		case NANDFS_IOCTL_GET_CPINFO:
2129 		case NANDFS_IOCTL_GET_CPSTAT:
2130 		case NANDFS_IOCTL_GET_SUINFO:
2131 		case NANDFS_IOCTL_GET_VINFO:
2132 		case NANDFS_IOCTL_GET_BDESCS:
2133 			break;
2134 		default:
2135 			return (EROFS);
2136 		}
2137 	}
2138 
2139 	switch (command) {
2140 	case NANDFS_IOCTL_GET_FSINFO:
2141 		error = nandfs_get_fsinfo(nmp, (struct nandfs_fsinfo *)data);
2142 		break;
2143 	case NANDFS_IOCTL_GET_SUSTAT:
2144 		nss = (struct nandfs_seg_stat *)data;
2145 		error = nandfs_get_seg_stat(nandfsdev, nss);
2146 		break;
2147 	case NANDFS_IOCTL_CHANGE_CPMODE:
2148 		ncpm = (struct nandfs_cpmode *)data;
2149 		error = nandfs_chng_cpmode(nandfsdev->nd_cp_node, ncpm);
2150 		nandfs_force_syncer(nmp);
2151 		break;
2152 	case NANDFS_IOCTL_GET_CPINFO:
2153 		nargv = (struct nandfs_argv *)data;
2154 		error = nandfs_get_cpinfo_ioctl(nandfsdev->nd_cp_node, nargv);
2155 		break;
2156 	case NANDFS_IOCTL_DELETE_CP:
2157 		tab = (uint64_t *)data;
2158 		error = nandfs_delete_cp(nandfsdev->nd_cp_node, tab[0], tab[1]);
2159 		nandfs_force_syncer(nmp);
2160 		break;
2161 	case NANDFS_IOCTL_GET_CPSTAT:
2162 		ncp = (struct nandfs_cpstat *)data;
2163 		error = nandfs_get_cpstat(nandfsdev->nd_cp_node, ncp);
2164 		break;
2165 	case NANDFS_IOCTL_GET_SUINFO:
2166 		nargv = (struct nandfs_argv *)data;
2167 		error = nandfs_get_segment_info_ioctl(nandfsdev, nargv);
2168 		break;
2169 	case NANDFS_IOCTL_GET_VINFO:
2170 		nargv = (struct nandfs_argv *)data;
2171 		error = nandfs_get_dat_vinfo_ioctl(nandfsdev, nargv);
2172 		break;
2173 	case NANDFS_IOCTL_GET_BDESCS:
2174 		nargv = (struct nandfs_argv *)data;
2175 		error = nandfs_get_dat_bdescs_ioctl(nandfsdev, nargv);
2176 		break;
2177 	case NANDFS_IOCTL_SYNC:
2178 		cno = (uint64_t *)data;
2179 		nandfs_force_syncer(nmp);
2180 		*cno = nandfsdev->nd_last_cno;
2181 		error = 0;
2182 		break;
2183 	case NANDFS_IOCTL_MAKE_SNAP:
2184 		cno = (uint64_t *)data;
2185 		error = nandfs_make_snap(nandfsdev, cno);
2186 		nandfs_force_syncer(nmp);
2187 		break;
2188 	case NANDFS_IOCTL_DELETE_SNAP:
2189 		cno = (uint64_t *)data;
2190 		error = nandfs_delete_snap(nandfsdev, *cno);
2191 		nandfs_force_syncer(nmp);
2192 		break;
2193 	default:
2194 		error = ENOTTY;
2195 		break;
2196 	}
2197 
2198 	return (error);
2199 }
2200 
2201 /*
2202  * Whiteout vnode call
2203  */
2204 static int
nandfs_whiteout(struct vop_whiteout_args * ap)2205 nandfs_whiteout(struct vop_whiteout_args *ap)
2206 {
2207 	struct vnode *dvp = ap->a_dvp;
2208 	struct componentname *cnp = ap->a_cnp;
2209 	int error = 0;
2210 
2211 	switch (ap->a_flags) {
2212 	case LOOKUP:
2213 		return (0);
2214 	case CREATE:
2215 		/* Create a new directory whiteout */
2216 #ifdef INVARIANTS
2217 		if ((cnp->cn_flags & SAVENAME) == 0)
2218 			panic("nandfs_whiteout: missing name");
2219 #endif
2220 		error = nandfs_add_dirent(dvp, NANDFS_WHT_INO, cnp->cn_nameptr,
2221 		    cnp->cn_namelen, DT_WHT);
2222 		break;
2223 
2224 	case DELETE:
2225 		/* Remove an existing directory whiteout */
2226 		cnp->cn_flags &= ~DOWHITEOUT;
2227 		error = nandfs_remove_dirent(dvp, NULL, cnp);
2228 		break;
2229 	default:
2230 		panic("nandf_whiteout: unknown op: %d", ap->a_flags);
2231 	}
2232 
2233 	return (error);
2234 }
2235 
2236 static int
nandfs_pathconf(struct vop_pathconf_args * ap)2237 nandfs_pathconf(struct vop_pathconf_args *ap)
2238 {
2239 	int error;
2240 
2241 	error = 0;
2242 	switch (ap->a_name) {
2243 	case _PC_LINK_MAX:
2244 		*ap->a_retval = NANDFS_LINK_MAX;
2245 		break;
2246 	case _PC_NAME_MAX:
2247 		*ap->a_retval = NANDFS_NAME_LEN;
2248 		break;
2249 	case _PC_PIPE_BUF:
2250 		if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO)
2251 			*ap->a_retval = PIPE_BUF;
2252 		else
2253 			error = EINVAL;
2254 		break;
2255 	case _PC_CHOWN_RESTRICTED:
2256 		*ap->a_retval = 1;
2257 		break;
2258 	case _PC_NO_TRUNC:
2259 		*ap->a_retval = 1;
2260 		break;
2261 	case _PC_ALLOC_SIZE_MIN:
2262 		*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
2263 		break;
2264 	case _PC_FILESIZEBITS:
2265 		*ap->a_retval = 64;
2266 		break;
2267 	case _PC_REC_INCR_XFER_SIZE:
2268 		*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
2269 		break;
2270 	case _PC_REC_MAX_XFER_SIZE:
2271 		*ap->a_retval = -1; /* means ``unlimited'' */
2272 		break;
2273 	case _PC_REC_MIN_XFER_SIZE:
2274 		*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
2275 		break;
2276 	default:
2277 		error = vop_stdpathconf(ap);
2278 		break;
2279 	}
2280 	return (error);
2281 }
2282 
2283 static int
nandfs_vnlock1(struct vop_lock1_args * ap)2284 nandfs_vnlock1(struct vop_lock1_args *ap)
2285 {
2286 	struct vnode *vp = ap->a_vp;
2287 	struct nandfs_node *node = VTON(vp);
2288 	int error, vi_locked;
2289 
2290 	/*
2291 	 * XXX can vnode go away while we are sleeping?
2292 	 */
2293 	vi_locked = mtx_owned(&vp->v_interlock);
2294 	if (vi_locked)
2295 		VI_UNLOCK(vp);
2296 	error = NANDFS_WRITELOCKFLAGS(node->nn_nandfsdev,
2297 	    ap->a_flags & LK_NOWAIT);
2298 	if (vi_locked && !error)
2299 		VI_LOCK(vp);
2300 	if (error)
2301 		return (error);
2302 
2303 	error = vop_stdlock(ap);
2304 	if (error) {
2305 		NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
2306 		return (error);
2307 	}
2308 
2309 	return (0);
2310 }
2311 
2312 static int
nandfs_vnunlock(struct vop_unlock_args * ap)2313 nandfs_vnunlock(struct vop_unlock_args *ap)
2314 {
2315 	struct vnode *vp = ap->a_vp;
2316 	struct nandfs_node *node = VTON(vp);
2317 	int error;
2318 
2319 	error = vop_stdunlock(ap);
2320 	if (error)
2321 		return (error);
2322 
2323 	NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
2324 
2325 	return (0);
2326 }
2327 
2328 /*
2329  * Global vfs data structures
2330  */
2331 struct vop_vector nandfs_vnodeops = {
2332 	.vop_default =		&default_vnodeops,
2333 	.vop_access =		nandfs_access,
2334 	.vop_advlock =		nandfs_advlock,
2335 	.vop_bmap =		nandfs_bmap,
2336 	.vop_close =		nandfs_close,
2337 	.vop_create =		nandfs_create,
2338 	.vop_fsync =		nandfs_fsync,
2339 	.vop_getattr =		nandfs_getattr,
2340 	.vop_inactive =		nandfs_inactive,
2341 	.vop_cachedlookup =	nandfs_lookup,
2342 	.vop_ioctl =		nandfs_ioctl,
2343 	.vop_link =		nandfs_link,
2344 	.vop_lookup =		vfs_cache_lookup,
2345 	.vop_mkdir =		nandfs_mkdir,
2346 	.vop_mknod =		nandfs_mknod,
2347 	.vop_open =		nandfs_open,
2348 	.vop_pathconf =		nandfs_pathconf,
2349 	.vop_print =		nandfs_print,
2350 	.vop_read =		nandfs_read,
2351 	.vop_readdir =		nandfs_readdir,
2352 	.vop_readlink =		nandfs_readlink,
2353 	.vop_reclaim =		nandfs_reclaim,
2354 	.vop_remove =		nandfs_remove,
2355 	.vop_rename =		nandfs_rename,
2356 	.vop_rmdir =		nandfs_rmdir,
2357 	.vop_whiteout =		nandfs_whiteout,
2358 	.vop_write =		nandfs_write,
2359 	.vop_setattr =		nandfs_setattr,
2360 	.vop_strategy =		nandfs_strategy,
2361 	.vop_symlink =		nandfs_symlink,
2362 	.vop_lock1 =		nandfs_vnlock1,
2363 	.vop_unlock =		nandfs_vnunlock,
2364 };
2365 
2366 struct vop_vector nandfs_system_vnodeops = {
2367 	.vop_default =		&default_vnodeops,
2368 	.vop_close =		nandfs_close,
2369 	.vop_inactive =		nandfs_inactive,
2370 	.vop_reclaim =		nandfs_reclaim,
2371 	.vop_strategy =		nandfs_strategy,
2372 	.vop_fsync =		nandfs_fsync,
2373 	.vop_bmap =		nandfs_bmap,
2374 	.vop_access =		VOP_PANIC,
2375 	.vop_advlock =		VOP_PANIC,
2376 	.vop_create =		VOP_PANIC,
2377 	.vop_getattr =		VOP_PANIC,
2378 	.vop_cachedlookup =	VOP_PANIC,
2379 	.vop_ioctl =		VOP_PANIC,
2380 	.vop_link =		VOP_PANIC,
2381 	.vop_lookup =		VOP_PANIC,
2382 	.vop_mkdir =		VOP_PANIC,
2383 	.vop_mknod =		VOP_PANIC,
2384 	.vop_open =		VOP_PANIC,
2385 	.vop_pathconf =		VOP_PANIC,
2386 	.vop_print =		VOP_PANIC,
2387 	.vop_read =		VOP_PANIC,
2388 	.vop_readdir =		VOP_PANIC,
2389 	.vop_readlink =		VOP_PANIC,
2390 	.vop_remove =		VOP_PANIC,
2391 	.vop_rename =		VOP_PANIC,
2392 	.vop_rmdir =		VOP_PANIC,
2393 	.vop_whiteout =		VOP_PANIC,
2394 	.vop_write =		VOP_PANIC,
2395 	.vop_setattr =		VOP_PANIC,
2396 	.vop_symlink =		VOP_PANIC,
2397 };
2398 
2399 static int
nandfsfifo_close(struct vop_close_args * ap)2400 nandfsfifo_close(struct vop_close_args *ap)
2401 {
2402 	struct vnode *vp = ap->a_vp;
2403 	struct nandfs_node *node = VTON(vp);
2404 
2405 	DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node));
2406 
2407 	mtx_lock(&vp->v_interlock);
2408 	if (vp->v_usecount > 1)
2409 		nandfs_itimes_locked(vp);
2410 	mtx_unlock(&vp->v_interlock);
2411 
2412 	return (fifo_specops.vop_close(ap));
2413 }
2414 
2415 struct vop_vector nandfs_fifoops = {
2416 	.vop_default =		&fifo_specops,
2417 	.vop_fsync =		VOP_PANIC,
2418 	.vop_access =		nandfs_access,
2419 	.vop_close =		nandfsfifo_close,
2420 	.vop_getattr =		nandfs_getattr,
2421 	.vop_inactive =		nandfs_inactive,
2422 	.vop_pathconf =		nandfs_pathconf,
2423 	.vop_print =		nandfs_print,
2424 	.vop_read =		VOP_PANIC,
2425 	.vop_reclaim =		nandfs_reclaim,
2426 	.vop_setattr =		nandfs_setattr,
2427 	.vop_write =		VOP_PANIC,
2428 	.vop_lock1 =		nandfs_vnlock1,
2429 	.vop_unlock =		nandfs_vnunlock,
2430 };
2431 
2432 int
nandfs_vinit(struct vnode * vp,uint64_t ino)2433 nandfs_vinit(struct vnode *vp, uint64_t ino)
2434 {
2435 	struct nandfs_node *node;
2436 
2437 	ASSERT_VOP_LOCKED(vp, __func__);
2438 
2439 	node = VTON(vp);
2440 
2441 	/* Check if we're fetching the root */
2442 	if (ino == NANDFS_ROOT_INO)
2443 		vp->v_vflag |= VV_ROOT;
2444 
2445 	if (ino != NANDFS_GC_INO)
2446 		vp->v_type = IFTOVT(node->nn_inode.i_mode);
2447 	else
2448 		vp->v_type = VREG;
2449 
2450 	if (vp->v_type == VFIFO)
2451 		vp->v_op = &nandfs_fifoops;
2452 
2453 	return (0);
2454 }
2455