1 /*
2  * Copyright (c) 2001, Alexander Kabaev
3  * Copyright (c) 2006, Russell Cattelan Digital Elves Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: stable/9/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c 207662 2010-05-05 16:44:25Z trasz $
28  */
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/namei.h>
32 #include <sys/kernel.h>
33 #include <sys/fcntl.h>
34 #include <sys/mount.h>
35 #include <sys/unistd.h>
36 #include <sys/vnode.h>
37 #include <sys/dirent.h>
38 #include <sys/ioccom.h>
39 #include <sys/malloc.h>
40 #include <sys/extattr.h>
41 
42 #include <vm/vm.h>
43 #include <vm/vm_extern.h>
44 #include <vm/vm_object.h>
45 #include <vm/vm_page.h>
46 #include <vm/vm_pager.h>
47 #include <vm/vnode_pager.h>
48 
49 #include <fs/fifofs/fifo.h>
50 
51 #define NO_VFS_MACROS
52 #include "xfs.h"
53 #include "xfs_types.h"
54 #include "xfs_bit.h"
55 #include "xfs_inum.h"
56 #include "xfs_log.h"
57 #include "xfs_trans.h"
58 #include "xfs_trans_priv.h"
59 #include "xfs_sb.h"
60 #include "xfs_ag.h"
61 #include "xfs_dir.h"
62 #include "xfs_dir2.h"
63 #include "xfs_dmapi.h"
64 #include "xfs_mount.h"
65 #include "xfs_alloc_btree.h"
66 #include "xfs_bmap_btree.h"
67 #include "xfs_ialloc_btree.h"
68 #include "xfs_btree.h"
69 #include "xfs_imap.h"
70 #include "xfs_attr.h"
71 #include "xfs_attr_sf.h"
72 #include "xfs_dir_sf.h"
73 #include "xfs_dir2_sf.h"
74 #include "xfs_dinode.h"
75 #include "xfs_ialloc.h"
76 #include "xfs_alloc.h"
77 #include "xfs_inode.h"
78 #include "xfs_inode_item.h"
79 #include "xfs_acl.h"
80 #include "xfs_cap.h"
81 #include "xfs_mac.h"
82 #include "xfs_iomap.h"
83 #include "xfs_clnt.h"
84 #include "xfs_mountops.h"
85 
86 /*
87  * Prototypes for XFS vnode operations.
88  */
89 static vop_access_t		_xfs_access;
90 static vop_advlock_t		_xfs_advlock;
91 static vop_bmap_t		_xfs_bmap;
92 static vop_cachedlookup_t	_xfs_cachedlookup;
93 static vop_close_t		_xfs_close;
94 static vop_create_t		_xfs_create;
95 static vop_deleteextattr_t	_xfs_deleteextattr;
96 static vop_fsync_t		_xfs_fsync;
97 static vop_getattr_t		_xfs_getattr;
98 static vop_getextattr_t		_xfs_getextattr;
99 static vop_inactive_t		_xfs_inactive;
100 static vop_ioctl_t		_xfs_ioctl;
101 static vop_link_t		_xfs_link;
102 static vop_listextattr_t	_xfs_listextattr;
103 static vop_mkdir_t		_xfs_mkdir;
104 static vop_mknod_t		_xfs_mknod;
105 static vop_open_t		_xfs_open;
106 static vop_read_t		_xfs_read;
107 static vop_readdir_t		_xfs_readdir;
108 static vop_readlink_t		_xfs_readlink;
109 static vop_reclaim_t		_xfs_reclaim;
110 static vop_remove_t		_xfs_remove;
111 static vop_rename_t		_xfs_rename;
112 static vop_rmdir_t		_xfs_rmdir;
113 static vop_setattr_t		_xfs_setattr;
114 static vop_setextattr_t		_xfs_setextattr;
115 static vop_strategy_t		_xfs_strategy;
116 static vop_symlink_t		_xfs_symlink;
117 static vop_write_t		_xfs_write;
118 static vop_vptofh_t		_xfs_vptofh;
119 
120 struct vop_vector xfs_vnops = {
121 	.vop_default =		&default_vnodeops,
122 	.vop_access =		_xfs_access,
123 	.vop_advlock =		_xfs_advlock,
124 	.vop_bmap =		_xfs_bmap,
125 	.vop_cachedlookup =	_xfs_cachedlookup,
126 	.vop_close =		_xfs_close,
127 	.vop_create =		_xfs_create,
128 	.vop_deleteextattr =	_xfs_deleteextattr,
129 	.vop_fsync =		_xfs_fsync,
130 	.vop_getattr =		_xfs_getattr,
131 	.vop_getextattr =	_xfs_getextattr,
132 	.vop_inactive =		_xfs_inactive,
133 	.vop_ioctl =		_xfs_ioctl,
134 	.vop_link =		_xfs_link,
135 	.vop_listextattr =	_xfs_listextattr,
136 	.vop_lookup =		vfs_cache_lookup,
137 	.vop_mkdir =		_xfs_mkdir,
138 	.vop_mknod =		_xfs_mknod,
139 	.vop_open =		_xfs_open,
140 	.vop_read =		_xfs_read,
141 	.vop_readdir =		_xfs_readdir,
142 	.vop_readlink =		_xfs_readlink,
143 	.vop_reclaim =		_xfs_reclaim,
144 	.vop_remove =		_xfs_remove,
145 	.vop_rename =		_xfs_rename,
146 	.vop_rmdir =		_xfs_rmdir,
147 	.vop_setattr =		_xfs_setattr,
148 	.vop_setextattr =	_xfs_setextattr,
149 	.vop_strategy =		_xfs_strategy,
150 	.vop_symlink =		_xfs_symlink,
151 	.vop_write =		_xfs_write,
152 	.vop_vptofh =		_xfs_vptofh,
153 };
154 
155 /*
156  *  FIFO's specific operations.
157  */
158 
159 static vop_close_t	_xfsfifo_close;
160 static vop_read_t	_xfsfifo_read;
161 static vop_kqfilter_t	_xfsfifo_kqfilter;
162 static vop_write_t	_xfsfifo_write;
163 
164 struct vop_vector xfs_fifoops = {
165 	.vop_default =		&fifo_specops,
166 	.vop_access =		_xfs_access,
167 	.vop_close =		_xfsfifo_close,
168 	.vop_fsync =		_xfs_fsync,
169 	.vop_getattr =		_xfs_getattr,
170 	.vop_inactive =		_xfs_inactive,
171 	.vop_kqfilter =		_xfsfifo_kqfilter,
172 	.vop_read =		_xfsfifo_read,
173 	.vop_reclaim =		_xfs_reclaim,
174 	.vop_setattr =		_xfs_setattr,
175 	.vop_write =		_xfsfifo_write,
176 	.vop_vptofh =		_xfs_vptofh,
177 };
178 
179 static int
_xfs_access(struct vop_access_args * ap)180 _xfs_access(
181     	struct vop_access_args /* {
182 		struct vnode *a_vp;
183 		accmode_t a_accmode;
184 		struct ucred *a_cred;
185 		struct thread *a_td;
186 	} */ *ap)
187 {
188 	int error;
189 
190 	XVOP_ACCESS(VPTOXFSVP(ap->a_vp), ap->a_accmode, ap->a_cred, error);
191 	return (error);
192 }
193 
194 static int
_xfs_open(struct vop_open_args * ap)195 _xfs_open(
196     	struct vop_open_args /* {
197 		struct vnode *a_vp;
198 		int  a_mode;
199 		struct ucred *a_cred;
200 		struct thread *a_td;
201 		struct file *a_fp;
202 	} */ *ap)
203 {
204 	int error;
205 
206 	XVOP_OPEN(VPTOXFSVP(ap->a_vp), ap->a_cred, error);
207 	if (error == 0)
208 		vnode_create_vobject(ap->a_vp, 0, ap->a_td);
209 	return (error);
210 }
211 
212 static int
_xfs_close(struct vop_close_args * ap)213 _xfs_close(
214 	struct vop_close_args /* {
215 		struct vnodeop_desc *a_desc;
216 		struct vnode *a_vp;
217 		int  a_fflag;
218 		struct ucred *a_cred;
219 		struct thread *a_td;
220 	} */ *ap)
221 {
222 	int error = 0;
223 	/* XVOP_CLOSE(VPTOXFSVP(ap->a_vp), NULL, error); */
224 	return (error);
225 }
226 
227 static int
_xfs_getattr(struct vop_getattr_args * ap)228 _xfs_getattr(
229 	struct vop_getattr_args /* {
230 		struct vnode *a_vp;
231 		struct vattr *a_vap;
232 		struct ucred *a_cred;
233 	} */ *ap)
234 {
235 	struct vnode	*vp = ap->a_vp;
236 	struct vattr	*vap = ap->a_vap;
237 	struct mount	*mp;
238 	xfs_vattr_t	va;
239 	int		error;
240 	/* extract the xfs vnode from the private data */
241 	//xfs_vnode_t	*xvp = (xfs_vnode_t *)vp->v_data;
242 
243 	memset(&va,0,sizeof(xfs_vattr_t));
244 	va.va_mask = XFS_AT_STAT|XFS_AT_GENCOUNT|XFS_AT_XFLAGS;
245 
246 	XVOP_GETATTR(VPTOXFSVP(vp), &va, 0, ap->a_cred, error);
247 	if (error)
248 		return (error);
249 
250 	mp  = vp->v_mount;
251 
252 	vap->va_type = IFTOVT(((xfs_vnode_t *)vp->v_data)->v_inode->i_d.di_mode);
253 	vap->va_mode = va.va_mode;
254 	vap->va_nlink = va.va_nlink;
255 	vap->va_uid = va.va_uid;
256 	vap->va_gid = va.va_gid;
257 	vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
258 	vap->va_fileid = va.va_nodeid;
259 	vap->va_size = va.va_size;
260 	vap->va_blocksize = va.va_blocksize;
261 	vap->va_atime = va.va_atime;
262 	vap->va_mtime = va.va_mtime;
263 	vap->va_ctime = va.va_ctime;
264 	vap->va_gen = va.va_gen;
265 	vap->va_rdev = va.va_rdev;
266 	vap->va_bytes = (va.va_nblocks << BBSHIFT);
267 
268 	/* XFS now supports devices that have block sizes
269 	 * other than 512 so BBSHIFT will work for now
270 	 * but need to get this value from the super block
271 	 */
272 
273 	/*
274 	 * Fields with no direct equivalent in XFS
275 	 */
276 	vap->va_filerev = 0;
277 	vap->va_flags = 0;
278 
279 	return (0);
280 }
281 
282 static int
_xfs_setattr(struct vop_setattr_args * ap)283 _xfs_setattr(
284 	struct vop_setattr_args /* {
285 		struct vnode *a_vp;
286 		struct vattr *a_vap;
287 		struct ucred *a_cred;
288 	} */ *ap)
289 {
290 	struct vnode *vp = ap->a_vp;
291 	struct vattr *vap = ap->a_vap;
292 	xfs_vattr_t   va;
293 	int error;
294 
295 	/*
296 	 * Check for unsettable attributes.
297 	 */
298 #ifdef RMC
299 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
300 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
301 	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
302 	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL))
303 		return (EINVAL);
304 #endif
305 
306 	memset(&va, 0, sizeof(va));
307 
308 	if (vap->va_uid != (uid_t)VNOVAL) {
309 		va.va_mask |= XFS_AT_UID;
310 		va.va_uid = vap->va_uid;
311 	}
312 	if (vap->va_gid != (gid_t)VNOVAL) {
313 		va.va_mask |= XFS_AT_GID;
314 		va.va_gid = vap->va_gid;
315 	}
316 	if (vap->va_size != VNOVAL) {
317 		va.va_mask |= XFS_AT_SIZE;
318 		va.va_size = vap->va_size;
319 	}
320 	if (vap->va_atime.tv_sec != VNOVAL) {
321 		va.va_mask |= XFS_AT_ATIME;
322 		va.va_atime = vap->va_atime;
323 	}
324 	if (vap->va_mtime.tv_sec != VNOVAL) {
325 		va.va_mask |= XFS_AT_MTIME;
326 		va.va_mtime = vap->va_mtime;
327 	}
328 	if (vap->va_ctime.tv_sec != VNOVAL) {
329 		va.va_mask |= XFS_AT_CTIME;
330 		va.va_ctime = vap->va_ctime;
331 	}
332 	if (vap->va_mode != (mode_t)VNOVAL) {
333 		va.va_mask |= XFS_AT_MODE;
334 		va.va_mode = vap->va_mode;
335 	}
336 
337 	XVOP_SETATTR(VPTOXFSVP(vp), &va, 0, ap->a_cred, error);
338 	return (error);
339 }
340 
341 static int
_xfs_inactive(struct vop_inactive_args * ap)342 _xfs_inactive(
343 	struct vop_inactive_args  /* {
344 		struct vnode *a_vp;
345 		struct thread *a_td;
346 	} */ *ap)
347 {
348 	struct vnode *vp = ap->a_vp;
349 	struct thread *td = ap->a_td;
350 	int error;
351 
352 	XVOP_INACTIVE(VPTOXFSVP(vp), td->td_ucred, error);
353 	return (error);
354 }
355 
356 static int
_xfs_read(struct vop_read_args * ap)357 _xfs_read(
358 	struct vop_read_args /* {
359 		struct vnode *a_vp;
360 		struct uio *a_uio;
361 		int  a_ioflag;
362 		struct ucred *a_cred;
363 	} */ *ap)
364 {
365 	struct vnode *vp = ap->a_vp;
366  	struct uio *uio = ap->a_uio;
367 	int error;
368 
369 	switch (vp->v_type) {
370 	case VREG:
371 		break;
372 	case VDIR:
373 		return (EISDIR);
374 	default:
375 		return (EPERM);
376 	};
377 
378 	XVOP_READ(VPTOXFSVP(vp), uio, ap->a_ioflag, ap->a_cred, error);
379 	return error;
380 }
381 
382 int
xfs_read_file(xfs_mount_t * mp,xfs_inode_t * ip,struct uio * uio,int ioflag)383 xfs_read_file(xfs_mount_t *mp, xfs_inode_t *ip, struct uio *uio, int ioflag)
384 {
385 	xfs_fileoff_t lbn, nextlbn;
386 	xfs_fsize_t bytesinfile;
387 	long size, xfersize, blkoffset;
388 	struct buf *bp;
389 	struct vnode *vp;
390 	int error, orig_resid;
391 	int seqcount;
392 
393 	seqcount = ioflag >> IO_SEQSHIFT;
394 
395 	orig_resid = uio->uio_resid;
396 	if (orig_resid <= 0)
397 		return (0);
398 
399 	vp = XFS_ITOV(ip)->v_vnode;
400 
401 	/*
402 	 * Ok so we couldn't do it all in one vm trick...
403 	 * so cycle around trying smaller bites..
404 	 */
405 	for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
406 		if ((bytesinfile = ip->i_d.di_size - uio->uio_offset) <= 0)
407 			break;
408 
409 		lbn = XFS_B_TO_FSBT(mp, uio->uio_offset);
410 		nextlbn = lbn + 1;
411 
412 		/*
413 		 * size of buffer.  The buffer representing the
414 		 * end of the file is rounded up to the size of
415 		 * the block type ( fragment or full block,
416 		 * depending ).
417 		 */
418 		size = mp->m_sb.sb_blocksize;
419 		blkoffset = XFS_B_FSB_OFFSET(mp, uio->uio_offset);
420 
421 		/*
422 		 * The amount we want to transfer in this iteration is
423 		 * one FS block less the amount of the data before
424 		 * our startpoint (duh!)
425 		 */
426 		xfersize = mp->m_sb.sb_blocksize - blkoffset;
427 
428 		/*
429 		 * But if we actually want less than the block,
430 		 * or the file doesn't have a whole block more of data,
431 		 * then use the lesser number.
432 		 */
433 		if (uio->uio_resid < xfersize)
434 			xfersize = uio->uio_resid;
435 		if (bytesinfile < xfersize)
436 			xfersize = bytesinfile;
437 
438 		if (XFS_FSB_TO_B(mp, nextlbn) >= ip->i_d.di_size ) {
439 			/*
440 			 * Don't do readahead if this is the end of the file.
441 			 */
442 			error = bread(vp, lbn, size, NOCRED, &bp);
443 		} else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
444 			/*
445 			 * Otherwise if we are allowed to cluster,
446 			 * grab as much as we can.
447 			 *
448 			 * XXX  This may not be a win if we are not
449 			 * doing sequential access.
450 			 */
451 			error = cluster_read(vp, ip->i_d.di_size, lbn,
452 				size, NOCRED, uio->uio_resid, seqcount, &bp);
453 		} else if (seqcount > 1) {
454 			/*
455 			 * If we are NOT allowed to cluster, then
456 			 * if we appear to be acting sequentially,
457 			 * fire off a request for a readahead
458 			 * as well as a read. Note that the 4th and 5th
459 			 * arguments point to arrays of the size specified in
460 			 * the 6th argument.
461 			 */
462 			int nextsize = mp->m_sb.sb_blocksize;
463 			error = breadn(vp, lbn,
464 			    size, &nextlbn, &nextsize, 1, NOCRED, &bp);
465 		} else {
466 			/*
467 			 * Failing all of the above, just read what the
468 			 * user asked for. Interestingly, the same as
469 			 * the first option above.
470 			 */
471 			error = bread(vp, lbn, size, NOCRED, &bp);
472 		}
473 		if (error) {
474 			brelse(bp);
475 			bp = NULL;
476 			break;
477 		}
478 
479 		/*
480 		 * If IO_DIRECT then set B_DIRECT for the buffer.  This
481 		 * will cause us to attempt to release the buffer later on
482 		 * and will cause the buffer cache to attempt to free the
483 		 * underlying pages.
484 		 */
485 		if (ioflag & IO_DIRECT)
486 			bp->b_flags |= B_DIRECT;
487 
488 		/*
489 		 * We should only get non-zero b_resid when an I/O error
490 		 * has occurred, which should cause us to break above.
491 		 * However, if the short read did not cause an error,
492 		 * then we want to ensure that we do not uiomove bad
493 		 * or uninitialized data.
494 		 */
495 		size -= bp->b_resid;
496 		if (size < xfersize) {
497 			if (size == 0)
498 				break;
499 			xfersize = size;
500 		}
501 
502 		/*
503 		 * otherwise use the general form
504 		 */
505 		error = uiomove((char *)bp->b_data + blkoffset,
506 			    (int)xfersize, uio);
507 
508 		if (error)
509 			break;
510 
511 		if (ioflag & (IO_VMIO|IO_DIRECT) ) {
512 			/*
513 			 * If there are no dependencies, and it's VMIO,
514 			 * then we don't need the buf, mark it available
515 			 * for freeing. The VM has the data.
516 			 */
517 			bp->b_flags |= B_RELBUF;
518 			brelse(bp);
519 		} else {
520 			/*
521 			 * Otherwise let whoever
522 			 * made the request take care of
523 			 * freeing it. We just queue
524 			 * it onto another list.
525 			 */
526 			bqrelse(bp);
527 		}
528 	}
529 
530 	/*
531 	 * This can only happen in the case of an error
532 	 * because the loop above resets bp to NULL on each iteration
533 	 * and on normal completion has not set a new value into it.
534 	 * so it must have come from a 'break' statement
535 	 */
536 	if (bp != NULL) {
537 		if (ioflag & (IO_VMIO|IO_DIRECT)) {
538 			bp->b_flags |= B_RELBUF;
539 			brelse(bp);
540 		} else
541 			bqrelse(bp);
542 	}
543 
544 	return (error);
545 }
546 
547 static int
_xfs_write(struct vop_write_args * ap)548 _xfs_write(struct vop_write_args /* {
549 		struct vnode *a_vp;
550 		struct uio *a_uio;
551 		int  a_ioflag;
552 		struct ucred *a_cred;
553 	} */ *ap)
554 {
555 	struct vnode *vp = ap->a_vp;
556 	struct uio *uio = ap->a_uio;
557 	int ioflag = ap->a_ioflag;
558 	int error;
559 
560 	xfs_vnode_t *xvp = (xfs_vnode_t *)vp->v_data;
561 
562 	error = xfs_write(xvp->v_bh.bh_first, uio, ioflag, ap->a_cred);
563 
564 	if (error < 0) {
565 		printf("Xfs_write got error %d\n",error);
566 		return -error;
567 	}
568 	return 0;
569 }
570 
571 
572 int
xfs_write_file(xfs_inode_t * xip,struct uio * uio,int ioflag)573 xfs_write_file(xfs_inode_t *xip, struct uio *uio, int ioflag)
574 {
575 	struct buf	*bp;
576 	//struct thread	*td;
577 	daddr_t		lbn;
578 	off_t		osize = 0;
579 	off_t		offset= 0;
580 	int		blkoffset, error, resid, xfersize;
581 	int		fsblocksize;
582 	int		seqcount;
583 	xfs_iomap_t	iomap;
584 	int		maps = 1;
585 
586 	xfs_vnode_t	*xvp = XFS_ITOV(xip);
587 	struct vnode	*vp = xvp->v_vnode;
588 
589 	xfs_mount_t	*mp = (&xip->i_iocore)->io_mount;
590 
591 	seqcount = ioflag >> IO_SEQSHIFT;
592 
593 	memset(&iomap,0,sizeof(xfs_iomap_t));
594 
595 	/*
596 	 * Maybe this should be above the vnode op call, but so long as
597 	 * file servers have no limits, I don't think it matters.
598 	 */
599 #if 0
600 	td = uio->uio_td;
601 	if (vn_rlimit_fsize(vp, uio, uio->uio_td))
602 		return (EFBIG);
603 #endif
604 
605 	resid = uio->uio_resid;
606 	offset = uio->uio_offset;
607 	osize = xip->i_d.di_size;
608 
609    /* xfs bmap wants bytes for both offset and size */
610 	XVOP_BMAP(xvp,
611 		  uio->uio_offset,
612 		  uio->uio_resid,
613 		  BMAPI_WRITE|BMAPI_DIRECT,
614 		  &iomap, &maps, error);
615 	if(error) {
616 		printf("XVOP_BMAP failed\n");
617 		goto error;
618 	}
619 
620 	for (error = 0; uio->uio_resid > 0;) {
621 
622 		lbn = XFS_B_TO_FSBT(mp, offset);
623 		blkoffset = XFS_B_FSB_OFFSET(mp, offset);
624 		xfersize = mp->m_sb.sb_blocksize - blkoffset;
625 		fsblocksize = mp->m_sb.sb_blocksize;
626 
627 		if (uio->uio_resid < xfersize)
628 			xfersize = uio->uio_resid;
629 
630 		/*
631 		 * getblk sets buf by  blkno *  bo->bo_bsize
632 		 * bo_bsize is set from the mnt point fsize
633 		 * so we call getblk in the case using fsblocks
634 		 * not basic blocks
635 		 */
636 
637 		bp = getblk(vp, lbn, fsblocksize, 0, 0, 0);
638 		if(!bp) {
639 			printf("getblk failed\n");
640 			error = EINVAL;
641 			break;
642 		}
643 
644 		if (!(bp->b_flags & B_CACHE)  && fsblocksize > xfersize)
645 			vfs_bio_clrbuf(bp);
646 
647 		if (offset + xfersize >  xip->i_d.di_size) {
648 			xip->i_d.di_size = offset + xfersize;
649 			vnode_pager_setsize(vp, offset + fsblocksize);
650 		}
651 
652 		/* move the offset for the next itteration of the loop */
653 		offset += xfersize;
654 
655 		error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
656 
657 		if ((ioflag & IO_VMIO) &&
658 		   (LIST_FIRST(&bp->b_dep) == NULL)) /* in ext2fs? */
659 			bp->b_flags |= B_RELBUF;
660 
661 		/* force to full direct for now */
662 		bp->b_flags |= B_DIRECT;
663 		/* and sync ... the delay path is not pushing data out */
664 		ioflag |= IO_SYNC;
665 
666 		if (ioflag & IO_SYNC) {
667 			(void)bwrite(bp);
668 		} else if (0 /* RMC xfersize + blkoffset == fs->s_frag_size */) {
669 			if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
670 				bp->b_flags |= B_CLUSTEROK;
671 				cluster_write(vp, bp, osize, seqcount);
672 			} else {
673 				bawrite(bp);
674 			}
675 		} else {
676 			bp->b_flags |= B_CLUSTEROK;
677 			bdwrite(bp);
678 		}
679 		if (error || xfersize == 0)
680 			break;
681 	}
682 	/*
683 	 * If we successfully wrote any data, and we are not the superuser
684 	 * we clear the setuid and setgid bits as a precaution against
685 	 * tampering.
686 	 */
687 #if 0
688 	if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
689 		ip->i_mode &= ~(ISUID | ISGID);
690 #endif
691 	if (error) {
692 		if (ioflag & IO_UNIT) {
693 #if 0
694 			(void)ext2_truncate(vp, osize,
695 			    ioflag & IO_SYNC, ap->a_cred, uio->uio_td);
696 #endif
697 			uio->uio_offset -= resid - uio->uio_resid;
698 			uio->uio_resid = resid;
699 		}
700 	} else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
701 		/* Update the vnode here? */
702 	}
703 
704 error:
705 	return error;
706 }
707 
708 static int
_xfs_create(struct vop_create_args * ap)709 _xfs_create(
710     	struct vop_create_args  /* {
711 		struct vnode *a_dvp;
712 		struct vnode **a_vpp;
713 		struct componentname *a_cnp;
714 		struct vattr *a_vap;
715 	} */ *ap)
716 {
717 	struct vnode *dvp = ap->a_dvp;
718  	struct vattr *vap = ap->a_vap;
719 	struct thread *td = curthread;
720 	struct ucred *credp = td->td_ucred;
721 	struct componentname *cnp = ap->a_cnp;
722 	xfs_vnode_t *xvp;
723 	xfs_vattr_t va;
724 	int error;
725 
726 	memset(&va, 0, sizeof (va));
727 	va.va_mask |= XFS_AT_MODE;
728 	va.va_mode = vap->va_mode;
729 	va.va_mask |= XFS_AT_TYPE;
730 	va.va_mode |=  VTTOIF(vap->va_type);
731 
732 	xvp = NULL;
733 	XVOP_CREATE(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error);
734 
735 	if (error == 0) {
736 		*ap->a_vpp = xvp->v_vnode;
737 		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
738 	}
739 
740 	return (error);
741 }
742 
743 extern int xfs_remove(bhv_desc_t *, bhv_desc_t *, vname_t *, cred_t *);
744 
745 static int
_xfs_remove(struct vop_remove_args * ap)746 _xfs_remove(
747 	struct vop_remove_args /* {
748 		struct vnodeop_desc *a_desc;
749 		struct vnode * a_dvp;
750 		struct vnode * a_vp;
751 		struct componentname * a_cnp;
752 	} */ *ap)
753 {
754 	struct vnode *vp = ap->a_vp;
755 	struct thread *td = curthread;
756 	struct ucred  *credp = td->td_ucred;
757 	/*
758 	struct vnode *dvp = ap->a_dvp;
759  	struct componentname *cnp = ap->a_cnp;
760 	*/
761 	int error;
762 
763 	if (vp->v_type == VDIR || vp->v_usecount != 1)
764 		return (EPERM);
765 
766 	error = xfs_remove(VPTOXFSVP(ap->a_dvp)->v_bh.bh_first,
767 			   VPTOXFSVP(ap->a_vp)->v_bh.bh_first,
768 			   ap->a_cnp,credp);
769 
770 	cache_purge(vp);
771 	return error;
772 }
773 
774 static int
_xfs_rename(struct vop_rename_args * ap)775 _xfs_rename(
776 	struct vop_rename_args /* {
777 		struct vnode *a_fdvp;
778 		struct vnode *a_fvp;
779 		struct componentname *a_fcnp;
780 		struct vnode *a_tdvp;
781 		struct vnode *a_tvp;
782 		struct componentname *a_tcnp;
783 	} */ *ap)
784 {
785 	struct vnode *fvp = ap->a_fvp;
786 	struct vnode *tvp = ap->a_tvp;
787 	struct vnode *fdvp = ap->a_fdvp;
788 	struct vnode *tdvp = ap->a_tdvp;
789 /* 	struct componentname *tcnp = ap->a_tcnp; */
790 /*	struct componentname *fcnp = ap->a_fcnp;*/
791 	int error = EPERM;
792 
793 	if (error)
794 		goto out;
795 
796 	/* Check for cross-device rename */
797 	if ((fvp->v_mount != tdvp->v_mount) ||
798 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
799 		error = EXDEV;
800 		goto out;
801 	}
802 
803 	if (tvp && tvp->v_usecount > 1) {
804 		error = EBUSY;
805 		goto out;
806 	}
807 
808 	if (fvp->v_type == VDIR) {
809 		if (tvp != NULL && tvp->v_type == VDIR)
810 			cache_purge(tdvp);
811 		cache_purge(fdvp);
812 	}
813 out:
814 	if (tdvp == tvp)
815 		vrele(tdvp);
816 	else
817 		vput(tdvp);
818 	if (tvp)
819 		vput(tvp);
820 	vrele(fdvp);
821 	vrele(fvp);
822 	vgone(fvp);
823 	if (tvp)
824 		vgone(tvp);
825 	return (error);
826 }
827 
828 static int
_xfs_link(struct vop_link_args * ap)829 _xfs_link(
830 	struct vop_link_args /* {
831 		struct vnode *a_tdvp;
832 		struct vnode *a_vp;
833 		struct componentname *a_cnp;
834 	} */ *ap)
835 {
836 	xfs_vnode_t *tdvp, *vp;
837 	int error;
838 
839 	tdvp = VPTOXFSVP(ap->a_tdvp);
840 	vp = VPTOXFSVP(ap->a_vp);
841 	XVOP_LINK(tdvp, vp, ap->a_cnp, NULL, error);
842 	return (error);
843 }
844 
845 static int
_xfs_symlink(struct vop_symlink_args * ap)846 _xfs_symlink(
847 	struct vop_symlink_args /* {
848 		struct vnode *a_dvp;
849 		struct vnode **a_vpp;
850 		struct componentname *a_cnp;
851 		struct vattr *a_vap;
852 		char *a_target;
853 	} */ *ap)
854 {
855 	struct thread *td = curthread;
856 	struct ucred  *credp = td->td_ucred;
857 	xfs_vnode_t *xvp;
858 	xfs_vattr_t va;
859 	int error;
860 
861 	memset(&va, 0, sizeof (va));
862 
863 	va.va_mask |= XFS_AT_MODE;
864 	va.va_mode = ap->a_vap->va_mode | S_IFLNK;
865 	va.va_mask |= XFS_AT_TYPE;
866 
867 	XVOP_SYMLINK(VPTOXFSVP(ap->a_dvp), ap->a_cnp, &va, ap->a_target,
868 	    &xvp, credp, error);
869 
870 	if (error == 0) {
871 		*ap->a_vpp = xvp->v_vnode;
872 		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
873 	}
874 
875 	return (error);
876 }
877 
878 static int
_xfs_mknod(struct vop_mknod_args * ap)879 _xfs_mknod(
880 	struct vop_mknod_args /* {
881 		struct vnode *a_dvp;
882 		struct vnode **a_vpp;
883 		struct componentname *a_cnp;
884 		struct vattr *a_vap;
885 	} */ *ap)
886 {
887 	struct vnode *dvp = ap->a_dvp;
888  	struct vattr *vap = ap->a_vap;
889 	struct thread *td = curthread;
890 	struct ucred *credp = td->td_ucred;
891 	struct componentname *cnp = ap->a_cnp;
892 	xfs_vnode_t *xvp;
893 	xfs_vattr_t va;
894 	int error;
895 
896 	memset(&va, 0, sizeof (va));
897 	va.va_mask |= XFS_AT_MODE;
898 	va.va_mode = vap->va_mode | S_IFIFO;
899 	va.va_mask |= XFS_AT_TYPE;
900 	va.va_mask |= XFS_AT_RDEV;
901 	va.va_rdev = vap->va_rdev;
902 
903 	xvp = NULL;
904 	XVOP_CREATE(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error);
905 
906 	if (error == 0) {
907 		*ap->a_vpp = xvp->v_vnode;
908 		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
909 	}
910 
911 	return (error);
912 }
913 
914 static int
_xfs_mkdir(struct vop_mkdir_args * ap)915 _xfs_mkdir(
916 	struct vop_mkdir_args /* {
917 		 struct vnode *a_dvp;
918 		 struct vnode **a_vpp;
919 		 struct componentname *a_cnp;
920 		 struct vattr *a_vap;
921 	} */ *ap)
922 {
923 	struct vnode *dvp = ap->a_dvp;
924  	struct vattr *vap = ap->a_vap;
925 	struct thread *td = curthread;
926 	struct ucred *credp = td->td_ucred;
927 	struct componentname *cnp = ap->a_cnp;
928 	xfs_vnode_t *xvp;
929 	xfs_vattr_t va;
930 	int error;
931 
932 	memset(&va, 0, sizeof (va));
933 	va.va_mask |= XFS_AT_MODE;
934 	va.va_mode = vap->va_mode | S_IFDIR;
935 	va.va_mask |= XFS_AT_TYPE;
936 
937 	xvp = NULL;
938 	XVOP_MKDIR(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error);
939 
940 	if (error == 0) {
941 		*ap->a_vpp = xvp->v_vnode;
942 		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
943 	}
944 
945 	return (error);
946 }
947 
948 static int
_xfs_rmdir(struct vop_rmdir_args * ap)949 _xfs_rmdir(
950 	struct vop_rmdir_args /* {
951 		struct vnode *a_dvp;
952 		struct vnode *a_vp;
953 		struct componentname *a_cnp;
954 	} */ *ap)
955 {
956 	struct vnode *vp = ap->a_vp;
957 	struct vnode *dvp = ap->a_dvp;
958 /* 	struct componentname *cnp = ap->a_cnp; */
959 	int error;
960 
961 	if (dvp == vp)
962 		return (EINVAL);
963 
964 	error = EPERM;
965 
966 	return (error);
967 }
968 
969 static int
_xfs_readdir(struct vop_readdir_args * ap)970 _xfs_readdir(
971 	struct vop_readdir_args /* {
972 		struct vnode *a_vp;
973 		struct uio *a_uio;
974 		struct ucred *a_cred;
975 		int *a_eofflag;
976 		int *a_ncookies;
977 		u_long **a_cookies;
978 	} */ *ap)
979 {
980 	struct vnode *vp = ap->a_vp;
981 	struct uio *uio = ap->a_uio;
982 	int error;
983 	off_t	off;
984 	int	eof = 0;
985 
986 	if (vp->v_type != VDIR)
987 		return (EPERM);
988 	if (ap->a_ncookies) {
989 		return (EOPNOTSUPP);
990 	}
991 
992 	error = 0;
993 	while (!eof){
994 		off = (int)uio->uio_offset;
995 
996 		XVOP_READDIR(VPTOXFSVP(vp), uio, NULL, &eof, error);
997 		if ((uio->uio_offset == off) || error) {
998 			break;
999 		}
1000 	}
1001 
1002 	if (ap->a_eofflag)
1003 		*ap->a_eofflag = (eof != 0);
1004 
1005         return (error);
1006 }
1007 
1008 
1009 static int
_xfs_readlink(struct vop_readlink_args * ap)1010 _xfs_readlink(
1011 	struct vop_readlink_args /* {
1012 		struct vnode *a_vp;
1013 		struct uio *a_uio;
1014 		struct ucred *a_cred;
1015 	} */ *ap)
1016 {
1017 	struct vnode *vp = ap->a_vp;
1018 	struct uio *uio = ap->a_uio;
1019 	struct ucred *cred = ap->a_cred;
1020 	int error;
1021 
1022 	XVOP_READLINK(VPTOXFSVP(vp), uio, 0, cred, error);
1023 	return (error);
1024 }
1025 
1026 static int
_xfs_fsync(struct vop_fsync_args * ap)1027 _xfs_fsync(
1028 	struct vop_fsync_args /* {
1029 		struct vnode * a_vp;
1030 		int  a_waitfor;
1031 		struct thread * a_td;
1032 	} */ *ap)
1033 {
1034 	xfs_vnode_t  *vp = VPTOXFSVP(ap->a_vp);
1035 	int flags = FSYNC_DATA;
1036 	int error;
1037 
1038 	if (ap->a_waitfor == MNT_WAIT)
1039 		flags |= FSYNC_WAIT;
1040 	XVOP_FSYNC(vp, flags, ap->a_td->td_ucred, (xfs_off_t)0, (xfs_off_t)-1, error);
1041 
1042 	return (error);
1043 }
1044 
1045 static int
_xfs_bmap(struct vop_bmap_args * ap)1046 _xfs_bmap(
1047 	struct vop_bmap_args /* {
1048 		struct vnode *a_vp;
1049 		daddr_t  a_bn;
1050 		struct bufobj **a_bop;
1051 		daddr_t *a_bnp;
1052 		int *a_runp;
1053 		int *a_runb;
1054 	} */ *ap)
1055 {
1056 	xfs_iomap_t iomap;
1057 	xfs_off_t offset;
1058 	ssize_t   size;
1059 	struct mount *mp;
1060 	struct xfs_mount *xmp;
1061 	struct xfs_vnode *xvp;
1062 	int error, maxrun, retbm;
1063 
1064 	mp  = ap->a_vp->v_mount;
1065 	xmp = XFS_VFSTOM(MNTTOVFS(mp));
1066 	if (ap->a_bop != NULL)
1067 		*ap->a_bop = &xmp->m_ddev_targp->specvp->v_bufobj;
1068 	if (ap->a_bnp == NULL)
1069 		return (0);
1070 
1071 	xvp = VPTOXFSVP(ap->a_vp);
1072 	retbm = 1;
1073 
1074 	offset = XFS_FSB_TO_B(xmp, ap->a_bn);
1075 	size = XFS_FSB_TO_B(xmp, 1);
1076 	XVOP_BMAP(xvp, offset, size, BMAPI_READ, &iomap, &retbm, error);
1077 	if (error)
1078 		return (error);
1079 	if (retbm == 0 || iomap.iomap_bn == IOMAP_DADDR_NULL) {
1080 		*ap->a_bnp = (daddr_t)-1;
1081 		if (ap->a_runb)
1082 			*ap->a_runb = 0;
1083 		if (ap->a_runp)
1084 			*ap->a_runp = 0;
1085 	} else {
1086 		*ap->a_bnp = iomap.iomap_bn + btodb(iomap.iomap_delta);
1087 		maxrun = mp->mnt_iosize_max / mp->mnt_stat.f_iosize - 1;
1088 		if (ap->a_runb) {
1089 			*ap->a_runb = XFS_B_TO_FSB(xmp, iomap.iomap_delta);
1090 			if (*ap->a_runb > maxrun)
1091 				*ap->a_runb  = maxrun;
1092 		}
1093 		if (ap->a_runp) {
1094 			*ap->a_runp =
1095 			    XFS_B_TO_FSB(xmp, iomap.iomap_bsize
1096 				- iomap.iomap_delta - size);
1097 			if (*ap->a_runp > maxrun)
1098 				*ap->a_runp  = maxrun;
1099 		}
1100 	}
1101 	return (0);
1102 }
1103 
1104 static int
_xfs_strategy(struct vop_strategy_args * ap)1105 _xfs_strategy(
1106 	struct vop_strategy_args /* {
1107 		struct vnode *a_vp;
1108 		struct buf *a_bp;
1109 	} */ *ap)
1110 {
1111 	daddr_t blkno;
1112 	struct buf *bp;
1113 	struct bufobj *bo;
1114 	struct vnode *vp;
1115 	struct xfs_mount *xmp;
1116 	int error;
1117 
1118 	bp = ap->a_bp;
1119 	vp = ap->a_vp;
1120 
1121 	KASSERT(ap->a_vp == ap->a_bp->b_vp, ("%s(%p != %p)",
1122 	    __func__, ap->a_vp, ap->a_bp->b_vp));
1123 	if (bp->b_blkno == bp->b_lblkno) {
1124 		error = VOP_BMAP(vp, bp->b_lblkno, NULL, &blkno, NULL, NULL);
1125 		bp->b_blkno = blkno;
1126 		bp->b_iooffset = (blkno << BBSHIFT);
1127 		if (error) {
1128 			bp->b_error = error;
1129 			bp->b_ioflags |= BIO_ERROR;
1130 			bufdone(bp);
1131 			return (0);
1132 		}
1133 		if ((long)bp->b_blkno == -1)
1134 			vfs_bio_clrbuf(bp);
1135         }
1136 	if ((long)bp->b_blkno == -1) {
1137 		bufdone(bp);
1138 		return (0);
1139 	}
1140 
1141 	xmp = XFS_VFSTOM(MNTTOVFS(vp->v_mount));
1142 	bo = &xmp->m_ddev_targp->specvp->v_bufobj;
1143 	bo->bo_ops->bop_strategy(bo, bp);
1144 	return (0);
1145 }
1146 
1147 int
_xfs_ioctl(struct vop_ioctl_args * ap)1148 _xfs_ioctl(
1149 	struct vop_ioctl_args /* {
1150 		struct vnode *a_vp;
1151 		u_long a_command;
1152 		caddr_t a_data;
1153 		int fflag;
1154 		struct ucred *cred;
1155 		struct thread *a_td;
1156 	} */ *ap)
1157 {
1158 /* 	struct vnode *vp = ap->a_vp; */
1159 /* 	struct thread *p = ap->a_td; */
1160 /* 	struct file *fp; */
1161 	int error;
1162 
1163 	xfs_vnode_t *xvp = VPTOXFSVP(ap->a_vp);
1164 
1165 	printf("_xfs_ioctl cmd 0x%lx data %p\n",ap->a_command,ap->a_data);
1166 
1167 //	XVOP_IOCTL(xvp,(void *)NULL,(void *)NULL,ap->a_fflag,ap->a_command,ap->a_data,error);
1168 	error = xfs_ioctl(xvp->v_bh.bh_first,NULL,NULL,ap->a_fflag,ap->a_command,ap->a_data);
1169 
1170 	return error;
1171 }
1172 
1173 int
_xfs_advlock(struct vop_advlock_args * ap)1174 _xfs_advlock(
1175 	struct vop_advlock_args /* {
1176 		struct vnode *a_vp;
1177 		caddr_t  a_id;
1178 		int  a_op;
1179 		struct flock *a_fl;
1180 		int  a_flags;
1181 	} */ *ap)
1182 {
1183 /* 	struct vnode *vp = ap->a_vp;*/
1184 	struct flock *fl = ap->a_fl;
1185 /* 	caddr_t id = (caddr_t)1 */ /* ap->a_id */;
1186 /* 	int flags = ap->a_flags; */
1187 	off_t start, end, size;
1188 	int error/* , lkop */;
1189 
1190 	/*KAN: temp */
1191 	return (EOPNOTSUPP);
1192 
1193 	size = 0;
1194 	error = 0;
1195 	switch (fl->l_whence) {
1196 	    case SEEK_SET:
1197 	    case SEEK_CUR:
1198 		start = fl->l_start;
1199 		break;
1200 	    case SEEK_END:
1201 		start = fl->l_start + size;
1202 	    default:
1203 		return (EINVAL);
1204 	}
1205 	if (start < 0)
1206 		return (EINVAL);
1207 	if (fl->l_len == 0)
1208 		end = -1;
1209 	else {
1210 		end = start + fl->l_len - 1;
1211 		if (end < start)
1212 			return (EINVAL);
1213 	}
1214 #ifdef notyet
1215 	switch (ap->a_op) {
1216 	    case F_SETLK:
1217 		error = lf_advlock(ap, &vp->v_lockf, size);
1218 		break;
1219 	    case F_UNLCK:
1220 		lf_advlock(ap, &vp->v_lockf, size);
1221 		break;
1222 	    case F_GETLK:
1223 		error = lf_advlock(ap, &vp->v_lockf, size);
1224 		break;
1225 	    default:
1226 		return (EINVAL);
1227 	}
1228 #endif
1229 	return (error);
1230 }
1231 
1232 static int
_xfs_cachedlookup(struct vop_cachedlookup_args * ap)1233 _xfs_cachedlookup(
1234 	struct vop_cachedlookup_args /* {
1235 		struct vnode * a_dvp;
1236 		struct vnode ** a_vpp;
1237 		struct componentname * a_cnp;
1238 	} */ *ap)
1239 {
1240 	struct vnode *dvp, *tvp;
1241 	struct xfs_vnode *cvp;
1242 	int islastcn;
1243 	int error;
1244 	struct vnode **vpp = ap->a_vpp;
1245 	struct componentname *cnp = ap->a_cnp;
1246 	struct ucred *cred = cnp->cn_cred;
1247 	int flags = cnp->cn_flags;
1248 	int nameiop = cnp->cn_nameiop;
1249 	struct thread *td = cnp->cn_thread;
1250 
1251 	char *pname = cnp->cn_nameptr;
1252 	int namelen = cnp->cn_namelen;
1253 
1254 	*vpp = NULL;
1255 	dvp = ap->a_dvp;
1256 	islastcn = flags & ISLASTCN;
1257 
1258 	XVOP_LOOKUP(VPTOXFSVP(dvp), cnp, &cvp, 0, NULL, cred, error);
1259 
1260 	if (error == ENOENT) {
1261 		if ((nameiop == CREATE || nameiop == RENAME ||
1262 		     nameiop == DELETE) && islastcn)
1263 		{
1264 			error = VOP_ACCESS(dvp, VWRITE, cred, td);
1265 			if (error)
1266 				return (error);
1267 			cnp->cn_flags |= SAVENAME;
1268 			return (EJUSTRETURN);
1269 		}
1270 		if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
1271 			cache_enter(dvp, *vpp, cnp);
1272 		return (error);
1273 	}
1274 	if (error)
1275 		return (error);
1276 
1277 	tvp = cvp->v_vnode;
1278 
1279 	if (nameiop == DELETE && islastcn) {
1280 		if ((error = vn_lock(tvp, LK_EXCLUSIVE))) {
1281 			vrele(tvp);
1282 			goto err_out;
1283 		}
1284 		*vpp = tvp;
1285 
1286 		/* Directory should be writable for deletes. */
1287 	        error = VOP_ACCESS(dvp, VWRITE, cred, td);
1288          	if (error)
1289 		 	goto err_out;
1290 
1291 		/* XXXKAN: Permission checks for sticky dirs? */
1292 		return (0);
1293 	 }
1294 
1295 	if (nameiop == RENAME && islastcn) {
1296 		if ((error = vn_lock(tvp, LK_EXCLUSIVE))) {
1297 			vrele(tvp);
1298 			goto err_out;
1299 		}
1300 		*vpp = tvp;
1301 
1302 		if ((error = VOP_ACCESS(dvp, VWRITE, cred, td)))
1303 			goto err_out;
1304 		return (0);
1305 	}
1306 
1307 	if (flags & ISDOTDOT) {
1308 		VOP_UNLOCK(dvp, 0);
1309 		error = vn_lock(tvp, cnp->cn_lkflags);
1310 		if (error) {
1311 			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
1312 			vrele(tvp);
1313 			goto err_out;
1314 		}
1315 		*vpp = tvp;
1316 	} else if (namelen == 1 && pname[0] == '.') {
1317 		*vpp = tvp;
1318 		KASSERT(tvp == dvp, ("not same directory"));
1319 	} else {
1320 		if ((error = vn_lock(tvp, cnp->cn_lkflags))) {
1321 			vrele(tvp);
1322 			goto err_out;
1323 		}
1324 		*vpp = tvp;
1325 	}
1326 
1327 	if (cnp->cn_flags & MAKEENTRY)
1328 		cache_enter(dvp, *vpp, cnp);
1329 	return (0);
1330 
1331 err_out:
1332 	if (*vpp != 0)
1333 		vput(*vpp);
1334 	return (error);
1335 }
1336 
1337 static int
_xfs_reclaim(struct vop_reclaim_args * ap)1338 _xfs_reclaim(
1339 	struct vop_reclaim_args /* {
1340 		struct vnode *a_vp;
1341 		struct thread  *a_td;
1342 	} */ *ap)
1343 {
1344 
1345 	struct vnode *vp = ap->a_vp;
1346 	struct xfs_vnode *xfs_vp = VPTOXFSVP(vp);
1347 	int error;
1348 
1349 	XVOP_RECLAIM(xfs_vp, error);
1350 	kmem_free(xfs_vp, sizeof(*xfs_vp));
1351 	vp->v_data = NULL;
1352 	return (error);
1353 }
1354 
1355 static int
_xfs_kqfilter(struct vop_kqfilter_args * ap)1356 _xfs_kqfilter(
1357 	struct vop_kqfilter_args /* {
1358 		struct vnodeop_desc *a_desc;
1359 		struct vnode *a_vp;
1360 		struct knote *a_kn;
1361 	} */ *ap)
1362 {
1363 	return (0);
1364 }
1365 
1366 struct xfs_inode *
xfs_vtoi(struct xfs_vnode * xvp)1367 xfs_vtoi(struct xfs_vnode *xvp)
1368 {
1369 	return(XFS_BHVTOI(xvp->v_fbhv));
1370 }
1371 
1372 /*
1373  * Read wrapper for fifos.
1374  */
1375 static int
_xfsfifo_read(struct vop_read_args * ap)1376 _xfsfifo_read(
1377 	struct vop_read_args /* {
1378 		struct vnode *a_vp;
1379 		struct uio *a_uio;
1380 		int  a_ioflag;
1381 		struct ucred *a_cred;
1382 	} */ *ap)
1383 {
1384 	int error, resid;
1385 	struct xfs_inode *ip;
1386 	struct uio *uio;
1387 
1388 	uio = ap->a_uio;
1389 	resid = uio->uio_resid;
1390 	error = fifo_specops.vop_read(ap);
1391 	ip = xfs_vtoi(VPTOXFSVP(ap->a_vp));
1392 	if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL &&
1393 	    (uio->uio_resid != resid || (error == 0 && resid != 0)))
1394 		xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
1395 	return (error);
1396 }
1397 
1398 /*
1399  * Write wrapper for fifos.
1400  */
1401 static int
_xfsfifo_write(struct vop_write_args * ap)1402 _xfsfifo_write(
1403 	struct vop_write_args /* {
1404 		struct vnode *a_vp;
1405 		struct uio *a_uio;
1406 		int  a_ioflag;
1407 		struct ucred *a_cred;
1408 	} */ *ap)
1409 {
1410 	int error, resid;
1411 	struct uio *uio;
1412 	struct xfs_inode *ip;
1413 
1414 	uio = ap->a_uio;
1415 	resid = uio->uio_resid;
1416 	error = fifo_specops.vop_write(ap);
1417 	ip = xfs_vtoi(VPTOXFSVP(ap->a_vp));
1418 	if (ip != NULL && (uio->uio_resid != resid ||
1419 	    (error == 0 && resid != 0)))
1420 		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
1421 	return (error);
1422 }
1423 
1424 /*
1425  * Close wrapper for fifos.
1426  *
1427  * Update the times on the inode then do device close.
1428  */
1429 static int
_xfsfifo_close(struct vop_close_args * ap)1430 _xfsfifo_close(
1431 	struct vop_close_args /* {
1432 		struct vnode *a_vp;
1433 		int  a_fflag;
1434 		struct ucred *a_cred;
1435 		struct thread *a_td;
1436 	} */ *ap)
1437 {
1438 
1439 	return (fifo_specops.vop_close(ap));
1440 }
1441 
1442 /*
1443  * Kqfilter wrapper for fifos.
1444  *
1445  * Fall through to ufs kqfilter routines if needed
1446  */
1447 static int
_xfsfifo_kqfilter(struct vop_kqfilter_args * ap)1448 _xfsfifo_kqfilter(
1449 	struct vop_kqfilter_args /* {
1450 		struct vnodeop_desc *a_desc;
1451 		struct vnode *a_vp;
1452 		struct knote *a_kn;
1453 	} */ *ap)
1454 {
1455 	int error;
1456 
1457 	error = fifo_specops.vop_kqfilter(ap);
1458 	if (error)
1459 		error = _xfs_kqfilter(ap);
1460 	return (error);
1461 }
1462 
1463 static int
_xfs_getextattr(struct vop_getextattr_args * ap)1464 _xfs_getextattr(
1465 	struct vop_getextattr_args /* {
1466 		struct vnode *a_vp;
1467 		int a_attrnamespace;
1468 		const char *a_name;
1469 		struct uio *a_uio;
1470 		size_t *a_size;
1471 		struct ucred *a_cred;
1472 		struct thread *a_td;
1473 	} */ *ap)
1474 {
1475 	int error;
1476 	char *value;
1477 	int size;
1478 
1479 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
1480 	    ap->a_cred, ap->a_td, VREAD);
1481         if (error)
1482 		return (error);
1483 
1484 	size = ATTR_MAX_VALUELEN;
1485 	value = (char *)kmem_zalloc(size, KM_SLEEP);
1486 	if (value == NULL)
1487 		return (ENOMEM);
1488 
1489 	XVOP_ATTR_GET(VPTOXFSVP(ap->a_vp), ap->a_name, value, &size, 1,
1490 	    ap->a_cred, error);
1491 
1492 	if (ap->a_uio != NULL) {
1493 		if (ap->a_uio->uio_iov->iov_len < size)
1494 			error = ERANGE;
1495 		else
1496 			uiomove(value, size, ap->a_uio);
1497 	}
1498 
1499 	if (ap->a_size != NULL)
1500 		*ap->a_size = size;
1501 
1502 	kmem_free(value, ATTR_MAX_VALUELEN);
1503 	return (error);
1504 }
1505 
1506 static int
_xfs_listextattr(struct vop_listextattr_args * ap)1507 _xfs_listextattr(
1508 	struct vop_listextattr_args /* {
1509 		struct vnode *a_vp;
1510 		int a_attrnamespace;
1511 		struct uio *a_uio;
1512 		size_t *a_size;
1513 		struct ucred *a_cred;
1514 		struct thread *a_td;
1515 	} */ *ap)
1516 {
1517 	int error;
1518 	char *buf = NULL;
1519 	int buf_len = 0;
1520 	attrlist_cursor_kern_t  cursor = { 0 };
1521 	int i;
1522 	char name_len;
1523 	int attrnames_len = 0;
1524 	int xfs_flags = ATTR_KERNAMELS;
1525 
1526 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
1527 	    ap->a_cred, ap->a_td, VREAD);
1528         if (error)
1529 		return (error);
1530 
1531 	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_USER)
1532 		xfs_flags |= ATTR_KERNORMALS;
1533 
1534 	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_SYSTEM)
1535 		xfs_flags |= ATTR_KERNROOTLS;
1536 
1537 	if (ap->a_uio == NULL || ap->a_uio->uio_iov[0].iov_base == NULL) {
1538 		xfs_flags |= ATTR_KERNOVAL;
1539 		buf_len = 0;
1540 	} else {
1541 		buf = ap->a_uio->uio_iov[0].iov_base;
1542 		buf_len = ap->a_uio->uio_iov[0].iov_len;
1543 	}
1544 
1545 	XVOP_ATTR_LIST(VPTOXFSVP(ap->a_vp), buf, buf_len, xfs_flags,
1546 		    &cursor, ap->a_cred, error);
1547 	if (error < 0) {
1548 		attrnames_len = -error;
1549 		error = 0;
1550 	}
1551 	if (buf == NULL)
1552 		goto done;
1553 
1554 	/*
1555 	 * extattr_list expects a list of names.  Each list
1556 	 * entry consists of one byte for the name length, followed
1557 	 * by the name (not null terminated)
1558 	 */
1559 	name_len=0;
1560 	for(i=attrnames_len-1; i > 0 ; --i) {
1561 		buf[i] = buf[i-1];
1562 		if (buf[i])
1563 			++name_len;
1564 		else {
1565 			buf[i] = name_len;
1566 			name_len = 0;
1567 		}
1568 	}
1569 	buf[0] = name_len;
1570 
1571 	if (ap->a_uio != NULL)
1572 		ap->a_uio->uio_resid -= attrnames_len;
1573 
1574 done:
1575 	if (ap->a_size != NULL)
1576 		*ap->a_size = attrnames_len;
1577 
1578 	return (error);
1579 }
1580 
1581 static int
_xfs_setextattr(struct vop_setextattr_args * ap)1582 _xfs_setextattr(struct vop_setextattr_args *ap)
1583 /*
1584 vop_setextattr {
1585 	IN struct vnode *a_vp;
1586 	IN int a_attrnamespace;
1587 	IN const char *a_name;
1588 	INOUT struct uio *a_uio;
1589 	IN struct ucred *a_cred;
1590 	IN struct thread *a_td;
1591 };
1592 */
1593 {
1594 	char *val;
1595 	size_t vallen;
1596 	int error, xfs_flags;
1597 
1598 	if (ap->a_vp->v_type == VCHR)
1599 		return (EOPNOTSUPP);
1600 
1601 	if (ap->a_uio == NULL)
1602 		return (EINVAL);
1603 	vallen = ap->a_uio->uio_resid;
1604 	if (vallen > ATTR_MAX_VALUELEN)
1605 		return (EOVERFLOW);
1606 
1607 	if (ap->a_name[0] == '\0')
1608 		return (EINVAL);
1609 
1610 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
1611 	    ap->a_cred, ap->a_td, VWRITE);
1612 	if (error)
1613 		return (error);
1614 
1615 	xfs_flags = 0;
1616 	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_USER)
1617 		xfs_flags |= ATTR_KERNORMALS;
1618 	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_SYSTEM)
1619 		xfs_flags |= ATTR_KERNROOTLS;
1620 
1621 	val = (char *)kmem_zalloc(vallen, KM_SLEEP);
1622 	if (val == NULL)
1623 		return (ENOMEM);
1624 	error = uiomove(val, (int)vallen, ap->a_uio);
1625 	if (error)
1626 		goto err_out;
1627 
1628 	XVOP_ATTR_SET(VPTOXFSVP(ap->a_vp), ap->a_name, val, vallen, xfs_flags,
1629 	    ap->a_cred, error);
1630 err_out:
1631 	kmem_free(val, vallen);
1632 	return(error);
1633 }
1634 
1635 static int
_xfs_deleteextattr(struct vop_deleteextattr_args * ap)1636 _xfs_deleteextattr(struct vop_deleteextattr_args *ap)
1637 /*
1638 vop_deleteextattr {
1639 	IN struct vnode *a_vp;
1640 	IN int a_attrnamespace;
1641 	IN const char *a_name;
1642 	IN struct ucred *a_cred;
1643 	IN struct thread *a_td;
1644 };
1645 */
1646 {
1647 	int error, xfs_flags;
1648 
1649 	if (ap->a_vp->v_type == VCHR)
1650 		return (EOPNOTSUPP);
1651 
1652 	if (ap->a_name[0] == '\0')
1653 		return (EINVAL);
1654 
1655 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
1656 	    ap->a_cred, ap->a_td, VWRITE);
1657 	if (error)
1658 		return (error);
1659 
1660 	xfs_flags = 0;
1661 	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_USER)
1662 		xfs_flags |= ATTR_KERNORMALS;
1663 	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_SYSTEM)
1664 		xfs_flags |= ATTR_KERNROOTLS;
1665 
1666 	XVOP_ATTR_REMOVE(VPTOXFSVP(ap->a_vp), ap->a_name, xfs_flags,
1667 	    ap->a_cred, error);
1668 	return (error);
1669 }
1670 
1671 static int
_xfs_vptofh(struct vop_vptofh_args * ap)1672 _xfs_vptofh(struct vop_vptofh_args *ap)
1673 /*
1674 vop_vptofh {
1675 	IN struct vnode *a_vp;
1676 	IN struct fid *a_fhp;
1677 };
1678 */
1679 {
1680 	printf("xfs_vptofh");
1681 	return ENOSYS;
1682 }
1683