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