2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1982, 1986, 1989, 1993, 1995
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
63 #include <rev_endian_fs.h>
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/namei.h>
67 #include <sys/resourcevar.h>
68 #include <sys/kernel.h>
69 #include <sys/file_internal.h>
73 #include <sys/kauth.h>
75 #include <sys/mount_internal.h>
76 #include <sys/vnode_internal.h>
77 #include <sys/malloc.h>
78 #include <sys/dirent.h>
79 #include <sys/fcntl.h>
81 #include <sys/quota.h>
82 #include <sys/uio_internal.h>
84 #include <kern/thread.h>
87 #include <miscfs/specfs/specdev.h>
89 #include <ufs/ufs/quota.h>
90 #include <ufs/ufs/inode.h>
91 #include <ufs/ufs/dir.h>
92 #include <ufs/ufs/ufsmount.h>
93 #include <ufs/ufs/ufs_extern.h>
96 #include <ufs/ufs/ufs_byte_order.h>
97 #include <architecture/byte_order.h>
98 #endif /* REV_ENDIAN_FS */
101 static int ufs_chmod(struct vnode
*, int, kauth_cred_t
, struct proc
*);
102 static int ufs_chown(struct vnode
*, uid_t
, gid_t
, kauth_cred_t
,
104 static int filt_ufsread(struct knote
*kn
, long hint
);
105 static int filt_ufswrite(struct knote
*kn
, long hint
);
106 static int filt_ufsvnode(struct knote
*kn
, long hint
);
107 static void filt_ufsdetach(struct knote
*kn
);
110 extern void fifo_printinfo(struct vnode
*vp
);
112 extern int ufs_direnter2(struct vnode
*dvp
, struct direct
*dirp
,
115 static int ufs_readdirext(vnode_t vp
, uio_t uio
, int *eofflag
, int *numdirent
,
116 vfs_context_t context
);
119 * Create a regular file
123 struct vnop_create_args
/* {
125 struct vnode **a_vpp;
126 struct componentname *a_cnp;
127 struct vnode_vattr *a_vap;
128 vfs_context_t a_context;
133 if ( (error
= ufs_makeinode(ap
->a_vap
, ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
)) )
135 VN_KNOTE(ap
->a_dvp
, NOTE_WRITE
);
144 struct vnop_mknod_args
/* {
146 struct vnode **a_vpp;
147 struct componentname *a_cnp;
148 struct vnode_attr *a_vap;
149 vfs_context_t a_context;
152 struct vnode_attr
*vap
= ap
->a_vap
;
153 struct vnode
**vpp
= ap
->a_vpp
;
154 struct vnode
*dvp
= ap
->a_dvp
;
157 struct componentname
*cnp
= ap
->a_cnp
;
160 /* use relookup to force correct directory hints */
161 cnp
->cn_flags
&= ~MODMASK
;
162 cnp
->cn_flags
|= (WANTPARENT
| NOCACHE
);
163 cnp
->cn_nameiop
= CREATE
;
165 (void) relookup(dvp
, &tvp
, cnp
);
167 /* get rid of reference relookup returned */
172 ufs_makeinode(ap
->a_vap
, ap
->a_dvp
, vpp
, ap
->a_cnp
)) )
174 VN_KNOTE(ap
->a_dvp
, NOTE_WRITE
);
176 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
177 if (vap
->va_rdev
!= VNOVAL
) {
179 * Want to be able to use this to make badblock
180 * inodes, so don't truncate the dev number.
182 ip
->i_rdev
= vap
->va_rdev
;
194 struct vnop_open_args
/* {
197 vfs_context_t a_context;
202 * Files marked append-only must be opened for appending.
204 if ((VTOI(ap
->a_vp
)->i_flags
& APPEND
) &&
205 (ap
->a_mode
& (FWRITE
| O_APPEND
)) == FWRITE
)
213 * Update the times on the inode.
217 struct vnop_close_args
/* {
220 vfs_context_t a_context;
223 register struct vnode
*vp
= ap
->a_vp
;
224 register struct inode
*ip
= VTOI(vp
);
227 if (vnode_isinuse(vp
, 1)) {
229 ITIMES(ip
, &tv
, &tv
);
232 cluster_push(vp
, IO_CLOSE
);
239 struct vnop_getattr_args
/* {
241 struct vnode_attr *a_vap;
242 vfs_context_t a_context;
245 register struct vnode
*vp
= ap
->a_vp
;
246 register struct inode
*ip
= VTOI(vp
);
247 register struct vnode_attr
*vap
= ap
->a_vap
;
253 ITIMES(ip
, &tv
, &tv
);
255 * Copy from inode table
257 VATTR_RETURN(vap
, va_fsid
, ip
->i_dev
);
258 VATTR_RETURN(vap
, va_fileid
, ip
->i_number
);
259 VATTR_RETURN(vap
, va_mode
, ip
->i_mode
& ~IFMT
);
260 VATTR_RETURN(vap
, va_nlink
, ip
->i_nlink
);
261 VATTR_RETURN(vap
, va_uid
, ip
->i_uid
);
262 VATTR_RETURN(vap
, va_gid
, ip
->i_gid
);
263 VATTR_RETURN(vap
, va_rdev
, (dev_t
)ip
->i_rdev
);
264 VATTR_RETURN(vap
, va_data_size
, ip
->i_din
.di_size
);
265 vap
->va_access_time
.tv_sec
= ip
->i_atime
;
266 vap
->va_access_time
.tv_nsec
= ip
->i_atimensec
;
267 VATTR_SET_SUPPORTED(vap
, va_access_time
);
268 vap
->va_modify_time
.tv_sec
= ip
->i_mtime
;
269 vap
->va_modify_time
.tv_nsec
= ip
->i_mtimensec
;
270 VATTR_SET_SUPPORTED(vap
, va_modify_time
);
271 vap
->va_change_time
.tv_sec
= ip
->i_ctime
;
272 vap
->va_change_time
.tv_nsec
= ip
->i_ctimensec
;
273 VATTR_SET_SUPPORTED(vap
, va_change_time
);
274 VATTR_RETURN(vap
, va_flags
, ip
->i_flags
);
275 VATTR_RETURN(vap
, va_gen
, ip
->i_gen
);
276 if (vp
->v_type
== VBLK
)
277 VATTR_RETURN(vap
, va_iosize
, BLKDEV_IOSIZE
);
278 else if (vp
->v_type
== VCHR
)
279 VATTR_RETURN(vap
, va_iosize
, MAXPHYSIO
);
281 VATTR_RETURN(vap
, va_iosize
, vp
->v_mount
->mnt_vfsstat
.f_iosize
);
282 devBlockSize
= vfs_devblocksize(vnode_mount(vp
));
283 VATTR_RETURN(vap
, va_data_alloc
, dbtob((u_quad_t
)ip
->i_blocks
, devBlockSize
));
284 VATTR_RETURN(vap
, va_type
, vp
->v_type
);
285 VATTR_RETURN(vap
, va_filerev
, ip
->i_modrev
);
290 * Set attribute vnode op. called from several syscalls
294 struct vnop_setattr_args
/* {
296 struct vnode_attr *a_vap;
298 vfs_context_t a_context;
301 struct vnode_attr
*vap
= ap
->a_vap
;
302 struct vnode
*vp
= ap
->a_vp
;
303 struct inode
*ip
= VTOI(vp
);
304 kauth_cred_t cred
= vfs_context_ucred(ap
->a_context
);
305 struct proc
*p
= vfs_context_proc(ap
->a_context
);
306 struct timeval atimeval
, mtimeval
;
312 * Go through the fields and update iff set.
314 if (VATTR_IS_ACTIVE(vap
, va_flags
)) {
315 ip
->i_flags
= vap
->va_flags
;
316 ip
->i_flag
|= IN_CHANGE
;
318 VATTR_SET_SUPPORTED(vap
, va_flags
);
320 nuid
= VATTR_IS_ACTIVE(vap
, va_uid
) ? vap
->va_uid
: (uid_t
)VNOVAL
;
321 ngid
= VATTR_IS_ACTIVE(vap
, va_gid
) ? vap
->va_gid
: (gid_t
)VNOVAL
;
322 if (nuid
!= (uid_t
)VNOVAL
|| ngid
!= (gid_t
)VNOVAL
) {
323 if ( (error
= ufs_chown(vp
, nuid
, ngid
, cred
, p
)) )
326 VATTR_SET_SUPPORTED(vap
, va_uid
);
327 VATTR_SET_SUPPORTED(vap
, va_gid
);
329 if (VATTR_IS_ACTIVE(vap
, va_data_size
)) {
330 if ( (error
= ffs_truncate_internal(vp
, vap
->va_data_size
, vap
->va_vaflags
& 0xffff, cred
)) )
333 VATTR_SET_SUPPORTED(vap
, va_data_size
);
336 if (VATTR_IS_ACTIVE(vap
, va_access_time
) || VATTR_IS_ACTIVE(vap
, va_modify_time
)) {
337 if (VATTR_IS_ACTIVE(vap
, va_access_time
))
338 ip
->i_flag
|= IN_ACCESS
;
339 if (VATTR_IS_ACTIVE(vap
, va_modify_time
))
340 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
341 atimeval
.tv_sec
= vap
->va_access_time
.tv_sec
;
342 atimeval
.tv_usec
= vap
->va_access_time
.tv_nsec
/ 1000;
343 mtimeval
.tv_sec
= vap
->va_modify_time
.tv_sec
;
344 mtimeval
.tv_usec
= vap
->va_modify_time
.tv_nsec
/ 1000;
345 if ( (error
= ffs_update(vp
, &atimeval
, &mtimeval
, 1)) )
348 VATTR_SET_SUPPORTED(vap
, va_access_time
);
349 VATTR_SET_SUPPORTED(vap
, va_modify_time
);
351 if (VATTR_IS_ACTIVE(vap
, va_mode
)) {
352 if ((error
= ufs_chmod(vp
, (int)vap
->va_mode
, cred
, p
)))
355 VATTR_SET_SUPPORTED(vap
, va_mode
);
357 VN_KNOTE(vp
, NOTE_ATTRIB
);
363 * Change the mode on a file.
364 * Inode must be locked before calling.
367 ufs_chmod(struct vnode
*vp
, int mode
, kauth_cred_t cred
, struct proc
*p
)
369 register struct inode
*ip
= VTOI(vp
);
371 ip
->i_mode
&= ~ALLPERMS
;
372 ip
->i_mode
|= (mode
& ALLPERMS
);
373 ip
->i_flag
|= IN_CHANGE
;
378 * Perform chown operation on inode ip;
379 * inode must be locked prior to call.
382 ufs_chown(struct vnode
*vp
, uid_t uid
, gid_t gid
, kauth_cred_t cred
,
385 register struct inode
*ip
= VTOI(vp
);
392 int64_t change
; /* in bytes */
396 if (uid
== (uid_t
)VNOVAL
)
398 if (gid
== (gid_t
)VNOVAL
)
403 if ( (error
= getinoquota(ip
)) )
406 dqrele(ip
->i_dquot
[USRQUOTA
]);
407 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
410 dqrele(ip
->i_dquot
[GRPQUOTA
]);
411 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
413 devBlockSize
= vfs_devblocksize(vnode_mount(vp
));
415 change
= dbtob((int64_t)ip
->i_blocks
, devBlockSize
);
416 (void) chkdq(ip
, -change
, cred
, CHOWN
);
417 (void) chkiq(ip
, -1, cred
, CHOWN
);
418 for (i
= 0; i
< MAXQUOTAS
; i
++) {
419 dqrele(ip
->i_dquot
[i
]);
420 ip
->i_dquot
[i
] = NODQUOT
;
426 if ((error
= getinoquota(ip
)) == 0) {
428 dqrele(ip
->i_dquot
[USRQUOTA
]);
429 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
432 dqrele(ip
->i_dquot
[GRPQUOTA
]);
433 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
435 if ((error
= chkdq(ip
, change
, cred
, CHOWN
)) == 0) {
436 if ((error
= chkiq(ip
, 1, cred
, CHOWN
)) == 0)
439 (void) chkdq(ip
, -change
, cred
, CHOWN
|FORCE
);
441 for (i
= 0; i
< MAXQUOTAS
; i
++) {
442 dqrele(ip
->i_dquot
[i
]);
443 ip
->i_dquot
[i
] = NODQUOT
;
448 if (getinoquota(ip
) == 0) {
450 dqrele(ip
->i_dquot
[USRQUOTA
]);
451 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
454 dqrele(ip
->i_dquot
[GRPQUOTA
]);
455 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
457 (void) chkdq(ip
, change
, cred
, FORCE
|CHOWN
);
458 (void) chkiq(ip
, 1, cred
, FORCE
|CHOWN
);
459 (void) getinoquota(ip
);
464 panic("chown: lost quota");
466 if (ouid
!= uid
|| ogid
!= gid
)
467 ip
->i_flag
|= IN_CHANGE
;
473 struct vnop_ioctl_args
/* {
478 vfs_context_t a_context;
482 switch (ap
->a_command
) {
485 { register struct inode
*ip
;
486 register struct vnode
*vp
;
487 register struct fs
*fs
;
488 register struct radvisory
*ra
;
489 int devBlockSize
= 0;
494 ra
= (struct radvisory
*)(ap
->a_data
);
498 if ((u_int64_t
)ra
->ra_offset
>= ip
->i_size
) {
501 devBlockSize
= vfs_devblocksize(vnode_mount(vp
));
503 error
= advisory_read(vp
, ip
->i_size
, ra
->ra_offset
, ra
->ra_count
);
513 ufs_select(__unused
struct vnop_select_args
*ap
)
516 * We should really check to see if I/O is possible.
524 * NB Currently unsupported.
527 ufs_mmap(__unused
struct vnop_mmap_args
*ap
)
534 struct vnop_remove_args
/* {
537 struct componentname *a_cnp;
539 vfs_context_t a_context;
542 return(ufs_remove_internal(ap
->a_dvp
, ap
->a_vp
, ap
->a_cnp
, ap
->a_flags
));
547 ufs_remove_internal(vnode_t dvp
, vnode_t vp
, struct componentname
*cnp
, int flags
)
553 if (flags
& VNODE_REMOVE_NODELETEBUSY
) {
554 /* Caller requested Carbon delete semantics */
555 if (vnode_isinuse(vp
, 0)) {
560 cnp
->cn_flags
&= ~MODMASK
;
561 cnp
->cn_flags
|= (WANTPARENT
| NOCACHE
);
562 cnp
->cn_nameiop
= DELETE
;
564 (void) relookup(dvp
, &tvp
, cnp
);
569 panic("ufs_remove_internal: relookup returned a different vp");
571 * get rid of reference relookup returned
578 if ((error
= ufs_dirremove(dvp
, cnp
)) == 0) {
580 ip
->i_flag
|= IN_CHANGE
;
581 VN_KNOTE(vp
, NOTE_DELETE
);
582 VN_KNOTE(dvp
, NOTE_WRITE
);
593 struct vnop_link_args
/* {
595 struct vnode *a_tdvp;
596 struct componentname *a_cnp;
597 vfs_context_t a_context;
600 struct vnode
*vp
= ap
->a_vp
;
601 struct vnode
*tdvp
= ap
->a_tdvp
;
602 struct componentname
*cnp
= ap
->a_cnp
;
603 vfs_context_t ctx
= cnp
->cn_context
;
604 struct proc
*p
= vfs_context_proc(ctx
);
611 if ((nlink_t
)ip
->i_nlink
>= LINK_MAX
) {
616 ip
->i_flag
|= IN_CHANGE
;
618 error
= ffs_update(vp
, &tv
, &tv
, 1);
620 error
= ufs_direnter(ip
, tdvp
, cnp
);
623 ip
->i_flag
|= IN_CHANGE
;
625 VN_KNOTE(vp
, NOTE_LINK
);
626 VN_KNOTE(tdvp
, NOTE_WRITE
);
632 * whiteout vnode call
637 struct vnop_whiteout_args
/* {
639 struct componentname *a_cnp;
641 vfs_context_t a_context;
644 struct vnode
*dvp
= ap
->a_dvp
;
645 struct componentname
*cnp
= ap
->a_cnp
;
646 struct direct newdir
;
649 switch (ap
->a_flags
) {
651 /* 4.4 format directories support whiteout operations */
652 if (dvp
->v_mount
->mnt_maxsymlinklen
> 0)
657 /* create a new directory whiteout */
659 if (dvp
->v_mount
->mnt_maxsymlinklen
<= 0)
660 panic("ufs_whiteout: old format filesystem");
664 newdir
.d_namlen
= cnp
->cn_namelen
;
665 bcopy(cnp
->cn_nameptr
, newdir
.d_name
, (unsigned)cnp
->cn_namelen
+ 1);
666 newdir
.d_type
= DT_WHT
;
667 error
= ufs_direnter2(dvp
, &newdir
, cnp
->cn_context
);
671 /* remove an existing directory whiteout */
673 if (dvp
->v_mount
->mnt_maxsymlinklen
<= 0)
674 panic("ufs_whiteout: old format filesystem");
677 cnp
->cn_flags
&= ~DOWHITEOUT
;
678 error
= ufs_dirremove(dvp
, cnp
);
686 * Rename system call.
687 * rename("foo", "bar");
690 * link("foo", "bar");
692 * but ``atomically''. Can't do full commit without saving state in the
693 * inode on disk which isn't feasible at this time. Best we can do is
694 * always guarantee the target exists.
696 * Basic algorithm is:
698 * 1) Bump link count on source while we're linking it to the
699 * target. This also ensure the inode won't be deleted out
700 * from underneath us while we work (it may be truncated by
701 * a concurrent `trunc' or `open' for creation).
702 * 2) Link source to destination. If destination already exists,
704 * 3) Unlink source reference to inode if still around. If a
705 * directory was moved and the parent of the destination
706 * is different from the source, patch the ".." entry in the
711 struct vnop_rename_args
/* {
712 struct vnode *a_fdvp;
714 struct componentname *a_fcnp;
715 struct vnode *a_tdvp;
717 struct componentname *a_tcnp;
718 vfs_context_t a_context;
721 struct vnode
*tvp
= ap
->a_tvp
;
722 register struct vnode
*tdvp
= ap
->a_tdvp
;
723 struct vnode
*fvp
= ap
->a_fvp
;
724 struct vnode
*fdvp
= ap
->a_fdvp
;
725 struct componentname
*tcnp
= ap
->a_tcnp
;
726 struct componentname
*fcnp
= ap
->a_fcnp
;
727 vfs_context_t ctx
= fcnp
->cn_context
;
728 struct proc
*p
= vfs_context_proc(ctx
);
729 struct inode
*ip
, *xp
, *dp
;
730 struct dirtemplate dirbuf
;
732 ino_t doingdirectory
= 0, oldparent
= 0, newparent
= 0;
733 int error
= 0, ioflag
;
735 struct vnode
*rl_vp
= NULL
;
739 * Check if just deleting a link name or if we've lost a race.
740 * If another process completes the same rename after we've looked
741 * up the source and have blocked looking up the target, then the
742 * source and target inodes may be identical now although the
743 * names were never linked.
746 if (fvp
->v_type
== VDIR
) {
748 * Linked directories are impossible, so we must
749 * have lost the race. Pretend that the rename
750 * completed before the lookup.
752 #ifdef UFS_RENAME_DEBUG
753 printf("ufs_rename: fvp == tvp for directories\n");
760 * don't need to check in here for permissions, must already have been granted
761 * ufs_remove_internal now does the relookup
763 error
= ufs_remove_internal(fdvp
, fvp
, fcnp
, 0);
768 * because the vnode_authorization code may have looked up in this directory
769 * between the original lookup and the actual call to VNOP_RENAME, we need
770 * to reset the directory hints... since we haven't dropped the FSNODELOCK
771 * on tdvp since this whole thing started, we expect relookup to return
772 * tvp (which may be NULL)
774 tcnp
->cn_flags
&= ~MODMASK
;
775 tcnp
->cn_flags
|= (WANTPARENT
| NOCACHE
);
777 if ( (error
= relookup(tdvp
, &rl_vp
, tcnp
)) )
778 panic("ufs_rename: relookup on target returned error");
781 * Don't panic. The only way this state will be reached is if
782 * another rename has taken effect. In that case, it's safe
783 * to restart this rename and let things sort themselves out.
797 if ((ip
->i_mode
& IFMT
) == IFDIR
) {
798 if (ip
->i_flag
& IN_RENAME
) {
802 ip
->i_flag
|= IN_RENAME
;
803 oldparent
= dp
->i_number
;
806 VN_KNOTE(fdvp
, NOTE_WRITE
); /* XXX right place? */
809 * When the target exists, both the directory
810 * and target vnodes are returned locked.
818 * 1) Bump link count while we're moving stuff
819 * around. If we crash somewhere before
820 * completing our work, the link count
821 * may be wrong, but correctable.
824 ip
->i_flag
|= IN_CHANGE
;
826 if ( (error
= ffs_update(fvp
, &tv
, &tv
, 1)) ) {
831 * If ".." must be changed (ie the directory gets a new
832 * parent) then the source directory must not be in the
833 * directory heirarchy above the target, as this would
834 * orphan everything below the source directory. Also
835 * the user must have write permission in the source so
836 * as to be able to change "..". We must repeat the call
837 * to namei, as the parent directory is unlocked by the
838 * call to checkpath().
841 if (oldparent
!= dp
->i_number
)
842 newparent
= dp
->i_number
;
844 if (doingdirectory
&& newparent
) {
845 if (error
) /* write access check above */
848 if ( (error
= ufs_checkpath(ip
, dp
, vfs_context_ucred(tcnp
->cn_context
))) )
851 if ( (error
= relookup(tdvp
, &tvp
, tcnp
)) )
862 * 2) If target doesn't exist, link the target
863 * to the source and unlink the source.
864 * Otherwise, rewrite the target directory
865 * entry to reference the source inode and
866 * expunge the original entry's existence.
869 if (dp
->i_dev
!= ip
->i_dev
)
870 panic("rename: EXDEV");
872 * Account for ".." in new directory.
873 * When source and destination have the same
874 * parent we don't fool with the link count.
876 if (doingdirectory
&& newparent
) {
877 if ((nlink_t
)dp
->i_nlink
>= LINK_MAX
) {
882 dp
->i_flag
|= IN_CHANGE
;
883 if ( (error
= ffs_update(tdvp
, &tv
, &tv
, 1)) )
886 if ( (error
= ufs_direnter(ip
, tdvp
, tcnp
)) ) {
887 if (doingdirectory
&& newparent
) {
889 dp
->i_flag
|= IN_CHANGE
;
890 (void)ffs_update(tdvp
, &tv
, &tv
, 1);
894 VN_KNOTE(tdvp
, NOTE_WRITE
);
896 if (xp
->i_dev
!= dp
->i_dev
|| xp
->i_dev
!= ip
->i_dev
)
897 panic("rename: EXDEV");
899 * Short circuit rename(foo, foo).
901 if (xp
->i_number
== ip
->i_number
)
902 panic("rename: same file");
904 * Target must be empty if a directory and have no links
905 * to it. Also, ensure source and target are compatible
906 * (both directories, or both not directories).
908 if ((xp
->i_mode
&IFMT
) == IFDIR
) {
909 if (!ufs_dirempty(xp
, dp
->i_number
, vfs_context_ucred(tcnp
->cn_context
)) ||
914 if (!doingdirectory
) {
919 } else if (doingdirectory
) {
923 if ( (error
= ufs_dirrewrite(dp
, ip
, tcnp
)) )
926 * If the target directory is in the same
927 * directory as the source directory,
928 * decrement the link count on the parent
929 * of the target directory.
931 if (doingdirectory
&& !newparent
) {
933 dp
->i_flag
|= IN_CHANGE
;
935 VN_KNOTE(tdvp
, NOTE_WRITE
);
937 * Adjust the link count of the target to
938 * reflect the dirrewrite above. If this is
939 * a directory it is empty and there are
940 * no links to it, so we can squash the inode and
941 * any space associated with it. We disallowed
942 * renaming over top of a directory with links to
943 * it above, as the remaining link would point to
944 * a directory without "." or ".." entries.
947 if (doingdirectory
) {
948 if (--xp
->i_nlink
!= 0)
949 panic("rename: linked directory");
950 ioflag
= ((tvp
)->v_mount
->mnt_flag
& MNT_ASYNC
) ?
952 error
= ffs_truncate_internal(tvp
, (off_t
)0, ioflag
, vfs_context_ucred(tcnp
->cn_context
));
954 xp
->i_flag
|= IN_CHANGE
;
955 VN_KNOTE(tvp
, NOTE_DELETE
);
963 * 3) Unlink the source.
965 fcnp
->cn_flags
&= ~MODMASK
;
966 fcnp
->cn_flags
|= (WANTPARENT
| NOCACHE
);
968 (void) relookup(fdvp
, &fvp
, fcnp
);
976 * From name has disappeared.
979 panic("rename: lost dir entry");
984 * Ensure that the directory entry still exists and has not
985 * changed while the new name has been entered. If the source is
986 * a file then the entry may have been unlinked or renamed. In
987 * either case there is no further work to be done. If the source
988 * is a directory then it cannot have been rmdir'ed; its link
989 * count of three would cause a rmdir to fail with ENOTEMPTY.
990 * The IN_RENAME flag ensures that it cannot be moved by another
995 panic("rename: lost dir entry");
998 * If the source is a directory with a
999 * new parent, the link count of the old
1000 * parent directory must be decremented
1001 * and ".." set to point to the new parent.
1003 if (doingdirectory
&& newparent
) {
1005 dp
->i_flag
|= IN_CHANGE
;
1006 error
= vn_rdwr(UIO_READ
, fvp
, (caddr_t
)&dirbuf
,
1007 sizeof (struct dirtemplate
), (off_t
)0,
1008 UIO_SYSSPACE32
, IO_NODELOCKED
,
1009 vfs_context_ucred(tcnp
->cn_context
), (int *)0, (struct proc
*)0);
1011 # if (BYTE_ORDER == LITTLE_ENDIAN)
1012 if (fvp
->v_mount
->mnt_maxsymlinklen
<= 0)
1013 namlen
= dirbuf
.dotdot_type
;
1015 namlen
= dirbuf
.dotdot_namlen
;
1017 namlen
= dirbuf
.dotdot_namlen
;
1020 dirbuf
.dotdot_name
[0] != '.' ||
1021 dirbuf
.dotdot_name
[1] != '.') {
1022 ufs_dirbad(xp
, (doff_t
)12,
1023 "rename: mangled dir");
1025 dirbuf
.dotdot_ino
= newparent
;
1026 (void) vn_rdwr(UIO_WRITE
, fvp
,
1028 sizeof (struct dirtemplate
),
1029 (off_t
)0, UIO_SYSSPACE32
,
1030 IO_NODELOCKED
|IO_SYNC
,
1031 vfs_context_ucred(tcnp
->cn_context
), (int *)0,
1037 error
= ufs_dirremove(fdvp
, fcnp
);
1040 xp
->i_flag
|= IN_CHANGE
;
1042 xp
->i_flag
&= ~IN_RENAME
;
1044 VN_KNOTE(fvp
, NOTE_RENAME
);
1056 ip
->i_flag
&= ~IN_RENAME
;
1059 ip
->i_flag
|= IN_CHANGE
;
1060 ip
->i_flag
&= ~IN_RENAME
;
1067 * A virgin directory (no blushing please).
1069 static struct dirtemplate mastertemplate
= {
1070 0, 12, DT_DIR
, 1, ".",
1071 0, DIRBLKSIZ
- 12, DT_DIR
, 2, ".."
1073 static struct odirtemplate omastertemplate
= {
1075 0, DIRBLKSIZ
- 12, 2, ".."
1083 struct vnop_mkdir_args
/* {
1084 struct vnode *a_dvp;
1085 struct vnode **a_vpp;
1086 struct componentname *a_cnp;
1087 struct vnode_attr *a_vap;
1088 vfs_context_t a_context;
1091 register struct vnode
*dvp
= ap
->a_dvp
;
1092 register struct vnode_attr
*vap
= ap
->a_vap
;
1093 register struct componentname
*cnp
= ap
->a_cnp
;
1094 register struct inode
*ip
, *dp
;
1096 struct dirtemplate dirtemplate
, *dtp
;
1100 /* use relookup to force correct directory hints */
1101 cnp
->cn_flags
&= ~MODMASK
;
1102 cnp
->cn_flags
|= (WANTPARENT
| NOCACHE
);
1103 cnp
->cn_nameiop
= CREATE
;
1105 (void) relookup(dvp
, &tvp
, cnp
);
1107 /* get rid of reference relookup returned */
1112 if ((nlink_t
)dp
->i_nlink
>= LINK_MAX
) {
1116 dmode
= vap
->va_mode
& 0777;
1120 * Must simulate part of ufs_makeinode here to acquire the inode,
1121 * but not have it entered in the parent directory. The entry is
1122 * made later after writing "." and ".." entries.
1124 if ( (error
= ffs_valloc(dvp
, (mode_t
)dmode
, vfs_context_ucred(cnp
->cn_context
), &tvp
)) )
1127 ip
->i_uid
= ap
->a_vap
->va_uid
;
1128 ip
->i_gid
= ap
->a_vap
->va_gid
;
1129 VATTR_SET_SUPPORTED(ap
->a_vap
, va_mode
);
1130 VATTR_SET_SUPPORTED(ap
->a_vap
, va_uid
);
1131 VATTR_SET_SUPPORTED(ap
->a_vap
, va_gid
);
1133 if ((error
= getinoquota(ip
)) ||
1134 (error
= chkiq(ip
, 1, vfs_context_ucred(cnp
->cn_context
), 0))) {
1135 ffs_vfree(tvp
, ip
->i_number
, dmode
);
1140 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
1143 if (cnp
->cn_flags
& ISWHITEOUT
)
1144 ip
->i_flags
|= UF_OPAQUE
;
1146 error
= ffs_update(tvp
, &tv
, &tv
, 1);
1149 * Bump link count in parent directory
1150 * to reflect work done below. Should
1151 * be done before reference is created
1152 * so reparation is possible if we crash.
1155 dp
->i_flag
|= IN_CHANGE
;
1156 if ( (error
= ffs_update(dvp
, &tv
, &tv
, 1)) )
1159 /* Initialize directory with "." and ".." from static template. */
1160 if (dvp
->v_mount
->mnt_maxsymlinklen
> 0)
1161 dtp
= &mastertemplate
;
1163 dtp
= (struct dirtemplate
*)&omastertemplate
;
1165 dirtemplate
.dot_ino
= ip
->i_number
;
1166 dirtemplate
.dotdot_ino
= dp
->i_number
;
1167 error
= vn_rdwr(UIO_WRITE
, tvp
, (caddr_t
)&dirtemplate
,
1168 sizeof (dirtemplate
), (off_t
)0, UIO_SYSSPACE32
,
1169 IO_NODELOCKED
|IO_SYNC
, vfs_context_ucred(cnp
->cn_context
), (int *)0, (struct proc
*)0);
1172 dp
->i_flag
|= IN_CHANGE
;
1175 if (DIRBLKSIZ
> VFSTOUFS(dvp
->v_mount
)->um_mountp
->mnt_vfsstat
.f_bsize
)
1176 panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
1178 ip
->i_size
= DIRBLKSIZ
;
1179 ip
->i_flag
|= IN_CHANGE
;
1182 /* Directory set up, now install it's entry in the parent directory. */
1183 if ( (error
= ufs_direnter(ip
, dvp
, cnp
)) ) {
1185 dp
->i_flag
|= IN_CHANGE
;
1189 * No need to do an explicit vnop_truncate here, vnode_put will do it
1190 * for us because we set the link count to 0.
1194 ip
->i_flag
|= IN_CHANGE
;
1196 * since we're not returning tvp due to the error,
1197 * we're responsible for releasing it here
1201 VN_KNOTE(dvp
, NOTE_WRITE
| NOTE_LINK
);
1209 * Rmdir system call.
1213 struct vnop_rmdir_args
/* {
1214 struct vnode *a_dvp;
1216 struct componentname *a_cnp;
1217 vfs_context_t a_context;
1220 struct vnode
*vp
= ap
->a_vp
;
1221 struct vnode
*dvp
= ap
->a_dvp
;
1223 struct componentname
*cnp
= ap
->a_cnp
;
1224 struct inode
*ip
, *dp
;
1231 * No rmdir "." please.
1237 cnp
->cn_flags
&= ~MODMASK
;
1238 cnp
->cn_flags
|= (WANTPARENT
| NOCACHE
);
1240 (void) relookup(dvp
, &tvp
, cnp
);
1245 panic("ufs_rmdir: relookup returned a different vp");
1247 * get rid of reference relookup returned
1253 * Verify the directory is empty (and valid).
1254 * (Rmdir ".." won't be valid since
1255 * ".." will contain a reference to
1256 * the current directory and thus be
1260 if (ip
->i_nlink
!= 2 ||
1261 !ufs_dirempty(ip
, dp
->i_number
, vfs_context_ucred(cnp
->cn_context
))) {
1266 * Delete reference to directory before purging
1267 * inode. If we crash in between, the directory
1268 * will be reattached to lost+found,
1270 if ( (error
= ufs_dirremove(dvp
, cnp
)) )
1272 VN_KNOTE(dvp
, NOTE_WRITE
| NOTE_LINK
);
1274 dp
->i_flag
|= IN_CHANGE
;
1277 * Truncate inode. The only stuff left
1278 * in the directory is "." and "..". The
1279 * "." reference is inconsequential since
1280 * we're quashing it. The ".." reference
1281 * has already been adjusted above. We've
1282 * removed the "." reference and the reference
1283 * in the parent directory, but there may be
1284 * other hard links so decrement by 2 and
1285 * worry about them later.
1288 ioflag
= ((vp
)->v_mount
->mnt_flag
& MNT_ASYNC
) ? 0 : IO_SYNC
;
1289 error
= ffs_truncate_internal(vp
, (off_t
)0, ioflag
, vfs_context_ucred(cnp
->cn_context
));
1290 cache_purge(ITOV(ip
));
1292 VN_KNOTE(vp
, NOTE_DELETE
);
1297 * symlink -- make a symbolic link
1301 struct vnop_symlink_args
/* {
1302 struct vnode *a_dvp;
1303 struct vnode **a_vpp;
1304 struct componentname *a_cnp;
1305 struct vnode_attr *a_vap;
1307 vfs_context_t a_context;
1310 register struct vnode
*vp
, **vpp
= ap
->a_vpp
;
1311 register struct inode
*ip
;
1314 if ( (error
= ufs_makeinode(ap
->a_vap
, ap
->a_dvp
, vpp
, ap
->a_cnp
)) )
1316 VN_KNOTE(ap
->a_dvp
, NOTE_WRITE
);
1318 len
= strlen(ap
->a_target
);
1319 if (len
< vp
->v_mount
->mnt_maxsymlinklen
) {
1321 bcopy(ap
->a_target
, (char *)ip
->i_shortlink
, len
);
1323 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1325 error
= vn_rdwr(UIO_WRITE
, vp
, ap
->a_target
, len
, (off_t
)0,
1326 UIO_SYSSPACE32
, IO_NODELOCKED
, vfs_context_ucred(ap
->a_cnp
->cn_context
), (int *)0,
1332 * Vnode op for reading directories.
1334 * The routine below assumes that the on-disk format of a directory
1335 * is the same as that defined by <sys/dirent.h>. If the on-disk
1336 * format changes, then it will be necessary to do a conversion
1337 * from the on-disk format that read returns to the format defined
1338 * by <sys/dirent.h>.
1342 struct vnop_readdir_args
/* {
1348 vfs_context_t a_context;
1351 struct uio
*uio
= ap
->a_uio
;
1355 if (ap
->a_flags
& VNODE_READDIR_EXTENDED
) {
1356 return ufs_readdirext(ap
->a_vp
, uio
, ap
->a_eofflag
,
1357 ap
->a_numdirent
, ap
->a_context
);
1360 // LP64todo - fix this
1361 count
= uio_resid(uio
);
1362 /* Make sure we don't return partial entries. */
1363 count
-= (uio
->uio_offset
+ count
) & (DIRBLKSIZ
-1);
1366 // LP64todo - fix this
1367 lost
= uio_resid(uio
) - count
;
1368 uio_setresid(uio
, count
);
1369 uio_iov_len_set(uio
, count
);
1370 # if (BYTE_ORDER == LITTLE_ENDIAN)
1371 if (ap
->a_vp
->v_mount
->mnt_maxsymlinklen
> 0) {
1372 error
= ffs_read_internal(ap
->a_vp
, uio
, 0);
1374 struct dirent
*dp
, *edp
;
1376 struct iovec_32 aiov
;
1382 auio
.uio_iovs
.iov32p
= &aiov
;
1383 auio
.uio_iovcnt
= 1;
1384 #if 1 /* LP64todo - can't use new segment flags until the drivers are ready */
1385 auio
.uio_segflg
= UIO_SYSSPACE
;
1387 auio
.uio_segflg
= UIO_SYSSPACE32
;
1389 aiov
.iov_len
= count
;
1390 MALLOC(dirbuf
, caddr_t
, count
, M_TEMP
, M_WAITOK
);
1391 aiov
.iov_base
= (uintptr_t)dirbuf
;
1392 error
= ffs_read_internal(ap
->a_vp
, &auio
, 0);
1394 // LP64todo - fix this
1395 readcnt
= count
- uio_resid(&auio
);
1396 edp
= (struct dirent
*)&dirbuf
[readcnt
];
1397 for (dp
= (struct dirent
*)dirbuf
; dp
< edp
; ) {
1399 dp
->d_namlen
= dp
->d_type
;
1401 if (dp
->d_reclen
> 0) {
1402 dp
= (struct dirent
*)
1403 ((char *)dp
+ dp
->d_reclen
);
1410 error
= uiomove(dirbuf
, readcnt
, uio
);
1412 FREE(dirbuf
, M_TEMP
);
1415 error
= ffs_read_internal(ap
->a_vp
, uio
, 0);
1418 uio_setresid(uio
, (uio_resid(uio
) + lost
));
1420 *ap
->a_eofflag
= (off_t
)VTOI(ap
->a_vp
)->i_size
<= uio
->uio_offset
;
1426 * ufs_readdirext reads directory entries into the buffer pointed
1427 * to by uio, in a filesystem independent format. Up to uio_resid
1428 * bytes of data can be transferred. The data in the buffer is a
1429 * series of packed direntry structures where each one contains the
1430 * following entries:
1432 * d_reclen: length of record
1433 * d_ino: file number of entry
1434 * d_seekoff: seek offset (used by NFS server, aka cookie)
1436 * d_namlen: length of string in d_name
1437 * d_name: null terminated file name
1439 * The current position (uio_offset) refers to the next block of
1440 * entries. The offset will only be set to a value previously
1441 * returned by ufs_readdirext or zero. This offset does not have
1442 * to match the number of bytes returned (in uio_resid).
1444 #define EXT_DIRENT_LEN(namlen) \
1445 ((sizeof(struct direntry) + (namlen) - (MAXPATHLEN-1) + 3) & ~3)
1448 ufs_readdirext(vnode_t vp
, uio_t uio
, int *eofflag
, int *numdirent
,
1449 __unused vfs_context_t context
)
1453 off_t off
= uio
->uio_offset
;
1454 struct dirent
*dp
, *edp
;
1456 struct iovec_32 aiov
;
1458 struct direntry
*xdp
;
1461 // LP64todo - fix this
1462 count
= uio_resid(uio
);
1463 /* Make sure we don't return partial entries. */
1464 count
-= (uio
->uio_offset
+ count
) & (DIRBLKSIZ
-1);
1467 // LP64todo - fix this
1468 lost
= uio_resid(uio
) - count
;
1469 uio_setresid(uio
, count
);
1470 uio_iov_len_set(uio
, count
);
1473 auio
.uio_iovs
.iov32p
= &aiov
;
1474 auio
.uio_iovcnt
= 1;
1475 /* LP64todo - can't use new segment flags until the drivers are ready */
1476 auio
.uio_segflg
= UIO_SYSSPACE
;
1477 aiov
.iov_len
= count
;
1478 MALLOC(dirbuf
, caddr_t
, count
, M_TEMP
, M_WAITOK
);
1479 aiov
.iov_base
= (uintptr_t)dirbuf
;
1481 MALLOC(xdp
, struct direntry
*, sizeof(struct direntry
), M_TEMP
, M_WAITOK
);
1483 error
= ffs_read_internal(vp
, &auio
, 0);
1487 // LP64todo - fix this
1488 edp
= (struct dirent
*)&dirbuf
[count
- uio_resid(&auio
)];
1489 for (dp
= (struct dirent
*)dirbuf
; dp
< edp
; ) {
1491 #if (BYTE_ORDER == LITTLE_ENDIAN)
1495 dp
->d_namlen
= dp
->d_type
;
1498 xdp
->d_reclen
= EXT_DIRENT_LEN(dp
->d_namlen
);
1499 if (xdp
->d_reclen
> uio_resid(uio
)) {
1500 break; /* user buffer is full */
1502 xdp
->d_ino
= dp
->d_ino
;
1503 xdp
->d_namlen
= dp
->d_namlen
;
1504 xdp
->d_type
= dp
->d_type
;
1505 bcopy(dp
->d_name
, xdp
->d_name
, dp
->d_namlen
+ 1);
1506 off
+= dp
->d_reclen
;
1507 xdp
->d_seekoff
= off
;
1508 error
= uiomove((caddr_t
)xdp
, xdp
->d_reclen
, uio
);
1510 off
-= dp
->d_reclen
;
1511 break; /* unexpected this error is */
1515 if (dp
->d_reclen
> 0) {
1516 dp
= (struct dirent
*)
1517 ((char *)dp
+ dp
->d_reclen
);
1524 FREE(dirbuf
, M_TEMP
);
1527 /* Use the on-disk dirent offset */
1528 uio_setoffset(uio
, off
);
1529 *numdirent
= nentries
;
1530 uio_setresid(uio
, (uio_resid(uio
) + lost
));
1532 *eofflag
= (off_t
)VTOI(vp
)->i_size
<= uio
->uio_offset
;
1538 * Return target name of a symbolic link
1542 struct vnop_readlink_args
/* {
1545 vfs_context_t a_context;
1548 register struct vnode
*vp
= ap
->a_vp
;
1549 register struct inode
*ip
= VTOI(vp
);
1553 if (isize
< vp
->v_mount
->mnt_maxsymlinklen
) {
1554 uiomove((char *)ip
->i_shortlink
, isize
, ap
->a_uio
);
1557 return (ffs_read_internal(vp
, ap
->a_uio
, 0));
1561 * prepare and issue the I/O
1565 struct vnop_strategy_args
/* {
1569 buf_t bp
= ap
->a_bp
;
1570 vnode_t vp
= buf_vnode(bp
);
1571 struct inode
*ip
= VTOI(vp
);
1573 return (buf_strategy(ip
->i_devvp
, ap
));
1577 * Read wrapper for special devices.
1581 struct vnop_read_args
/* {
1585 vfs_context_t a_context;
1592 VTOI(ap
->a_vp
)->i_flag
|= IN_ACCESS
;
1593 return (VOCALL (spec_vnodeop_p
, VOFFSET(vnop_read
), ap
));
1597 * Write wrapper for special devices.
1601 struct vnop_write_args
/* {
1605 kauth_cred_t a_cred;
1610 * Set update and change flags.
1612 VTOI(ap
->a_vp
)->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1613 return (VOCALL (spec_vnodeop_p
, VOFFSET(vnop_write
), ap
));
1617 * Close wrapper for special devices.
1619 * Update the times on the inode then do device close.
1623 struct vnop_close_args
/* {
1626 vfs_context_t a_context;
1629 struct vnode
*vp
= ap
->a_vp
;
1630 struct inode
*ip
= VTOI(vp
);
1633 if (ap
->a_vp
->v_usecount
> 1) {
1635 ITIMES(ip
, &tv
, &tv
);
1637 return (VOCALL (spec_vnodeop_p
, VOFFSET(vnop_close
), ap
));
1642 * Read wrapper for fifo's
1646 struct vnop_read_args
/* {
1650 vfs_context_t a_context;
1653 extern int (**fifo_vnodeop_p
)(void *);
1658 VTOI(ap
->a_vp
)->i_flag
|= IN_ACCESS
;
1659 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vnop_read
), ap
));
1663 * Write wrapper for fifo's.
1667 struct vnop_write_args
/* {
1671 kauth_cred_t a_cred;
1674 extern int (**fifo_vnodeop_p
)(void *);
1677 * Set update and change flags.
1679 VTOI(ap
->a_vp
)->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1680 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vnop_write
), ap
));
1684 * Close wrapper for fifo's.
1686 * Update the times on the inode then do device close.
1690 struct vnop_close_args
/* {
1693 vfs_context_t a_context;
1696 extern int (**fifo_vnodeop_p
)(void *);
1697 struct vnode
*vp
= ap
->a_vp
;
1698 struct inode
*ip
= VTOI(vp
);
1701 if (ap
->a_vp
->v_usecount
> 1) {
1703 ITIMES(ip
, &tv
, &tv
);
1705 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vnop_close
), ap
));
1709 * kqfilt_add wrapper for fifos.
1711 * Fall through to ufs kqfilt_add routines if needed
1714 ufsfifo_kqfilt_add(ap
)
1715 struct vnop_kqfilt_add_args
*ap
;
1717 extern int (**fifo_vnodeop_p
)(void *);
1720 error
= VOCALL(fifo_vnodeop_p
, VOFFSET(vnop_kqfilt_add
), ap
);
1722 error
= ufs_kqfilt_add(ap
);
1728 * kqfilt_remove wrapper for fifos.
1730 * Fall through to ufs kqfilt_remove routines if needed
1733 ufsfifo_kqfilt_remove(ap
)
1734 struct vnop_kqfilt_remove_args
*ap
;
1736 extern int (**fifo_vnodeop_p
)(void *);
1739 error
= VOCALL(fifo_vnodeop_p
, VOFFSET(vnop_kqfilt_remove
), ap
);
1741 error
= ufs_kqfilt_remove(ap
);
1749 static struct filterops ufsread_filtops
=
1750 { 1, NULL
, filt_ufsdetach
, filt_ufsread
};
1751 static struct filterops ufswrite_filtops
=
1752 { 1, NULL
, filt_ufsdetach
, filt_ufswrite
};
1753 static struct filterops ufsvnode_filtops
=
1754 { 1, NULL
, filt_ufsdetach
, filt_ufsvnode
};
1758 #% kqfilt_add vp L L L
1761 IN struct vnode *vp;
1762 IN struct knote *kn;
1763 IN vfs_context_t context;
1767 struct vnop_kqfilt_add_args
/* {
1770 vfs_context_t a_context;
1773 struct vnode
*vp
= ap
->a_vp
;
1774 struct knote
*kn
= ap
->a_kn
;
1776 switch (kn
->kn_filter
) {
1778 kn
->kn_fop
= &ufsread_filtops
;
1781 kn
->kn_fop
= &ufswrite_filtops
;
1784 kn
->kn_fop
= &ufsvnode_filtops
;
1790 kn
->kn_hook
= (caddr_t
)vp
;
1791 kn
->kn_hookid
= vnode_vid(vp
);
1793 KNOTE_ATTACH(&VTOI(vp
)->i_knotes
, kn
);
1799 filt_ufsdetach(struct knote
*kn
)
1803 struct proc
*p
= current_proc();
1805 vp
= (struct vnode
*)kn
->kn_hook
;
1807 if (vnode_getwithvid(vp
, kn
->kn_hookid
))
1810 result
= KNOTE_DETACH(&VTOI(vp
)->i_knotes
, kn
);
1815 filt_ufsread(struct knote
*kn
, long hint
)
1817 struct vnode
*vp
= (struct vnode
*)kn
->kn_hook
;
1823 if ((vnode_getwithvid(vp
, kn
->kn_hookid
) != 0)) {
1828 if (hint
== NOTE_REVOKE
) {
1830 * filesystem is gone, so set the EOF flag and schedule
1831 * the knote for deletion.
1833 kn
->kn_flags
|= (EV_EOF
| EV_ONESHOT
);
1837 /* poll(2) semantics dictate always returning true */
1838 if (kn
->kn_flags
& EV_POLL
) {
1843 kn
->kn_data
= ip
->i_size
- kn
->kn_fp
->f_fglob
->fg_offset
;
1844 result
= (kn
->kn_data
!= 0);
1854 filt_ufswrite(struct knote
*kn
, long hint
)
1860 if ((vnode_getwithvid(kn
->kn_hook
, kn
->kn_hookid
) != 0)) {
1863 vnode_put(kn
->kn_hook
);
1865 if (hint
== NOTE_REVOKE
) {
1867 * filesystem is gone, so set the EOF flag and schedule
1868 * the knote for deletion.
1871 kn
->kn_flags
|= (EV_EOF
| EV_ONESHOT
);
1879 filt_ufsvnode(struct knote
*kn
, long hint
)
1883 if ((vnode_getwithvid(kn
->kn_hook
, kn
->kn_hookid
) != 0)) {
1886 vnode_put(kn
->kn_hook
);
1888 if (kn
->kn_sfflags
& hint
)
1889 kn
->kn_fflags
|= hint
;
1890 if ((hint
== NOTE_REVOKE
)) {
1891 kn
->kn_flags
|= (EV_EOF
| EV_ONESHOT
);
1895 return (kn
->kn_fflags
!= 0);
1899 * Return POSIX pathconf information applicable to ufs filesystems.
1903 struct vnop_pathconf_args
/* {
1907 vfs_context_t a_context;
1911 switch (ap
->a_name
) {
1913 *ap
->a_retval
= LINK_MAX
;
1916 *ap
->a_retval
= NAME_MAX
;
1919 *ap
->a_retval
= PATH_MAX
;
1922 *ap
->a_retval
= PIPE_BUF
;
1924 case _PC_CHOWN_RESTRICTED
:
1937 * Allocate a new inode.
1940 ufs_makeinode(vap
, dvp
, vpp
, cnp
)
1941 struct vnode_attr
*vap
;
1944 struct componentname
*cnp
;
1946 register struct inode
*ip
, *pdir
;
1953 mode
= MAKEIMODE(vap
->va_type
, vap
->va_mode
);
1956 if ((mode
& IFMT
) == 0)
1959 if ( (error
= ffs_valloc(dvp
, (mode_t
)mode
, vfs_context_ucred(cnp
->cn_context
), &tvp
)) )
1963 ip
->i_gid
= vap
->va_gid
;
1964 ip
->i_uid
= vap
->va_uid
;
1965 VATTR_SET_SUPPORTED(vap
, va_mode
);
1966 VATTR_SET_SUPPORTED(vap
, va_uid
);
1967 VATTR_SET_SUPPORTED(vap
, va_gid
);
1969 if ((error
= getinoquota(ip
)) ||
1970 (error
= chkiq(ip
, 1, vfs_context_ucred(cnp
->cn_context
), 0))) {
1971 ffs_vfree(tvp
, ip
->i_number
, mode
);
1976 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
1980 if (cnp
->cn_flags
& ISWHITEOUT
)
1981 ip
->i_flags
|= UF_OPAQUE
;
1984 * Make sure inode goes to disk before directory entry.
1987 if ( (error
= ffs_update(tvp
, &tv
, &tv
, 1)) )
1989 if ( (error
= ufs_direnter(ip
, dvp
, cnp
)) )
1997 * Write error occurred trying to update the inode
1998 * or the directory so must deallocate the inode.
2001 ip
->i_flag
|= IN_CHANGE
;