2 * Copyright (c) 2000 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>
74 #include <sys/mount.h>
75 #include <sys/vnode.h>
76 #include <sys/malloc.h>
77 #include <sys/dirent.h>
78 #include <sys/fcntl.h>
81 #include <kern/thread.h>
84 #include <miscfs/specfs/specdev.h>
86 #include <ufs/ufs/lockf.h>
87 #include <ufs/ufs/quota.h>
88 #include <ufs/ufs/inode.h>
89 #include <ufs/ufs/dir.h>
90 #include <ufs/ufs/ufsmount.h>
91 #include <ufs/ufs/ufs_extern.h>
94 #include <ufs/ufs/ufs_byte_order.h>
95 #include <architecture/byte_order.h>
96 #endif /* REV_ENDIAN_FS */
98 static int ufs_chmod
__P((struct vnode
*, int, struct ucred
*, struct proc
*));
100 __P((struct vnode
*, uid_t
, gid_t
, struct ucred
*, struct proc
*));
106 #define SETHIGH(q, h) { \
109 tmp.val[_QUAD_HIGHWORD] = (h); \
112 #define SETLOW(q, l) { \
115 tmp.val[_QUAD_LOWWORD] = (l); \
120 * Create a regular file
124 struct vop_create_args
/* {
126 struct vnode **a_vpp;
127 struct componentname *a_cnp;
134 ufs_makeinode(MAKEIMODE(ap
->a_vap
->va_type
, ap
->a_vap
->va_mode
),
135 ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
))
146 struct vop_mknod_args
/* {
148 struct vnode **a_vpp;
149 struct componentname *a_cnp;
153 struct vattr
*vap
= ap
->a_vap
;
154 struct vnode
**vpp
= ap
->a_vpp
;
159 ufs_makeinode(MAKEIMODE(vap
->va_type
, vap
->va_mode
),
160 ap
->a_dvp
, vpp
, ap
->a_cnp
))
163 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
164 if (vap
->va_rdev
!= VNOVAL
) {
166 * Want to be able to use this to make badblock
167 * inodes, so don't truncate the dev number.
169 ip
->i_rdev
= vap
->va_rdev
;
172 * Remove inode so that it will be reloaded by VFS_VGET and
173 * checked to see if it is an alias of an existing entry in
177 (*vpp
)->v_type
= VNON
;
191 struct vop_open_args
/* {
194 struct ucred *a_cred;
200 * Files marked append-only must be opened for appending.
202 if ((VTOI(ap
->a_vp
)->i_flags
& APPEND
) &&
203 (ap
->a_mode
& (FWRITE
| O_APPEND
)) == FWRITE
)
211 * Update the times on the inode.
216 struct vop_close_args
/* {
219 struct ucred *a_cred;
223 register struct vnode
*vp
= ap
->a_vp
;
224 register struct inode
*ip
= VTOI(vp
);
226 simple_lock(&vp
->v_interlock
);
227 if (vp
->v_usecount
> (UBCINFOEXISTS(vp
) ? 2 : 1))
228 ITIMES(ip
, &time
, &time
);
229 simple_unlock(&vp
->v_interlock
);
231 if (!VOP_ISLOCKED(vp
)) {
232 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, ap
->a_p
);
236 VOP_UNLOCK(vp
, 0, ap
->a_p
);
243 struct vop_access_args
/* {
246 struct ucred *a_cred;
250 struct vnode
*vp
= ap
->a_vp
;
251 struct inode
*ip
= VTOI(vp
);
252 struct ucred
*cred
= ap
->a_cred
;
253 mode_t mask
, mode
= ap
->a_mode
;
258 * Disallow write attempts on read-only file systems;
259 * unless the file is a socket, fifo, or a block or
260 * character device resident on the file system.
263 switch (vp
->v_type
) {
267 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
270 if (error
= getinoquota(ip
))
277 /* If immutable bit set, nobody gets to write it. */
278 if ((mode
& VWRITE
) && (ip
->i_flags
& IMMUTABLE
))
281 /* Otherwise, user id 0 always gets access. */
282 if (cred
->cr_uid
== 0)
287 /* Otherwise, check the owner. */
288 if (cred
->cr_uid
== ip
->i_uid
) {
295 return ((ip
->i_mode
& mask
) == mask
? 0 : EACCES
);
298 /* Otherwise, check the groups. */
299 for (i
= 0, gp
= cred
->cr_groups
; i
< cred
->cr_ngroups
; i
++, gp
++)
300 if (ip
->i_gid
== *gp
) {
307 return ((ip
->i_mode
& mask
) == mask
? 0 : EACCES
);
310 /* Otherwise, check everyone else. */
317 return ((ip
->i_mode
& mask
) == mask
? 0 : EACCES
);
323 struct vop_getattr_args
/* {
326 struct ucred *a_cred;
330 register struct vnode
*vp
= ap
->a_vp
;
331 register struct inode
*ip
= VTOI(vp
);
332 register struct vattr
*vap
= ap
->a_vap
;
335 ITIMES(ip
, &time
, &time
);
337 * Copy from inode table
339 vap
->va_fsid
= ip
->i_dev
;
340 vap
->va_fileid
= ip
->i_number
;
341 vap
->va_mode
= ip
->i_mode
& ~IFMT
;
342 vap
->va_nlink
= ip
->i_nlink
;
343 vap
->va_uid
= ip
->i_uid
;
344 vap
->va_gid
= ip
->i_gid
;
345 vap
->va_rdev
= (dev_t
)ip
->i_rdev
;
346 vap
->va_size
= ip
->i_din
.di_size
;
347 vap
->va_atime
.tv_sec
= ip
->i_atime
;
348 vap
->va_atime
.tv_nsec
= ip
->i_atimensec
;
349 vap
->va_mtime
.tv_sec
= ip
->i_mtime
;
350 vap
->va_mtime
.tv_nsec
= ip
->i_mtimensec
;
351 vap
->va_ctime
.tv_sec
= ip
->i_ctime
;
352 vap
->va_ctime
.tv_nsec
= ip
->i_ctimensec
;
353 vap
->va_flags
= ip
->i_flags
;
354 vap
->va_gen
= ip
->i_gen
;
355 /* this doesn't belong here */
356 if (vp
->v_type
== VBLK
)
357 vap
->va_blocksize
= BLKDEV_IOSIZE
;
358 else if (vp
->v_type
== VCHR
)
359 vap
->va_blocksize
= MAXPHYSIO
;
361 vap
->va_blocksize
= vp
->v_mount
->mnt_stat
.f_iosize
;
362 VOP_DEVBLOCKSIZE(ip
->i_devvp
, &devBlockSize
);
363 vap
->va_bytes
= dbtob((u_quad_t
)ip
->i_blocks
, devBlockSize
);
364 vap
->va_type
= vp
->v_type
;
365 vap
->va_filerev
= ip
->i_modrev
;
370 * Set attribute vnode op. called from several syscalls
374 struct vop_setattr_args
/* {
377 struct ucred *a_cred;
381 struct vattr
*vap
= ap
->a_vap
;
382 struct vnode
*vp
= ap
->a_vp
;
383 struct inode
*ip
= VTOI(vp
);
384 struct ucred
*cred
= ap
->a_cred
;
385 struct proc
*p
= ap
->a_p
;
386 struct timeval atimeval
, mtimeval
;
390 * Check for unsettable attributes.
392 if ((vap
->va_type
!= VNON
) || (vap
->va_nlink
!= VNOVAL
) ||
393 (vap
->va_fsid
!= VNOVAL
) || (vap
->va_fileid
!= VNOVAL
) ||
394 (vap
->va_blocksize
!= VNOVAL
) || (vap
->va_rdev
!= VNOVAL
) ||
395 ((int)vap
->va_bytes
!= VNOVAL
) || (vap
->va_gen
!= VNOVAL
)) {
398 if (vap
->va_flags
!= VNOVAL
) {
399 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
401 if (cred
->cr_uid
!= ip
->i_uid
&&
402 (error
= suser(cred
, &p
->p_acflag
)))
404 if (cred
->cr_uid
== 0) {
405 if ((ip
->i_flags
& (SF_IMMUTABLE
| SF_APPEND
)) &&
408 ip
->i_flags
= vap
->va_flags
;
410 if (ip
->i_flags
& (SF_IMMUTABLE
| SF_APPEND
) ||
411 (vap
->va_flags
& UF_SETTABLE
) != vap
->va_flags
)
413 ip
->i_flags
&= SF_SETTABLE
;
414 ip
->i_flags
|= (vap
->va_flags
& UF_SETTABLE
);
416 ip
->i_flag
|= IN_CHANGE
;
417 if (vap
->va_flags
& (IMMUTABLE
| APPEND
))
420 if (ip
->i_flags
& (IMMUTABLE
| APPEND
))
423 * Go through the fields and update iff not VNOVAL.
425 if (vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
) {
426 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
428 if (error
= ufs_chown(vp
, vap
->va_uid
, vap
->va_gid
, cred
, p
))
431 if (vap
->va_size
!= VNOVAL
) {
433 * Disallow write attempts on read-only file systems;
434 * unless the file is a socket, fifo, or a block or
435 * character device resident on the file system.
437 switch (vp
->v_type
) {
442 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
446 if (error
= VOP_TRUNCATE(vp
, vap
->va_size
, 0, cred
, p
))
450 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
451 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
453 if (cred
->cr_uid
!= ip
->i_uid
&&
454 (error
= suser(cred
, &p
->p_acflag
)) &&
455 ((vap
->va_vaflags
& VA_UTIMES_NULL
) == 0 ||
456 (error
= VOP_ACCESS(vp
, VWRITE
, cred
, p
))))
458 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
459 ip
->i_flag
|= IN_ACCESS
;
460 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
461 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
462 atimeval
.tv_sec
= vap
->va_atime
.tv_sec
;
463 atimeval
.tv_usec
= vap
->va_atime
.tv_nsec
/ 1000;
464 mtimeval
.tv_sec
= vap
->va_mtime
.tv_sec
;
465 mtimeval
.tv_usec
= vap
->va_mtime
.tv_nsec
/ 1000;
466 if (error
= VOP_UPDATE(vp
, &atimeval
, &mtimeval
, 1))
470 if (vap
->va_mode
!= (mode_t
)VNOVAL
) {
471 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
473 error
= ufs_chmod(vp
, (int)vap
->va_mode
, cred
, p
);
479 * Change the mode on a file.
480 * Inode must be locked before calling.
483 ufs_chmod(vp
, mode
, cred
, p
)
484 register struct vnode
*vp
;
486 register struct ucred
*cred
;
489 register struct inode
*ip
= VTOI(vp
);
492 if (cred
->cr_uid
!= ip
->i_uid
&&
493 (error
= suser(cred
, &p
->p_acflag
)))
496 if (vp
->v_type
!= VDIR
&& (mode
& S_ISTXT
))
498 if (!groupmember(ip
->i_gid
, cred
) && (mode
& ISGID
))
501 ip
->i_mode
&= ~ALLPERMS
;
502 ip
->i_mode
|= (mode
& ALLPERMS
);
503 ip
->i_flag
|= IN_CHANGE
;
508 * Perform chown operation on inode ip;
509 * inode must be locked prior to call.
512 ufs_chown(vp
, uid
, gid
, cred
, p
)
513 register struct vnode
*vp
;
519 register struct inode
*ip
= VTOI(vp
);
528 if (uid
== (uid_t
)VNOVAL
)
530 if (gid
== (gid_t
)VNOVAL
)
533 * If we don't own the file, are trying to change the owner
534 * of the file, or are not a member of the target group,
535 * the caller must be superuser or the call fails.
537 if ((cred
->cr_uid
!= ip
->i_uid
|| uid
!= ip
->i_uid
||
538 (gid
!= ip
->i_gid
&& !groupmember((gid_t
)gid
, cred
))) &&
539 (error
= suser(cred
, &p
->p_acflag
)))
544 if (error
= getinoquota(ip
))
547 dqrele(vp
, ip
->i_dquot
[USRQUOTA
]);
548 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
551 dqrele(vp
, ip
->i_dquot
[GRPQUOTA
]);
552 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
554 change
= ip
->i_blocks
;
555 (void) chkdq(ip
, -change
, cred
, CHOWN
);
556 (void) chkiq(ip
, -1, cred
, CHOWN
);
557 for (i
= 0; i
< MAXQUOTAS
; i
++) {
558 dqrele(vp
, ip
->i_dquot
[i
]);
559 ip
->i_dquot
[i
] = NODQUOT
;
565 if ((error
= getinoquota(ip
)) == 0) {
567 dqrele(vp
, ip
->i_dquot
[USRQUOTA
]);
568 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
571 dqrele(vp
, ip
->i_dquot
[GRPQUOTA
]);
572 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
574 if ((error
= chkdq(ip
, change
, cred
, CHOWN
)) == 0) {
575 if ((error
= chkiq(ip
, 1, cred
, CHOWN
)) == 0)
578 (void) chkdq(ip
, -change
, cred
, CHOWN
|FORCE
);
580 for (i
= 0; i
< MAXQUOTAS
; i
++) {
581 dqrele(vp
, ip
->i_dquot
[i
]);
582 ip
->i_dquot
[i
] = NODQUOT
;
587 if (getinoquota(ip
) == 0) {
589 dqrele(vp
, ip
->i_dquot
[USRQUOTA
]);
590 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
593 dqrele(vp
, ip
->i_dquot
[GRPQUOTA
]);
594 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
596 (void) chkdq(ip
, change
, cred
, FORCE
|CHOWN
);
597 (void) chkiq(ip
, 1, cred
, FORCE
|CHOWN
);
598 (void) getinoquota(ip
);
603 panic("chown: lost quota");
605 if (ouid
!= uid
|| ogid
!= gid
)
606 ip
->i_flag
|= IN_CHANGE
;
607 if (ouid
!= uid
&& cred
->cr_uid
!= 0)
608 ip
->i_mode
&= ~ISUID
;
609 if (ogid
!= gid
&& cred
->cr_uid
!= 0)
610 ip
->i_mode
&= ~ISGID
;
617 struct vop_ioctl_args
/* {
622 struct ucred *a_cred;
627 switch (ap
->a_command
) {
630 { register struct inode
*ip
;
631 register struct vnode
*vp
;
632 register struct fs
*fs
;
633 register struct radvisory
*ra
;
634 int devBlockSize
= 0;
639 VOP_LEASE(vp
, ap
->a_p
, ap
->a_cred
, LEASE_READ
);
640 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, ap
->a_p
);
642 ra
= (struct radvisory
*)(ap
->a_data
);
646 if ((u_int64_t
)ra
->ra_offset
>= ip
->i_size
) {
647 VOP_UNLOCK(vp
, 0, ap
->a_p
);
650 VOP_DEVBLOCKSIZE(ip
->i_devvp
, &devBlockSize
);
652 error
= advisory_read(vp
, ip
->i_size
, ra
->ra_offset
, ra
->ra_count
, devBlockSize
);
653 VOP_UNLOCK(vp
, 0, ap
->a_p
);
664 struct vop_select_args
/* {
668 struct ucred *a_cred;
675 * We should really check to see if I/O is possible.
683 * NB Currently unsupported.
688 struct vop_mmap_args
/* {
691 struct ucred *a_cred;
702 * Nothing to do, so just return.
707 struct vop_seek_args
/* {
711 struct ucred *a_cred;
720 struct vop_remove_args
/* {
723 struct componentname *a_cnp;
727 struct vnode
*vp
= ap
->a_vp
;
728 struct vnode
*dvp
= ap
->a_dvp
;
732 if ((ip
->i_flags
& (IMMUTABLE
| APPEND
)) ||
733 (VTOI(dvp
)->i_flags
& APPEND
)) {
737 if ((vp
->v_usecount
> (UBCINFOEXISTS(vp
) ? 2 : 1)) &&
738 (ap
->a_cnp
->cn_flags
& NODELETEBUSY
)) {
739 /* Carbon and Classic clients can't delete busy files */
743 if ((error
= ufs_dirremove(dvp
, ap
->a_cnp
)) == 0) {
745 ip
->i_flag
|= IN_CHANGE
;
749 VOP_UNLOCK(vp
, 0, ap
->a_cnp
->cn_proc
);
751 (void) ubc_uncache(vp
);
772 struct vop_link_args
/* {
774 struct vnode *a_tdvp;
775 struct componentname *a_cnp;
778 struct vnode
*vp
= ap
->a_vp
;
779 struct vnode
*tdvp
= ap
->a_tdvp
;
780 struct componentname
*cnp
= ap
->a_cnp
;
781 struct proc
*p
= cnp
->cn_proc
;
787 if ((cnp
->cn_flags
& HASBUF
) == 0)
788 panic("ufs_link: no name");
790 if (tdvp
->v_mount
!= vp
->v_mount
) {
791 VOP_ABORTOP(tdvp
, cnp
);
795 if (tdvp
!= vp
&& (error
= vn_lock(vp
, LK_EXCLUSIVE
, p
))) {
796 VOP_ABORTOP(tdvp
, cnp
);
800 if ((nlink_t
)ip
->i_nlink
>= LINK_MAX
) {
801 VOP_ABORTOP(tdvp
, cnp
);
805 if (ip
->i_flags
& (IMMUTABLE
| APPEND
)) {
806 VOP_ABORTOP(tdvp
, cnp
);
811 ip
->i_flag
|= IN_CHANGE
;
813 error
= VOP_UPDATE(vp
, &tv
, &tv
, 1);
815 error
= ufs_direnter(ip
, tdvp
, cnp
);
818 ip
->i_flag
|= IN_CHANGE
;
820 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
823 VOP_UNLOCK(vp
, 0, p
);
830 * whiteout vnode call
834 struct vop_whiteout_args
/* {
836 struct componentname *a_cnp;
840 struct vnode
*dvp
= ap
->a_dvp
;
841 struct componentname
*cnp
= ap
->a_cnp
;
842 struct direct newdir
;
845 switch (ap
->a_flags
) {
847 /* 4.4 format directories support whiteout operations */
848 if (dvp
->v_mount
->mnt_maxsymlinklen
> 0)
853 /* create a new directory whiteout */
855 if ((cnp
->cn_flags
& SAVENAME
) == 0)
856 panic("ufs_whiteout: missing name");
857 if (dvp
->v_mount
->mnt_maxsymlinklen
<= 0)
858 panic("ufs_whiteout: old format filesystem");
862 newdir
.d_namlen
= cnp
->cn_namelen
;
863 bcopy(cnp
->cn_nameptr
, newdir
.d_name
, (unsigned)cnp
->cn_namelen
+ 1);
864 newdir
.d_type
= DT_WHT
;
865 error
= ufs_direnter2(dvp
, &newdir
, cnp
->cn_cred
, cnp
->cn_proc
);
869 /* remove an existing directory whiteout */
871 if (dvp
->v_mount
->mnt_maxsymlinklen
<= 0)
872 panic("ufs_whiteout: old format filesystem");
875 cnp
->cn_flags
&= ~DOWHITEOUT
;
876 error
= ufs_dirremove(dvp
, cnp
);
879 if (cnp
->cn_flags
& HASBUF
) {
880 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
881 cnp
->cn_flags
&= ~HASBUF
;
888 * Rename system call.
889 * rename("foo", "bar");
892 * link("foo", "bar");
894 * but ``atomically''. Can't do full commit without saving state in the
895 * inode on disk which isn't feasible at this time. Best we can do is
896 * always guarantee the target exists.
898 * Basic algorithm is:
900 * 1) Bump link count on source while we're linking it to the
901 * target. This also ensure the inode won't be deleted out
902 * from underneath us while we work (it may be truncated by
903 * a concurrent `trunc' or `open' for creation).
904 * 2) Link source to destination. If destination already exists,
906 * 3) Unlink source reference to inode if still around. If a
907 * directory was moved and the parent of the destination
908 * is different from the source, patch the ".." entry in the
913 struct vop_rename_args
/* {
914 struct vnode *a_fdvp;
916 struct componentname *a_fcnp;
917 struct vnode *a_tdvp;
919 struct componentname *a_tcnp;
922 struct vnode
*tvp
= ap
->a_tvp
;
923 register struct vnode
*tdvp
= ap
->a_tdvp
;
924 struct vnode
*fvp
= ap
->a_fvp
;
925 struct vnode
*fdvp
= ap
->a_fdvp
;
926 struct componentname
*tcnp
= ap
->a_tcnp
;
927 struct componentname
*fcnp
= ap
->a_fcnp
;
928 struct proc
*p
= fcnp
->cn_proc
;
929 struct inode
*ip
, *xp
, *dp
;
930 struct dirtemplate dirbuf
;
932 int doingdirectory
= 0, oldparent
= 0, newparent
= 0;
937 if ((tcnp
->cn_flags
& HASBUF
) == 0 ||
938 (fcnp
->cn_flags
& HASBUF
) == 0)
939 panic("ufs_rename: no name");
942 * Check for cross-device rename.
944 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
945 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
948 VOP_ABORTOP(tdvp
, tcnp
); /* XXX, why not in NFS? */
955 VOP_ABORTOP(fdvp
, fcnp
); /* XXX, why not in NFS? */
962 * Check if just deleting a link name.
964 if (tvp
&& ((VTOI(tvp
)->i_flags
& (IMMUTABLE
| APPEND
)) ||
965 (VTOI(tdvp
)->i_flags
& APPEND
))) {
970 if (fvp
->v_type
== VDIR
) {
975 /* Release destination completely. */
976 VOP_ABORTOP(tdvp
, tcnp
);
983 fcnp
->cn_flags
&= ~MODMASK
;
984 fcnp
->cn_flags
|= LOCKPARENT
| LOCKLEAF
;
985 if ((fcnp
->cn_flags
& SAVESTART
) == 0)
986 panic("ufs_rename: lost from startdir");
987 fcnp
->cn_nameiop
= DELETE
;
988 (void) relookup(fdvp
, &fvp
, fcnp
);
989 return (VOP_REMOVE(fdvp
, fvp
, fcnp
));
991 if (error
= vn_lock(fvp
, LK_EXCLUSIVE
, p
))
995 if ((ip
->i_flags
& (IMMUTABLE
| APPEND
)) || (dp
->i_flags
& APPEND
)) {
996 VOP_UNLOCK(fvp
, 0, p
);
1000 if ((ip
->i_mode
& IFMT
) == IFDIR
) {
1002 * Avoid ".", "..", and aliases of "." for obvious reasons.
1004 if ((fcnp
->cn_namelen
== 1 && fcnp
->cn_nameptr
[0] == '.') ||
1005 dp
== ip
|| (fcnp
->cn_flags
&ISDOTDOT
) ||
1006 (ip
->i_flag
& IN_RENAME
)) {
1007 VOP_UNLOCK(fvp
, 0, p
);
1011 ip
->i_flag
|= IN_RENAME
;
1012 oldparent
= dp
->i_number
;
1018 * When the target exists, both the directory
1019 * and target vnodes are returned locked.
1027 * 1) Bump link count while we're moving stuff
1028 * around. If we crash somewhere before
1029 * completing our work, the link count
1030 * may be wrong, but correctable.
1033 ip
->i_flag
|= IN_CHANGE
;
1035 if (error
= VOP_UPDATE(fvp
, &tv
, &tv
, 1)) {
1036 VOP_UNLOCK(fvp
, 0, p
);
1041 * If ".." must be changed (ie the directory gets a new
1042 * parent) then the source directory must not be in the
1043 * directory heirarchy above the target, as this would
1044 * orphan everything below the source directory. Also
1045 * the user must have write permission in the source so
1046 * as to be able to change "..". We must repeat the call
1047 * to namei, as the parent directory is unlocked by the
1048 * call to checkpath().
1050 error
= VOP_ACCESS(fvp
, VWRITE
, tcnp
->cn_cred
, tcnp
->cn_proc
);
1051 VOP_UNLOCK(fvp
, 0, p
);
1052 if (oldparent
!= dp
->i_number
)
1053 newparent
= dp
->i_number
;
1054 if (doingdirectory
&& newparent
) {
1055 if (error
) /* write access check above */
1059 if (error
= ufs_checkpath(ip
, dp
, tcnp
->cn_cred
))
1061 if ((tcnp
->cn_flags
& SAVESTART
) == 0)
1062 panic("ufs_rename: lost to startdir");
1063 if (error
= relookup(tdvp
, &tvp
, tcnp
))
1071 * 2) If target doesn't exist, link the target
1072 * to the source and unlink the source.
1073 * Otherwise, rewrite the target directory
1074 * entry to reference the source inode and
1075 * expunge the original entry's existence.
1078 if (dp
->i_dev
!= ip
->i_dev
)
1079 panic("rename: EXDEV");
1081 * Account for ".." in new directory.
1082 * When source and destination have the same
1083 * parent we don't fool with the link count.
1085 if (doingdirectory
&& newparent
) {
1086 if ((nlink_t
)dp
->i_nlink
>= LINK_MAX
) {
1091 dp
->i_flag
|= IN_CHANGE
;
1092 if (error
= VOP_UPDATE(tdvp
, &tv
, &tv
, 1))
1095 if (error
= ufs_direnter(ip
, tdvp
, tcnp
)) {
1096 if (doingdirectory
&& newparent
) {
1098 dp
->i_flag
|= IN_CHANGE
;
1099 (void)VOP_UPDATE(tdvp
, &tv
, &tv
, 1);
1105 if (xp
->i_dev
!= dp
->i_dev
|| xp
->i_dev
!= ip
->i_dev
)
1106 panic("rename: EXDEV");
1108 * Short circuit rename(foo, foo).
1110 if (xp
->i_number
== ip
->i_number
)
1111 panic("rename: same file");
1113 * If the parent directory is "sticky", then the user must
1114 * own the parent directory, or the destination of the rename,
1115 * otherwise the destination may not be changed (except by
1116 * root). This implements append-only directories.
1118 if ((dp
->i_mode
& S_ISTXT
) && tcnp
->cn_cred
->cr_uid
!= 0 &&
1119 tcnp
->cn_cred
->cr_uid
!= dp
->i_uid
&&
1120 xp
->i_uid
!= tcnp
->cn_cred
->cr_uid
) {
1125 * Target must be empty if a directory and have no links
1126 * to it. Also, ensure source and target are compatible
1127 * (both directories, or both not directories).
1129 if ((xp
->i_mode
&IFMT
) == IFDIR
) {
1130 if (!ufs_dirempty(xp
, dp
->i_number
, tcnp
->cn_cred
) ||
1135 if (!doingdirectory
) {
1140 } else if (doingdirectory
) {
1144 if (error
= ufs_dirrewrite(dp
, ip
, tcnp
))
1147 * If the target directory is in the same
1148 * directory as the source directory,
1149 * decrement the link count on the parent
1150 * of the target directory.
1152 if (doingdirectory
&& !newparent
) {
1154 dp
->i_flag
|= IN_CHANGE
;
1158 * Adjust the link count of the target to
1159 * reflect the dirrewrite above. If this is
1160 * a directory it is empty and there are
1161 * no links to it, so we can squash the inode and
1162 * any space associated with it. We disallowed
1163 * renaming over top of a directory with links to
1164 * it above, as the remaining link would point to
1165 * a directory without "." or ".." entries.
1168 if (doingdirectory
) {
1169 if (--xp
->i_nlink
!= 0)
1170 panic("rename: linked directory");
1171 error
= VOP_TRUNCATE(tvp
, (off_t
)0, IO_SYNC
,
1172 tcnp
->cn_cred
, tcnp
->cn_proc
);
1174 xp
->i_flag
|= IN_CHANGE
;
1180 * 3) Unlink the source.
1182 fcnp
->cn_flags
&= ~MODMASK
;
1183 fcnp
->cn_flags
|= LOCKPARENT
| LOCKLEAF
;
1184 if ((fcnp
->cn_flags
& SAVESTART
) == 0)
1185 panic("ufs_rename: lost from startdir");
1186 (void) relookup(fdvp
, &fvp
, fcnp
);
1192 * From name has disappeared.
1195 panic("rename: lost dir entry");
1200 * Ensure that the directory entry still exists and has not
1201 * changed while the new name has been entered. If the source is
1202 * a file then the entry may have been unlinked or renamed. In
1203 * either case there is no further work to be done. If the source
1204 * is a directory then it cannot have been rmdir'ed; its link
1205 * count of three would cause a rmdir to fail with ENOTEMPTY.
1206 * The IRENAME flag ensures that it cannot be moved by another
1211 panic("rename: lost dir entry");
1214 * If the source is a directory with a
1215 * new parent, the link count of the old
1216 * parent directory must be decremented
1217 * and ".." set to point to the new parent.
1219 if (doingdirectory
&& newparent
) {
1221 dp
->i_flag
|= IN_CHANGE
;
1222 error
= vn_rdwr(UIO_READ
, fvp
, (caddr_t
)&dirbuf
,
1223 sizeof (struct dirtemplate
), (off_t
)0,
1224 UIO_SYSSPACE
, IO_NODELOCKED
,
1225 tcnp
->cn_cred
, (int *)0, (struct proc
*)0);
1227 # if (BYTE_ORDER == LITTLE_ENDIAN)
1228 if (fvp
->v_mount
->mnt_maxsymlinklen
<= 0)
1229 namlen
= dirbuf
.dotdot_type
;
1231 namlen
= dirbuf
.dotdot_namlen
;
1233 namlen
= dirbuf
.dotdot_namlen
;
1236 dirbuf
.dotdot_name
[0] != '.' ||
1237 dirbuf
.dotdot_name
[1] != '.') {
1238 ufs_dirbad(xp
, (doff_t
)12,
1239 "rename: mangled dir");
1241 dirbuf
.dotdot_ino
= newparent
;
1242 (void) vn_rdwr(UIO_WRITE
, fvp
,
1244 sizeof (struct dirtemplate
),
1245 (off_t
)0, UIO_SYSSPACE
,
1246 IO_NODELOCKED
|IO_SYNC
,
1247 tcnp
->cn_cred
, (int *)0,
1253 error
= ufs_dirremove(fdvp
, fcnp
);
1256 xp
->i_flag
|= IN_CHANGE
;
1258 xp
->i_flag
&= ~IN_RENAME
;
1273 ip
->i_flag
&= ~IN_RENAME
;
1274 if (vn_lock(fvp
, LK_EXCLUSIVE
, p
) == 0) {
1276 ip
->i_flag
|= IN_CHANGE
;
1284 * A virgin directory (no blushing please).
1286 static struct dirtemplate mastertemplate
= {
1287 0, 12, DT_DIR
, 1, ".",
1288 0, DIRBLKSIZ
- 12, DT_DIR
, 2, ".."
1290 static struct odirtemplate omastertemplate
= {
1292 0, DIRBLKSIZ
- 12, 2, ".."
1300 struct vop_mkdir_args
/* {
1301 struct vnode *a_dvp;
1302 struct vnode **a_vpp;
1303 struct componentname *a_cnp;
1304 struct vattr *a_vap;
1307 register struct vnode
*dvp
= ap
->a_dvp
;
1308 register struct vattr
*vap
= ap
->a_vap
;
1309 register struct componentname
*cnp
= ap
->a_cnp
;
1310 register struct inode
*ip
, *dp
;
1312 struct dirtemplate dirtemplate
, *dtp
;
1317 if ((cnp
->cn_flags
& HASBUF
) == 0)
1318 panic("ufs_mkdir: no name");
1321 if ((nlink_t
)dp
->i_nlink
>= LINK_MAX
) {
1325 dmode
= vap
->va_mode
& 0777;
1328 * Must simulate part of ufs_makeinode here to acquire the inode,
1329 * but not have it entered in the parent directory. The entry is
1330 * made later after writing "." and ".." entries.
1332 if (error
= VOP_VALLOC(dvp
, dmode
, cnp
->cn_cred
, &tvp
))
1335 ip
->i_uid
= cnp
->cn_cred
->cr_uid
;
1336 ip
->i_gid
= dp
->i_gid
;
1338 if ((error
= getinoquota(ip
)) ||
1339 (error
= chkiq(ip
, 1, cnp
->cn_cred
, 0))) {
1340 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1341 VOP_VFREE(tvp
, ip
->i_number
, dmode
);
1347 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
1349 tvp
->v_type
= VDIR
; /* Rest init'd in getnewvnode(). */
1351 if (cnp
->cn_flags
& ISWHITEOUT
)
1352 ip
->i_flags
|= UF_OPAQUE
;
1354 error
= VOP_UPDATE(tvp
, &tv
, &tv
, 1);
1357 * Bump link count in parent directory
1358 * to reflect work done below. Should
1359 * be done before reference is created
1360 * so reparation is possible if we crash.
1363 dp
->i_flag
|= IN_CHANGE
;
1364 if (error
= VOP_UPDATE(dvp
, &tv
, &tv
, 1))
1367 /* Initialize directory with "." and ".." from static template. */
1368 if (dvp
->v_mount
->mnt_maxsymlinklen
> 0)
1369 dtp
= &mastertemplate
;
1371 dtp
= (struct dirtemplate
*)&omastertemplate
;
1373 dirtemplate
.dot_ino
= ip
->i_number
;
1374 dirtemplate
.dotdot_ino
= dp
->i_number
;
1375 error
= vn_rdwr(UIO_WRITE
, tvp
, (caddr_t
)&dirtemplate
,
1376 sizeof (dirtemplate
), (off_t
)0, UIO_SYSSPACE
,
1377 IO_NODELOCKED
|IO_SYNC
, cnp
->cn_cred
, (int *)0, (struct proc
*)0);
1380 dp
->i_flag
|= IN_CHANGE
;
1383 if (DIRBLKSIZ
> VFSTOUFS(dvp
->v_mount
)->um_mountp
->mnt_stat
.f_bsize
)
1384 panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
1386 ip
->i_size
= DIRBLKSIZ
;
1387 ip
->i_flag
|= IN_CHANGE
;
1390 /* Directory set up, now install it's entry in the parent directory. */
1391 if (error
= ufs_direnter(ip
, dvp
, cnp
)) {
1393 dp
->i_flag
|= IN_CHANGE
;
1397 * No need to do an explicit VOP_TRUNCATE here, vrele will do this
1398 * for us because we set the link count to 0.
1402 ip
->i_flag
|= IN_CHANGE
;
1407 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1413 * Rmdir system call.
1417 struct vop_rmdir_args
/* {
1418 struct vnode *a_dvp;
1420 struct componentname *a_cnp;
1423 struct vnode
*vp
= ap
->a_vp
;
1424 struct vnode
*dvp
= ap
->a_dvp
;
1425 struct componentname
*cnp
= ap
->a_cnp
;
1426 struct inode
*ip
, *dp
;
1432 * No rmdir "." please.
1440 * Verify the directory is empty (and valid).
1441 * (Rmdir ".." won't be valid since
1442 * ".." will contain a reference to
1443 * the current directory and thus be
1447 if (ip
->i_nlink
!= 2 ||
1448 !ufs_dirempty(ip
, dp
->i_number
, cnp
->cn_cred
)) {
1452 if ((dp
->i_flags
& APPEND
) || (ip
->i_flags
& (IMMUTABLE
| APPEND
))) {
1457 * Delete reference to directory before purging
1458 * inode. If we crash in between, the directory
1459 * will be reattached to lost+found,
1461 if (error
= ufs_dirremove(dvp
, cnp
))
1464 dp
->i_flag
|= IN_CHANGE
;
1469 * Truncate inode. The only stuff left
1470 * in the directory is "." and "..". The
1471 * "." reference is inconsequential since
1472 * we're quashing it. The ".." reference
1473 * has already been adjusted above. We've
1474 * removed the "." reference and the reference
1475 * in the parent directory, but there may be
1476 * other hard links so decrement by 2 and
1477 * worry about them later.
1480 error
= VOP_TRUNCATE(vp
, (off_t
)0, IO_SYNC
, cnp
->cn_cred
,
1482 cache_purge(ITOV(ip
));
1491 * symlink -- make a symbolic link
1495 struct vop_symlink_args
/* {
1496 struct vnode *a_dvp;
1497 struct vnode **a_vpp;
1498 struct componentname *a_cnp;
1499 struct vattr *a_vap;
1503 register struct vnode
*vp
, **vpp
= ap
->a_vpp
;
1504 register struct inode
*ip
;
1507 if (error
= ufs_makeinode(IFLNK
| ap
->a_vap
->va_mode
, ap
->a_dvp
,
1511 len
= strlen(ap
->a_target
);
1512 if (len
< vp
->v_mount
->mnt_maxsymlinklen
) {
1514 bcopy(ap
->a_target
, (char *)ip
->i_shortlink
, len
);
1516 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1518 error
= vn_rdwr(UIO_WRITE
, vp
, ap
->a_target
, len
, (off_t
)0,
1519 UIO_SYSSPACE
, IO_NODELOCKED
, ap
->a_cnp
->cn_cred
, (int *)0,
1526 * Vnode op for reading directories.
1528 * The routine below assumes that the on-disk format of a directory
1529 * is the same as that defined by <sys/dirent.h>. If the on-disk
1530 * format changes, then it will be necessary to do a conversion
1531 * from the on-disk format that read returns to the format defined
1532 * by <sys/dirent.h>.
1536 struct vop_readdir_args
/* {
1539 struct ucred *a_cred;
1545 register struct uio
*uio
= ap
->a_uio
;
1548 off_t off
= uio
->uio_offset
;
1550 count
= uio
->uio_resid
;
1551 /* Make sure we don't return partial entries. */
1552 count
-= (uio
->uio_offset
+ count
) & (DIRBLKSIZ
-1);
1555 lost
= uio
->uio_resid
- count
;
1556 uio
->uio_resid
= count
;
1557 uio
->uio_iov
->iov_len
= count
;
1558 # if (BYTE_ORDER == LITTLE_ENDIAN)
1559 if (ap
->a_vp
->v_mount
->mnt_maxsymlinklen
> 0) {
1560 error
= VOP_READ(ap
->a_vp
, uio
, 0, ap
->a_cred
);
1562 struct dirent
*dp
, *edp
;
1570 auio
.uio_iov
= &aiov
;
1571 auio
.uio_iovcnt
= 1;
1572 auio
.uio_segflg
= UIO_SYSSPACE
;
1573 aiov
.iov_len
= count
;
1574 MALLOC(dirbuf
, caddr_t
, count
, M_TEMP
, M_WAITOK
);
1575 aiov
.iov_base
= dirbuf
;
1576 error
= VOP_READ(ap
->a_vp
, &auio
, 0, ap
->a_cred
);
1578 readcnt
= count
- auio
.uio_resid
;
1579 edp
= (struct dirent
*)&dirbuf
[readcnt
];
1580 for (dp
= (struct dirent
*)dirbuf
; dp
< edp
; ) {
1582 dp
->d_namlen
= dp
->d_type
;
1584 if (dp
->d_reclen
> 0) {
1585 dp
= (struct dirent
*)
1586 ((char *)dp
+ dp
->d_reclen
);
1593 error
= uiomove(dirbuf
, readcnt
, uio
);
1595 FREE(dirbuf
, M_TEMP
);
1598 error
= VOP_READ(ap
->a_vp
, uio
, 0, ap
->a_cred
);
1600 if (!error
&& ap
->a_ncookies
!= NULL
) {
1601 struct dirent
* dpStart
;
1602 struct dirent
* dpEnd
;
1609 * Only the NFS server uses cookies, and it loads the
1610 * directory block into system space, so we can just look at
1613 if (uio
->uio_segflg
!= UIO_SYSSPACE
|| uio
->uio_iovcnt
!= 1)
1614 panic("ufs_readdir: unexpected uio from NFS server");
1615 dpStart
= (struct dirent
*)
1616 (uio
->uio_iov
->iov_base
- (uio
->uio_offset
- off
));
1617 dpEnd
= (struct dirent
*) uio
->uio_iov
->iov_base
;
1618 for (dp
= dpStart
, ncookies
= 0;
1619 dp
< dpEnd
&& dp
->d_reclen
!= 0;
1620 dp
= (struct dirent
*)((caddr_t
)dp
+ dp
->d_reclen
))
1622 MALLOC(cookies
, u_long
*, ncookies
* sizeof(u_long
), M_TEMP
,
1624 for (dp
= dpStart
, cookiep
= cookies
;
1626 dp
= (struct dirent
*)((caddr_t
) dp
+ dp
->d_reclen
)) {
1627 off
+= dp
->d_reclen
;
1628 *cookiep
++ = (u_long
) off
;
1630 *ap
->a_ncookies
= ncookies
;
1631 *ap
->a_cookies
= cookies
;
1633 uio
->uio_resid
+= lost
;
1635 *ap
->a_eofflag
= VTOI(ap
->a_vp
)->i_size
<= uio
->uio_offset
;
1640 * Return target name of a symbolic link
1644 struct vop_readlink_args
/* {
1647 struct ucred *a_cred;
1650 register struct vnode
*vp
= ap
->a_vp
;
1651 register struct inode
*ip
= VTOI(vp
);
1655 if (isize
< vp
->v_mount
->mnt_maxsymlinklen
) {
1656 uiomove((char *)ip
->i_shortlink
, isize
, ap
->a_uio
);
1659 return (VOP_READ(vp
, ap
->a_uio
, 0, ap
->a_cred
));
1663 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
1664 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
1669 struct vop_abortop_args
/* {
1670 struct vnode *a_dvp;
1671 struct componentname *a_cnp;
1674 if ((ap
->a_cnp
->cn_flags
& (HASBUF
| SAVESTART
)) == HASBUF
)
1675 FREE_ZONE(ap
->a_cnp
->cn_pnbuf
, ap
->a_cnp
->cn_pnlen
, M_NAMEI
);
1680 * Lock an inode. If its already locked, set the WANT bit and sleep.
1684 struct vop_lock_args
/* {
1690 struct vnode
*vp
= ap
->a_vp
;
1692 if (VTOI(vp
) == (struct inode
*)NULL
)
1693 panic("inode in vnode is null\n");
1694 return (lockmgr(&VTOI(vp
)->i_lock
, ap
->a_flags
, &vp
->v_interlock
,
1703 struct vop_unlock_args
/* {
1709 struct vnode
*vp
= ap
->a_vp
;
1711 return (lockmgr(&VTOI(vp
)->i_lock
, ap
->a_flags
| LK_RELEASE
,
1712 &vp
->v_interlock
, ap
->a_p
));
1716 * Check for a locked inode.
1720 struct vop_islocked_args
/* {
1725 return (lockstatus(&VTOI(ap
->a_vp
)->i_lock
));
1729 * Calculate the logical to physical mapping if not done already,
1730 * then call the device strategy routine.
1734 struct vop_strategy_args
/* {
1738 register struct buf
*bp
= ap
->a_bp
;
1739 register struct vnode
*vp
= bp
->b_vp
;
1740 register struct inode
*ip
;
1744 if ( !(bp
->b_flags
& B_VECTORLIST
)) {
1745 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
1746 panic("ufs_strategy: spec");
1749 if (bp
->b_flags
& B_PAGELIST
) {
1751 * if we have a page list associated with this bp,
1752 * then go through cluste_bp since it knows how to
1753 * deal with a page request that might span non-contiguous
1754 * physical blocks on the disk...
1757 if (bp
->b_blkno
== bp
->b_lblkno
) {
1758 if (error
= VOP_BMAP(vp
, bp
->b_lblkno
, NULL
,
1759 &bp
->b_blkno
, NULL
)) {
1760 bp
->b_error
= error
;
1761 bp
->b_flags
|= B_ERROR
;
1767 error
= cluster_bp(bp
);
1769 bp
->b_dev
= vp
->v_rdev
;
1774 if (bp
->b_blkno
== bp
->b_lblkno
) {
1776 VOP_BMAP(vp
, bp
->b_lblkno
, NULL
, &bp
->b_blkno
, NULL
)) {
1777 bp
->b_error
= error
;
1778 bp
->b_flags
|= B_ERROR
;
1782 if ((long)bp
->b_blkno
== -1)
1785 if ((long)bp
->b_blkno
== -1) {
1793 bp
->b_dev
= vp
->v_rdev
;
1794 VOCALL (vp
->v_op
, VOFFSET(vop_strategy
), ap
);
1799 * Print out the contents of an inode.
1803 struct vop_print_args
/* {
1807 register struct vnode
*vp
= ap
->a_vp
;
1808 register struct inode
*ip
= VTOI(vp
);
1810 printf("tag VT_UFS, ino %d, on dev %d, %d", ip
->i_number
,
1811 major(ip
->i_dev
), minor(ip
->i_dev
));
1813 if (vp
->v_type
== VFIFO
)
1816 lockmgr_printinfo(&ip
->i_lock
);
1822 * Read wrapper for special devices.
1826 struct vop_read_args
/* {
1830 struct ucred *a_cred;
1837 VTOI(ap
->a_vp
)->i_flag
|= IN_ACCESS
;
1838 return (VOCALL (spec_vnodeop_p
, VOFFSET(vop_read
), ap
));
1842 * Write wrapper for special devices.
1846 struct vop_write_args
/* {
1850 struct ucred *a_cred;
1855 * Set update and change flags.
1857 VTOI(ap
->a_vp
)->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1858 return (VOCALL (spec_vnodeop_p
, VOFFSET(vop_write
), ap
));
1862 * Close wrapper for special devices.
1864 * Update the times on the inode then do device close.
1868 struct vop_close_args
/* {
1871 struct ucred *a_cred;
1875 struct vnode
*vp
= ap
->a_vp
;
1876 struct inode
*ip
= VTOI(vp
);
1878 simple_lock(&vp
->v_interlock
);
1879 if (ap
->a_vp
->v_usecount
> 1)
1880 ITIMES(ip
, &time
, &time
);
1881 simple_unlock(&vp
->v_interlock
);
1882 return (VOCALL (spec_vnodeop_p
, VOFFSET(vop_close
), ap
));
1887 * Read wrapper for fifo's
1891 struct vop_read_args
/* {
1895 struct ucred *a_cred;
1898 extern int (**fifo_vnodeop_p
)(void *);
1903 VTOI(ap
->a_vp
)->i_flag
|= IN_ACCESS
;
1904 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vop_read
), ap
));
1908 * Write wrapper for fifo's.
1912 struct vop_write_args
/* {
1916 struct ucred *a_cred;
1919 extern int (**fifo_vnodeop_p
)(void *);
1922 * Set update and change flags.
1924 VTOI(ap
->a_vp
)->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1925 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vop_write
), ap
));
1929 * Close wrapper for fifo's.
1931 * Update the times on the inode then do device close.
1934 struct vop_close_args
/* {
1937 struct ucred *a_cred;
1941 extern int (**fifo_vnodeop_p
)(void *);
1942 struct vnode
*vp
= ap
->a_vp
;
1943 struct inode
*ip
= VTOI(vp
);
1945 simple_lock(&vp
->v_interlock
);
1946 if (ap
->a_vp
->v_usecount
> 1)
1947 ITIMES(ip
, &time
, &time
);
1948 simple_unlock(&vp
->v_interlock
);
1949 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vop_close
), ap
));
1954 * Return POSIX pathconf information applicable to ufs filesystems.
1957 struct vop_pathconf_args
/* {
1964 switch (ap
->a_name
) {
1966 *ap
->a_retval
= LINK_MAX
;
1969 *ap
->a_retval
= NAME_MAX
;
1972 *ap
->a_retval
= PATH_MAX
;
1975 *ap
->a_retval
= PIPE_BUF
;
1977 case _PC_CHOWN_RESTRICTED
:
1990 * Advisory record locking support
1994 struct vop_advlock_args
/* {
2002 register struct inode
*ip
= VTOI(ap
->a_vp
);
2003 register struct flock
*fl
= ap
->a_fl
;
2004 register struct lockf
*lock
;
2009 * Avoid the common case of unlocking when inode has no locks.
2011 if (ip
->i_lockf
== (struct lockf
*)0) {
2012 if (ap
->a_op
!= F_SETLK
) {
2013 fl
->l_type
= F_UNLCK
;
2018 * Convert the flock structure into a start and end.
2020 switch (fl
->l_whence
) {
2025 * Caller is responsible for adding any necessary offset
2026 * when SEEK_CUR is used.
2028 start
= fl
->l_start
;
2032 start
= ip
->i_size
+ fl
->l_start
;
2043 end
= start
+ fl
->l_len
- 1;
2045 * Create the lockf structure
2047 MALLOC(lock
, struct lockf
*, sizeof *lock
, M_LOCKF
, M_WAITOK
);
2048 lock
->lf_start
= start
;
2050 lock
->lf_id
= ap
->a_id
;
2051 lock
->lf_inode
= ip
;
2052 lock
->lf_type
= fl
->l_type
;
2053 lock
->lf_next
= (struct lockf
*)0;
2054 TAILQ_INIT(&lock
->lf_blkhd
);
2055 lock
->lf_flags
= ap
->a_flags
;
2057 * Do the requested operation.
2061 return (lf_setlock(lock
));
2064 error
= lf_clearlock(lock
);
2065 FREE(lock
, M_LOCKF
);
2069 error
= lf_getlock(lock
, fl
);
2070 FREE(lock
, M_LOCKF
);
2074 _FREE(lock
, M_LOCKF
);
2081 * Initialize the vnode associated with a new inode, handle aliased
2085 ufs_vinit(mntp
, specops
, fifoops
, vpp
)
2091 struct proc
*p
= current_proc(); /* XXX */
2093 struct vnode
*vp
, *nvp
;
2097 switch(vp
->v_type
= IFTOVT(ip
->i_mode
)) {
2101 if (nvp
= checkalias(vp
, ip
->i_rdev
, mntp
)) {
2103 * Discard unneeded vnode, but save its inode.
2104 * Note that the lock is carried over in the inode
2105 * to the replacement vnode.
2107 nvp
->v_data
= vp
->v_data
;
2109 vp
->v_op
= spec_vnodeop_p
;
2113 * Reinitialize aliased inode.
2124 return (EOPNOTSUPP
);
2134 if (ip
->i_number
== ROOTINO
)
2135 vp
->v_flag
|= VROOT
;
2137 * Initialize modrev times
2139 SETHIGH(ip
->i_modrev
, time
.tv_sec
);
2140 SETLOW(ip
->i_modrev
, time
.tv_usec
* 4294);
2146 * Allocate a new inode.
2149 ufs_makeinode(mode
, dvp
, vpp
, cnp
)
2153 struct componentname
*cnp
;
2155 register struct inode
*ip
, *pdir
;
2162 if ((cnp
->cn_flags
& HASBUF
) == 0)
2163 panic("ufs_makeinode: no name");
2166 if ((mode
& IFMT
) == 0)
2169 if (error
= VOP_VALLOC(dvp
, mode
, cnp
->cn_cred
, &tvp
)) {
2170 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2175 ip
->i_gid
= pdir
->i_gid
;
2176 if ((mode
& IFMT
) == IFLNK
)
2177 ip
->i_uid
= pdir
->i_uid
;
2179 ip
->i_uid
= cnp
->cn_cred
->cr_uid
;
2181 if ((error
= getinoquota(ip
)) ||
2182 (error
= chkiq(ip
, 1, cnp
->cn_cred
, 0))) {
2183 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2184 VOP_VFREE(tvp
, ip
->i_number
, mode
);
2190 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
2192 tvp
->v_type
= IFTOVT(mode
); /* Rest init'd in getnewvnode(). */
2194 if ((ip
->i_mode
& ISGID
) && !groupmember(ip
->i_gid
, cnp
->cn_cred
) &&
2195 suser(cnp
->cn_cred
, NULL
))
2196 ip
->i_mode
&= ~ISGID
;
2198 if (cnp
->cn_flags
& ISWHITEOUT
)
2199 ip
->i_flags
|= UF_OPAQUE
;
2202 * initialize UBC before calling VOP_UPDATE and ufs_direnter
2203 * Not doing so introduces probelms in handling error from
2205 * It results in a "vget: stolen ubc_info" panic due to attempt
2206 * to shutdown uninitialized UBC.
2208 if (UBCINFOMISSING(tvp
) || UBCINFORECLAIMED(tvp
))
2212 * Make sure inode goes to disk before directory entry.
2215 if (error
= VOP_UPDATE(tvp
, &tv
, &tv
, 1))
2217 if (error
= ufs_direnter(ip
, dvp
, cnp
))
2219 if ((cnp
->cn_flags
& SAVESTART
) == 0)
2220 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2228 * Write error occurred trying to update the inode
2229 * or the directory so must deallocate the inode.
2231 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2234 ip
->i_flag
|= IN_CHANGE
;