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>
80 #include <sys/quota.h>
82 #include <kern/thread.h>
85 #include <miscfs/specfs/specdev.h>
87 #include <ufs/ufs/lockf.h>
88 #include <ufs/ufs/quota.h>
89 #include <ufs/ufs/inode.h>
90 #include <ufs/ufs/dir.h>
91 #include <ufs/ufs/ufsmount.h>
92 #include <ufs/ufs/ufs_extern.h>
95 #include <ufs/ufs/ufs_byte_order.h>
96 #include <architecture/byte_order.h>
97 #endif /* REV_ENDIAN_FS */
99 static int ufs_chmod
__P((struct vnode
*, int, struct ucred
*, struct proc
*));
101 __P((struct vnode
*, uid_t
, gid_t
, struct ucred
*, struct proc
*));
107 #define SETHIGH(q, h) { \
110 tmp.val[_QUAD_HIGHWORD] = (h); \
113 #define SETLOW(q, l) { \
116 tmp.val[_QUAD_LOWWORD] = (l); \
121 * Create a regular file
125 struct vop_create_args
/* {
127 struct vnode **a_vpp;
128 struct componentname *a_cnp;
135 ufs_makeinode(MAKEIMODE(ap
->a_vap
->va_type
, ap
->a_vap
->va_mode
),
136 ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
))
147 struct vop_mknod_args
/* {
149 struct vnode **a_vpp;
150 struct componentname *a_cnp;
154 struct vattr
*vap
= ap
->a_vap
;
155 struct vnode
**vpp
= ap
->a_vpp
;
160 ufs_makeinode(MAKEIMODE(vap
->va_type
, vap
->va_mode
),
161 ap
->a_dvp
, vpp
, ap
->a_cnp
))
164 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
165 if (vap
->va_rdev
!= VNOVAL
) {
167 * Want to be able to use this to make badblock
168 * inodes, so don't truncate the dev number.
170 ip
->i_rdev
= vap
->va_rdev
;
173 * Remove inode so that it will be reloaded by VFS_VGET and
174 * checked to see if it is an alias of an existing entry in
178 (*vpp
)->v_type
= VNON
;
192 struct vop_open_args
/* {
195 struct ucred *a_cred;
201 * Files marked append-only must be opened for appending.
203 if ((VTOI(ap
->a_vp
)->i_flags
& APPEND
) &&
204 (ap
->a_mode
& (FWRITE
| O_APPEND
)) == FWRITE
)
212 * Update the times on the inode.
217 struct vop_close_args
/* {
220 struct ucred *a_cred;
224 register struct vnode
*vp
= ap
->a_vp
;
225 register struct inode
*ip
= VTOI(vp
);
227 simple_lock(&vp
->v_interlock
);
228 if ((!UBCISVALID(vp
) && vp
->v_usecount
> 1)
229 || (UBCISVALID(vp
) && ubc_isinuse(vp
, 1)))
230 ITIMES(ip
, &time
, &time
);
231 simple_unlock(&vp
->v_interlock
);
233 if (!VOP_ISLOCKED(vp
)) {
234 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, ap
->a_p
);
238 VOP_UNLOCK(vp
, 0, ap
->a_p
);
245 struct vop_access_args
/* {
248 struct ucred *a_cred;
252 struct vnode
*vp
= ap
->a_vp
;
253 struct inode
*ip
= VTOI(vp
);
254 struct ucred
*cred
= ap
->a_cred
;
255 mode_t mask
, mode
= ap
->a_mode
;
260 * Disallow write attempts on read-only file systems;
261 * unless the file is a socket, fifo, or a block or
262 * character device resident on the file system.
265 switch (vp
->v_type
) {
269 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
272 if (error
= getinoquota(ip
))
279 /* If immutable bit set, nobody gets to write it. */
280 if ((mode
& VWRITE
) && (ip
->i_flags
& IMMUTABLE
))
283 /* Otherwise, user id 0 always gets access. */
284 if (cred
->cr_uid
== 0)
289 /* Otherwise, check the owner. */
290 if (cred
->cr_uid
== ip
->i_uid
) {
297 return ((ip
->i_mode
& mask
) == mask
? 0 : EACCES
);
300 /* Otherwise, check the groups. */
301 for (i
= 0, gp
= cred
->cr_groups
; i
< cred
->cr_ngroups
; i
++, gp
++)
302 if (ip
->i_gid
== *gp
) {
309 return ((ip
->i_mode
& mask
) == mask
? 0 : EACCES
);
312 /* Otherwise, check everyone else. */
319 return ((ip
->i_mode
& mask
) == mask
? 0 : EACCES
);
325 struct vop_getattr_args
/* {
328 struct ucred *a_cred;
332 register struct vnode
*vp
= ap
->a_vp
;
333 register struct inode
*ip
= VTOI(vp
);
334 register struct vattr
*vap
= ap
->a_vap
;
337 ITIMES(ip
, &time
, &time
);
339 * Copy from inode table
341 vap
->va_fsid
= ip
->i_dev
;
342 vap
->va_fileid
= ip
->i_number
;
343 vap
->va_mode
= ip
->i_mode
& ~IFMT
;
344 vap
->va_nlink
= ip
->i_nlink
;
345 vap
->va_uid
= ip
->i_uid
;
346 vap
->va_gid
= ip
->i_gid
;
347 vap
->va_rdev
= (dev_t
)ip
->i_rdev
;
348 vap
->va_size
= ip
->i_din
.di_size
;
349 vap
->va_atime
.tv_sec
= ip
->i_atime
;
350 vap
->va_atime
.tv_nsec
= ip
->i_atimensec
;
351 vap
->va_mtime
.tv_sec
= ip
->i_mtime
;
352 vap
->va_mtime
.tv_nsec
= ip
->i_mtimensec
;
353 vap
->va_ctime
.tv_sec
= ip
->i_ctime
;
354 vap
->va_ctime
.tv_nsec
= ip
->i_ctimensec
;
355 vap
->va_flags
= ip
->i_flags
;
356 vap
->va_gen
= ip
->i_gen
;
357 /* this doesn't belong here */
358 if (vp
->v_type
== VBLK
)
359 vap
->va_blocksize
= BLKDEV_IOSIZE
;
360 else if (vp
->v_type
== VCHR
)
361 vap
->va_blocksize
= MAXPHYSIO
;
363 vap
->va_blocksize
= vp
->v_mount
->mnt_stat
.f_iosize
;
364 VOP_DEVBLOCKSIZE(ip
->i_devvp
, &devBlockSize
);
365 vap
->va_bytes
= dbtob((u_quad_t
)ip
->i_blocks
, devBlockSize
);
366 vap
->va_type
= vp
->v_type
;
367 vap
->va_filerev
= ip
->i_modrev
;
372 * Set attribute vnode op. called from several syscalls
376 struct vop_setattr_args
/* {
379 struct ucred *a_cred;
383 struct vattr
*vap
= ap
->a_vap
;
384 struct vnode
*vp
= ap
->a_vp
;
385 struct inode
*ip
= VTOI(vp
);
386 struct ucred
*cred
= ap
->a_cred
;
387 struct proc
*p
= ap
->a_p
;
388 struct timeval atimeval
, mtimeval
;
392 * Check for unsettable attributes.
394 if ((vap
->va_type
!= VNON
) || (vap
->va_nlink
!= VNOVAL
) ||
395 (vap
->va_fsid
!= VNOVAL
) || (vap
->va_fileid
!= VNOVAL
) ||
396 (vap
->va_blocksize
!= VNOVAL
) || (vap
->va_rdev
!= VNOVAL
) ||
397 ((int)vap
->va_bytes
!= VNOVAL
) || (vap
->va_gen
!= VNOVAL
)) {
400 if (vap
->va_flags
!= VNOVAL
) {
401 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
403 if (cred
->cr_uid
!= ip
->i_uid
&&
404 (error
= suser(cred
, &p
->p_acflag
)))
406 if (cred
->cr_uid
== 0) {
407 if ((ip
->i_flags
& (SF_IMMUTABLE
| SF_APPEND
)) &&
410 ip
->i_flags
= vap
->va_flags
;
412 if (ip
->i_flags
& (SF_IMMUTABLE
| SF_APPEND
) ||
413 (vap
->va_flags
& UF_SETTABLE
) != vap
->va_flags
)
415 ip
->i_flags
&= SF_SETTABLE
;
416 ip
->i_flags
|= (vap
->va_flags
& UF_SETTABLE
);
418 ip
->i_flag
|= IN_CHANGE
;
419 if (vap
->va_flags
& (IMMUTABLE
| APPEND
))
422 if (ip
->i_flags
& (IMMUTABLE
| APPEND
))
425 * Go through the fields and update iff not VNOVAL.
427 if (vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
) {
428 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
430 if (error
= ufs_chown(vp
, vap
->va_uid
, vap
->va_gid
, cred
, p
))
433 if (vap
->va_size
!= VNOVAL
) {
435 * Disallow write attempts on read-only file systems;
436 * unless the file is a socket, fifo, or a block or
437 * character device resident on the file system.
439 switch (vp
->v_type
) {
444 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
448 if (error
= VOP_TRUNCATE(vp
, vap
->va_size
, 0, cred
, p
))
452 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
453 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
455 if (cred
->cr_uid
!= ip
->i_uid
&&
456 (error
= suser(cred
, &p
->p_acflag
)) &&
457 ((vap
->va_vaflags
& VA_UTIMES_NULL
) == 0 ||
458 (error
= VOP_ACCESS(vp
, VWRITE
, cred
, p
))))
460 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
461 ip
->i_flag
|= IN_ACCESS
;
462 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
463 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
464 atimeval
.tv_sec
= vap
->va_atime
.tv_sec
;
465 atimeval
.tv_usec
= vap
->va_atime
.tv_nsec
/ 1000;
466 mtimeval
.tv_sec
= vap
->va_mtime
.tv_sec
;
467 mtimeval
.tv_usec
= vap
->va_mtime
.tv_nsec
/ 1000;
468 if (error
= VOP_UPDATE(vp
, &atimeval
, &mtimeval
, 1))
472 if (vap
->va_mode
!= (mode_t
)VNOVAL
) {
473 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
475 error
= ufs_chmod(vp
, (int)vap
->va_mode
, cred
, p
);
481 * Change the mode on a file.
482 * Inode must be locked before calling.
485 ufs_chmod(vp
, mode
, cred
, p
)
486 register struct vnode
*vp
;
488 register struct ucred
*cred
;
491 register struct inode
*ip
= VTOI(vp
);
494 if (cred
->cr_uid
!= ip
->i_uid
&&
495 (error
= suser(cred
, &p
->p_acflag
)))
498 if (vp
->v_type
!= VDIR
&& (mode
& S_ISTXT
))
500 if (!groupmember(ip
->i_gid
, cred
) && (mode
& ISGID
))
503 ip
->i_mode
&= ~ALLPERMS
;
504 ip
->i_mode
|= (mode
& ALLPERMS
);
505 ip
->i_flag
|= IN_CHANGE
;
510 * Perform chown operation on inode ip;
511 * inode must be locked prior to call.
514 ufs_chown(vp
, uid
, gid
, cred
, p
)
515 register struct vnode
*vp
;
521 register struct inode
*ip
= VTOI(vp
);
527 int64_t change
; /* in bytes */
531 if (uid
== (uid_t
)VNOVAL
)
533 if (gid
== (gid_t
)VNOVAL
)
536 * If we don't own the file, are trying to change the owner
537 * of the file, or are not a member of the target group,
538 * the caller must be superuser or the call fails.
540 if ((cred
->cr_uid
!= ip
->i_uid
|| uid
!= ip
->i_uid
||
541 (gid
!= ip
->i_gid
&& !groupmember((gid_t
)gid
, cred
))) &&
542 (error
= suser(cred
, &p
->p_acflag
)))
547 if (error
= getinoquota(ip
))
550 dqrele(vp
, ip
->i_dquot
[USRQUOTA
]);
551 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
554 dqrele(vp
, ip
->i_dquot
[GRPQUOTA
]);
555 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
557 VOP_DEVBLOCKSIZE(ip
->i_devvp
, &devBlockSize
);
558 change
= dbtob((int64_t)ip
->i_blocks
, devBlockSize
);
559 (void) chkdq(ip
, -change
, cred
, CHOWN
);
560 (void) chkiq(ip
, -1, cred
, CHOWN
);
561 for (i
= 0; i
< MAXQUOTAS
; i
++) {
562 dqrele(vp
, ip
->i_dquot
[i
]);
563 ip
->i_dquot
[i
] = NODQUOT
;
569 if ((error
= getinoquota(ip
)) == 0) {
571 dqrele(vp
, ip
->i_dquot
[USRQUOTA
]);
572 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
575 dqrele(vp
, ip
->i_dquot
[GRPQUOTA
]);
576 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
578 if ((error
= chkdq(ip
, change
, cred
, CHOWN
)) == 0) {
579 if ((error
= chkiq(ip
, 1, cred
, CHOWN
)) == 0)
582 (void) chkdq(ip
, -change
, cred
, CHOWN
|FORCE
);
584 for (i
= 0; i
< MAXQUOTAS
; i
++) {
585 dqrele(vp
, ip
->i_dquot
[i
]);
586 ip
->i_dquot
[i
] = NODQUOT
;
591 if (getinoquota(ip
) == 0) {
593 dqrele(vp
, ip
->i_dquot
[USRQUOTA
]);
594 ip
->i_dquot
[USRQUOTA
] = NODQUOT
;
597 dqrele(vp
, ip
->i_dquot
[GRPQUOTA
]);
598 ip
->i_dquot
[GRPQUOTA
] = NODQUOT
;
600 (void) chkdq(ip
, change
, cred
, FORCE
|CHOWN
);
601 (void) chkiq(ip
, 1, cred
, FORCE
|CHOWN
);
602 (void) getinoquota(ip
);
607 panic("chown: lost quota");
609 if (ouid
!= uid
|| ogid
!= gid
)
610 ip
->i_flag
|= IN_CHANGE
;
611 if (ouid
!= uid
&& cred
->cr_uid
!= 0)
612 ip
->i_mode
&= ~ISUID
;
613 if (ogid
!= gid
&& cred
->cr_uid
!= 0)
614 ip
->i_mode
&= ~ISGID
;
621 struct vop_ioctl_args
/* {
626 struct ucred *a_cred;
631 switch (ap
->a_command
) {
634 { register struct inode
*ip
;
635 register struct vnode
*vp
;
636 register struct fs
*fs
;
637 register struct radvisory
*ra
;
638 int devBlockSize
= 0;
643 VOP_LEASE(vp
, ap
->a_p
, ap
->a_cred
, LEASE_READ
);
644 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
, ap
->a_p
);
646 ra
= (struct radvisory
*)(ap
->a_data
);
650 if ((u_int64_t
)ra
->ra_offset
>= ip
->i_size
) {
651 VOP_UNLOCK(vp
, 0, ap
->a_p
);
654 VOP_DEVBLOCKSIZE(ip
->i_devvp
, &devBlockSize
);
656 error
= advisory_read(vp
, ip
->i_size
, ra
->ra_offset
, ra
->ra_count
, devBlockSize
);
657 VOP_UNLOCK(vp
, 0, ap
->a_p
);
668 struct vop_select_args
/* {
672 struct ucred *a_cred;
679 * We should really check to see if I/O is possible.
687 * NB Currently unsupported.
692 struct vop_mmap_args
/* {
695 struct ucred *a_cred;
706 * Nothing to do, so just return.
711 struct vop_seek_args
/* {
715 struct ucred *a_cred;
724 struct vop_remove_args
/* {
727 struct componentname *a_cnp;
731 struct vnode
*vp
= ap
->a_vp
;
732 struct vnode
*dvp
= ap
->a_dvp
;
736 if ((ip
->i_flags
& (IMMUTABLE
| APPEND
)) ||
737 (VTOI(dvp
)->i_flags
& APPEND
)) {
742 if (ap
->a_cnp
->cn_flags
& NODELETEBUSY
) {
743 /* Caller requested Carbon delete semantics */
744 if ((!UBCISVALID(vp
) && vp
->v_usecount
> 1)
745 || (UBCISVALID(vp
) && ubc_isinuse(vp
, 1))) {
751 if ((error
= ufs_dirremove(dvp
, ap
->a_cnp
)) == 0) {
753 ip
->i_flag
|= IN_CHANGE
;
757 VOP_UNLOCK(vp
, 0, ap
->a_cnp
->cn_proc
);
759 (void) ubc_uncache(vp
);
780 struct vop_link_args
/* {
782 struct vnode *a_tdvp;
783 struct componentname *a_cnp;
786 struct vnode
*vp
= ap
->a_vp
;
787 struct vnode
*tdvp
= ap
->a_tdvp
;
788 struct componentname
*cnp
= ap
->a_cnp
;
789 struct proc
*p
= cnp
->cn_proc
;
795 if ((cnp
->cn_flags
& HASBUF
) == 0)
796 panic("ufs_link: no name");
798 if (tdvp
->v_mount
!= vp
->v_mount
) {
799 VOP_ABORTOP(tdvp
, cnp
);
803 if (tdvp
!= vp
&& (error
= vn_lock(vp
, LK_EXCLUSIVE
, p
))) {
804 VOP_ABORTOP(tdvp
, cnp
);
808 if ((nlink_t
)ip
->i_nlink
>= LINK_MAX
) {
809 VOP_ABORTOP(tdvp
, cnp
);
813 if (ip
->i_flags
& (IMMUTABLE
| APPEND
)) {
814 VOP_ABORTOP(tdvp
, cnp
);
819 ip
->i_flag
|= IN_CHANGE
;
821 error
= VOP_UPDATE(vp
, &tv
, &tv
, 1);
823 error
= ufs_direnter(ip
, tdvp
, cnp
);
826 ip
->i_flag
|= IN_CHANGE
;
828 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
831 VOP_UNLOCK(vp
, 0, p
);
838 * whiteout vnode call
842 struct vop_whiteout_args
/* {
844 struct componentname *a_cnp;
848 struct vnode
*dvp
= ap
->a_dvp
;
849 struct componentname
*cnp
= ap
->a_cnp
;
850 struct direct newdir
;
853 switch (ap
->a_flags
) {
855 /* 4.4 format directories support whiteout operations */
856 if (dvp
->v_mount
->mnt_maxsymlinklen
> 0)
861 /* create a new directory whiteout */
863 if ((cnp
->cn_flags
& SAVENAME
) == 0)
864 panic("ufs_whiteout: missing name");
865 if (dvp
->v_mount
->mnt_maxsymlinklen
<= 0)
866 panic("ufs_whiteout: old format filesystem");
870 newdir
.d_namlen
= cnp
->cn_namelen
;
871 bcopy(cnp
->cn_nameptr
, newdir
.d_name
, (unsigned)cnp
->cn_namelen
+ 1);
872 newdir
.d_type
= DT_WHT
;
873 error
= ufs_direnter2(dvp
, &newdir
, cnp
->cn_cred
, cnp
->cn_proc
);
877 /* remove an existing directory whiteout */
879 if (dvp
->v_mount
->mnt_maxsymlinklen
<= 0)
880 panic("ufs_whiteout: old format filesystem");
883 cnp
->cn_flags
&= ~DOWHITEOUT
;
884 error
= ufs_dirremove(dvp
, cnp
);
887 if (cnp
->cn_flags
& HASBUF
) {
888 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
889 cnp
->cn_flags
&= ~HASBUF
;
896 * Rename system call.
897 * rename("foo", "bar");
900 * link("foo", "bar");
902 * but ``atomically''. Can't do full commit without saving state in the
903 * inode on disk which isn't feasible at this time. Best we can do is
904 * always guarantee the target exists.
906 * Basic algorithm is:
908 * 1) Bump link count on source while we're linking it to the
909 * target. This also ensure the inode won't be deleted out
910 * from underneath us while we work (it may be truncated by
911 * a concurrent `trunc' or `open' for creation).
912 * 2) Link source to destination. If destination already exists,
914 * 3) Unlink source reference to inode if still around. If a
915 * directory was moved and the parent of the destination
916 * is different from the source, patch the ".." entry in the
921 struct vop_rename_args
/* {
922 struct vnode *a_fdvp;
924 struct componentname *a_fcnp;
925 struct vnode *a_tdvp;
927 struct componentname *a_tcnp;
930 struct vnode
*tvp
= ap
->a_tvp
;
931 register struct vnode
*tdvp
= ap
->a_tdvp
;
932 struct vnode
*fvp
= ap
->a_fvp
;
933 struct vnode
*fdvp
= ap
->a_fdvp
;
934 struct componentname
*tcnp
= ap
->a_tcnp
;
935 struct componentname
*fcnp
= ap
->a_fcnp
;
936 struct proc
*p
= fcnp
->cn_proc
;
937 struct inode
*ip
, *xp
, *dp
;
938 struct dirtemplate dirbuf
;
940 int doingdirectory
= 0, oldparent
= 0, newparent
= 0;
945 if ((tcnp
->cn_flags
& HASBUF
) == 0 ||
946 (fcnp
->cn_flags
& HASBUF
) == 0)
947 panic("ufs_rename: no name");
950 * Check for cross-device rename.
952 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
953 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
956 VOP_ABORTOP(tdvp
, tcnp
); /* XXX, why not in NFS? */
963 VOP_ABORTOP(fdvp
, fcnp
); /* XXX, why not in NFS? */
970 * Check if just deleting a link name.
972 if (tvp
&& ((VTOI(tvp
)->i_flags
& (IMMUTABLE
| APPEND
)) ||
973 (VTOI(tdvp
)->i_flags
& APPEND
))) {
978 if (fvp
->v_type
== VDIR
) {
983 /* Release destination completely. */
984 VOP_ABORTOP(tdvp
, tcnp
);
991 fcnp
->cn_flags
&= ~MODMASK
;
992 fcnp
->cn_flags
|= LOCKPARENT
| LOCKLEAF
;
993 if ((fcnp
->cn_flags
& SAVESTART
) == 0)
994 panic("ufs_rename: lost from startdir");
995 fcnp
->cn_nameiop
= DELETE
;
996 (void) relookup(fdvp
, &fvp
, fcnp
);
997 return (VOP_REMOVE(fdvp
, fvp
, fcnp
));
999 if (error
= vn_lock(fvp
, LK_EXCLUSIVE
, p
))
1003 if ((ip
->i_flags
& (IMMUTABLE
| APPEND
)) || (dp
->i_flags
& APPEND
)) {
1004 VOP_UNLOCK(fvp
, 0, p
);
1008 if ((ip
->i_mode
& IFMT
) == IFDIR
) {
1010 * Avoid ".", "..", and aliases of "." for obvious reasons.
1012 if ((fcnp
->cn_namelen
== 1 && fcnp
->cn_nameptr
[0] == '.') ||
1013 dp
== ip
|| (fcnp
->cn_flags
&ISDOTDOT
) ||
1014 (ip
->i_flag
& IN_RENAME
)) {
1015 VOP_UNLOCK(fvp
, 0, p
);
1019 ip
->i_flag
|= IN_RENAME
;
1020 oldparent
= dp
->i_number
;
1026 * When the target exists, both the directory
1027 * and target vnodes are returned locked.
1035 * 1) Bump link count while we're moving stuff
1036 * around. If we crash somewhere before
1037 * completing our work, the link count
1038 * may be wrong, but correctable.
1041 ip
->i_flag
|= IN_CHANGE
;
1043 if (error
= VOP_UPDATE(fvp
, &tv
, &tv
, 1)) {
1044 VOP_UNLOCK(fvp
, 0, p
);
1049 * If ".." must be changed (ie the directory gets a new
1050 * parent) then the source directory must not be in the
1051 * directory heirarchy above the target, as this would
1052 * orphan everything below the source directory. Also
1053 * the user must have write permission in the source so
1054 * as to be able to change "..". We must repeat the call
1055 * to namei, as the parent directory is unlocked by the
1056 * call to checkpath().
1058 error
= VOP_ACCESS(fvp
, VWRITE
, tcnp
->cn_cred
, tcnp
->cn_proc
);
1059 VOP_UNLOCK(fvp
, 0, p
);
1060 if (oldparent
!= dp
->i_number
)
1061 newparent
= dp
->i_number
;
1062 if (doingdirectory
&& newparent
) {
1063 if (error
) /* write access check above */
1067 if (error
= ufs_checkpath(ip
, dp
, tcnp
->cn_cred
))
1069 if ((tcnp
->cn_flags
& SAVESTART
) == 0)
1070 panic("ufs_rename: lost to startdir");
1071 if (error
= relookup(tdvp
, &tvp
, tcnp
))
1079 * 2) If target doesn't exist, link the target
1080 * to the source and unlink the source.
1081 * Otherwise, rewrite the target directory
1082 * entry to reference the source inode and
1083 * expunge the original entry's existence.
1086 if (dp
->i_dev
!= ip
->i_dev
)
1087 panic("rename: EXDEV");
1089 * Account for ".." in new directory.
1090 * When source and destination have the same
1091 * parent we don't fool with the link count.
1093 if (doingdirectory
&& newparent
) {
1094 if ((nlink_t
)dp
->i_nlink
>= LINK_MAX
) {
1099 dp
->i_flag
|= IN_CHANGE
;
1100 if (error
= VOP_UPDATE(tdvp
, &tv
, &tv
, 1))
1103 if (error
= ufs_direnter(ip
, tdvp
, tcnp
)) {
1104 if (doingdirectory
&& newparent
) {
1106 dp
->i_flag
|= IN_CHANGE
;
1107 (void)VOP_UPDATE(tdvp
, &tv
, &tv
, 1);
1113 if (xp
->i_dev
!= dp
->i_dev
|| xp
->i_dev
!= ip
->i_dev
)
1114 panic("rename: EXDEV");
1116 * Short circuit rename(foo, foo).
1118 if (xp
->i_number
== ip
->i_number
)
1119 panic("rename: same file");
1121 * If the parent directory is "sticky", then the user must
1122 * own the parent directory, or the destination of the rename,
1123 * otherwise the destination may not be changed (except by
1124 * root). This implements append-only directories.
1126 if ((dp
->i_mode
& S_ISTXT
) && tcnp
->cn_cred
->cr_uid
!= 0 &&
1127 tcnp
->cn_cred
->cr_uid
!= dp
->i_uid
&&
1128 xp
->i_uid
!= tcnp
->cn_cred
->cr_uid
) {
1133 * Target must be empty if a directory and have no links
1134 * to it. Also, ensure source and target are compatible
1135 * (both directories, or both not directories).
1137 if ((xp
->i_mode
&IFMT
) == IFDIR
) {
1138 if (!ufs_dirempty(xp
, dp
->i_number
, tcnp
->cn_cred
) ||
1143 if (!doingdirectory
) {
1148 } else if (doingdirectory
) {
1152 if (error
= ufs_dirrewrite(dp
, ip
, tcnp
))
1155 * If the target directory is in the same
1156 * directory as the source directory,
1157 * decrement the link count on the parent
1158 * of the target directory.
1160 if (doingdirectory
&& !newparent
) {
1162 dp
->i_flag
|= IN_CHANGE
;
1166 * Adjust the link count of the target to
1167 * reflect the dirrewrite above. If this is
1168 * a directory it is empty and there are
1169 * no links to it, so we can squash the inode and
1170 * any space associated with it. We disallowed
1171 * renaming over top of a directory with links to
1172 * it above, as the remaining link would point to
1173 * a directory without "." or ".." entries.
1176 if (doingdirectory
) {
1177 if (--xp
->i_nlink
!= 0)
1178 panic("rename: linked directory");
1179 error
= VOP_TRUNCATE(tvp
, (off_t
)0, IO_SYNC
,
1180 tcnp
->cn_cred
, tcnp
->cn_proc
);
1182 xp
->i_flag
|= IN_CHANGE
;
1188 * 3) Unlink the source.
1190 fcnp
->cn_flags
&= ~MODMASK
;
1191 fcnp
->cn_flags
|= LOCKPARENT
| LOCKLEAF
;
1192 if ((fcnp
->cn_flags
& SAVESTART
) == 0)
1193 panic("ufs_rename: lost from startdir");
1194 (void) relookup(fdvp
, &fvp
, fcnp
);
1200 * From name has disappeared.
1203 panic("rename: lost dir entry");
1208 * Ensure that the directory entry still exists and has not
1209 * changed while the new name has been entered. If the source is
1210 * a file then the entry may have been unlinked or renamed. In
1211 * either case there is no further work to be done. If the source
1212 * is a directory then it cannot have been rmdir'ed; its link
1213 * count of three would cause a rmdir to fail with ENOTEMPTY.
1214 * The IRENAME flag ensures that it cannot be moved by another
1219 panic("rename: lost dir entry");
1222 * If the source is a directory with a
1223 * new parent, the link count of the old
1224 * parent directory must be decremented
1225 * and ".." set to point to the new parent.
1227 if (doingdirectory
&& newparent
) {
1229 dp
->i_flag
|= IN_CHANGE
;
1230 error
= vn_rdwr(UIO_READ
, fvp
, (caddr_t
)&dirbuf
,
1231 sizeof (struct dirtemplate
), (off_t
)0,
1232 UIO_SYSSPACE
, IO_NODELOCKED
,
1233 tcnp
->cn_cred
, (int *)0, (struct proc
*)0);
1235 # if (BYTE_ORDER == LITTLE_ENDIAN)
1236 if (fvp
->v_mount
->mnt_maxsymlinklen
<= 0)
1237 namlen
= dirbuf
.dotdot_type
;
1239 namlen
= dirbuf
.dotdot_namlen
;
1241 namlen
= dirbuf
.dotdot_namlen
;
1244 dirbuf
.dotdot_name
[0] != '.' ||
1245 dirbuf
.dotdot_name
[1] != '.') {
1246 ufs_dirbad(xp
, (doff_t
)12,
1247 "rename: mangled dir");
1249 dirbuf
.dotdot_ino
= newparent
;
1250 (void) vn_rdwr(UIO_WRITE
, fvp
,
1252 sizeof (struct dirtemplate
),
1253 (off_t
)0, UIO_SYSSPACE
,
1254 IO_NODELOCKED
|IO_SYNC
,
1255 tcnp
->cn_cred
, (int *)0,
1261 error
= ufs_dirremove(fdvp
, fcnp
);
1264 xp
->i_flag
|= IN_CHANGE
;
1266 xp
->i_flag
&= ~IN_RENAME
;
1281 ip
->i_flag
&= ~IN_RENAME
;
1282 if (vn_lock(fvp
, LK_EXCLUSIVE
, p
) == 0) {
1284 ip
->i_flag
|= IN_CHANGE
;
1292 * A virgin directory (no blushing please).
1294 static struct dirtemplate mastertemplate
= {
1295 0, 12, DT_DIR
, 1, ".",
1296 0, DIRBLKSIZ
- 12, DT_DIR
, 2, ".."
1298 static struct odirtemplate omastertemplate
= {
1300 0, DIRBLKSIZ
- 12, 2, ".."
1308 struct vop_mkdir_args
/* {
1309 struct vnode *a_dvp;
1310 struct vnode **a_vpp;
1311 struct componentname *a_cnp;
1312 struct vattr *a_vap;
1315 register struct vnode
*dvp
= ap
->a_dvp
;
1316 register struct vattr
*vap
= ap
->a_vap
;
1317 register struct componentname
*cnp
= ap
->a_cnp
;
1318 register struct inode
*ip
, *dp
;
1320 struct dirtemplate dirtemplate
, *dtp
;
1325 if ((cnp
->cn_flags
& HASBUF
) == 0)
1326 panic("ufs_mkdir: no name");
1329 if ((nlink_t
)dp
->i_nlink
>= LINK_MAX
) {
1333 dmode
= vap
->va_mode
& 0777;
1336 * Must simulate part of ufs_makeinode here to acquire the inode,
1337 * but not have it entered in the parent directory. The entry is
1338 * made later after writing "." and ".." entries.
1340 if (error
= VOP_VALLOC(dvp
, dmode
, cnp
->cn_cred
, &tvp
))
1343 ip
->i_uid
= cnp
->cn_cred
->cr_uid
;
1344 ip
->i_gid
= dp
->i_gid
;
1346 if ((error
= getinoquota(ip
)) ||
1347 (error
= chkiq(ip
, 1, cnp
->cn_cred
, 0))) {
1348 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1349 VOP_VFREE(tvp
, ip
->i_number
, dmode
);
1355 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
1357 tvp
->v_type
= VDIR
; /* Rest init'd in getnewvnode(). */
1359 if (cnp
->cn_flags
& ISWHITEOUT
)
1360 ip
->i_flags
|= UF_OPAQUE
;
1362 error
= VOP_UPDATE(tvp
, &tv
, &tv
, 1);
1365 * Bump link count in parent directory
1366 * to reflect work done below. Should
1367 * be done before reference is created
1368 * so reparation is possible if we crash.
1371 dp
->i_flag
|= IN_CHANGE
;
1372 if (error
= VOP_UPDATE(dvp
, &tv
, &tv
, 1))
1375 /* Initialize directory with "." and ".." from static template. */
1376 if (dvp
->v_mount
->mnt_maxsymlinklen
> 0)
1377 dtp
= &mastertemplate
;
1379 dtp
= (struct dirtemplate
*)&omastertemplate
;
1381 dirtemplate
.dot_ino
= ip
->i_number
;
1382 dirtemplate
.dotdot_ino
= dp
->i_number
;
1383 error
= vn_rdwr(UIO_WRITE
, tvp
, (caddr_t
)&dirtemplate
,
1384 sizeof (dirtemplate
), (off_t
)0, UIO_SYSSPACE
,
1385 IO_NODELOCKED
|IO_SYNC
, cnp
->cn_cred
, (int *)0, (struct proc
*)0);
1388 dp
->i_flag
|= IN_CHANGE
;
1391 if (DIRBLKSIZ
> VFSTOUFS(dvp
->v_mount
)->um_mountp
->mnt_stat
.f_bsize
)
1392 panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
1394 ip
->i_size
= DIRBLKSIZ
;
1395 ip
->i_flag
|= IN_CHANGE
;
1398 /* Directory set up, now install it's entry in the parent directory. */
1399 if (error
= ufs_direnter(ip
, dvp
, cnp
)) {
1401 dp
->i_flag
|= IN_CHANGE
;
1405 * No need to do an explicit VOP_TRUNCATE here, vrele will do this
1406 * for us because we set the link count to 0.
1410 ip
->i_flag
|= IN_CHANGE
;
1415 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1421 * Rmdir system call.
1425 struct vop_rmdir_args
/* {
1426 struct vnode *a_dvp;
1428 struct componentname *a_cnp;
1431 struct vnode
*vp
= ap
->a_vp
;
1432 struct vnode
*dvp
= ap
->a_dvp
;
1433 struct componentname
*cnp
= ap
->a_cnp
;
1434 struct inode
*ip
, *dp
;
1440 * No rmdir "." please.
1448 * Verify the directory is empty (and valid).
1449 * (Rmdir ".." won't be valid since
1450 * ".." will contain a reference to
1451 * the current directory and thus be
1455 if (ip
->i_nlink
!= 2 ||
1456 !ufs_dirempty(ip
, dp
->i_number
, cnp
->cn_cred
)) {
1460 if ((dp
->i_flags
& APPEND
) || (ip
->i_flags
& (IMMUTABLE
| APPEND
))) {
1465 * Delete reference to directory before purging
1466 * inode. If we crash in between, the directory
1467 * will be reattached to lost+found,
1469 if (error
= ufs_dirremove(dvp
, cnp
))
1472 dp
->i_flag
|= IN_CHANGE
;
1477 * Truncate inode. The only stuff left
1478 * in the directory is "." and "..". The
1479 * "." reference is inconsequential since
1480 * we're quashing it. The ".." reference
1481 * has already been adjusted above. We've
1482 * removed the "." reference and the reference
1483 * in the parent directory, but there may be
1484 * other hard links so decrement by 2 and
1485 * worry about them later.
1488 error
= VOP_TRUNCATE(vp
, (off_t
)0, IO_SYNC
, cnp
->cn_cred
,
1490 cache_purge(ITOV(ip
));
1499 * symlink -- make a symbolic link
1503 struct vop_symlink_args
/* {
1504 struct vnode *a_dvp;
1505 struct vnode **a_vpp;
1506 struct componentname *a_cnp;
1507 struct vattr *a_vap;
1511 register struct vnode
*vp
, **vpp
= ap
->a_vpp
;
1512 register struct inode
*ip
;
1515 if (error
= ufs_makeinode(IFLNK
| ap
->a_vap
->va_mode
, ap
->a_dvp
,
1519 len
= strlen(ap
->a_target
);
1520 if (len
< vp
->v_mount
->mnt_maxsymlinklen
) {
1522 bcopy(ap
->a_target
, (char *)ip
->i_shortlink
, len
);
1524 ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1526 error
= vn_rdwr(UIO_WRITE
, vp
, ap
->a_target
, len
, (off_t
)0,
1527 UIO_SYSSPACE
, IO_NODELOCKED
, ap
->a_cnp
->cn_cred
, (int *)0,
1534 * Vnode op for reading directories.
1536 * The routine below assumes that the on-disk format of a directory
1537 * is the same as that defined by <sys/dirent.h>. If the on-disk
1538 * format changes, then it will be necessary to do a conversion
1539 * from the on-disk format that read returns to the format defined
1540 * by <sys/dirent.h>.
1544 struct vop_readdir_args
/* {
1547 struct ucred *a_cred;
1553 register struct uio
*uio
= ap
->a_uio
;
1556 off_t off
= uio
->uio_offset
;
1558 count
= uio
->uio_resid
;
1559 /* Make sure we don't return partial entries. */
1560 count
-= (uio
->uio_offset
+ count
) & (DIRBLKSIZ
-1);
1563 lost
= uio
->uio_resid
- count
;
1564 uio
->uio_resid
= count
;
1565 uio
->uio_iov
->iov_len
= count
;
1566 # if (BYTE_ORDER == LITTLE_ENDIAN)
1567 if (ap
->a_vp
->v_mount
->mnt_maxsymlinklen
> 0) {
1568 error
= VOP_READ(ap
->a_vp
, uio
, 0, ap
->a_cred
);
1570 struct dirent
*dp
, *edp
;
1578 auio
.uio_iov
= &aiov
;
1579 auio
.uio_iovcnt
= 1;
1580 auio
.uio_segflg
= UIO_SYSSPACE
;
1581 aiov
.iov_len
= count
;
1582 MALLOC(dirbuf
, caddr_t
, count
, M_TEMP
, M_WAITOK
);
1583 aiov
.iov_base
= dirbuf
;
1584 error
= VOP_READ(ap
->a_vp
, &auio
, 0, ap
->a_cred
);
1586 readcnt
= count
- auio
.uio_resid
;
1587 edp
= (struct dirent
*)&dirbuf
[readcnt
];
1588 for (dp
= (struct dirent
*)dirbuf
; dp
< edp
; ) {
1590 dp
->d_namlen
= dp
->d_type
;
1592 if (dp
->d_reclen
> 0) {
1593 dp
= (struct dirent
*)
1594 ((char *)dp
+ dp
->d_reclen
);
1601 error
= uiomove(dirbuf
, readcnt
, uio
);
1603 FREE(dirbuf
, M_TEMP
);
1606 error
= VOP_READ(ap
->a_vp
, uio
, 0, ap
->a_cred
);
1608 if (!error
&& ap
->a_ncookies
!= NULL
) {
1609 struct dirent
* dpStart
;
1610 struct dirent
* dpEnd
;
1617 * Only the NFS server uses cookies, and it loads the
1618 * directory block into system space, so we can just look at
1621 if (uio
->uio_segflg
!= UIO_SYSSPACE
|| uio
->uio_iovcnt
!= 1)
1622 panic("ufs_readdir: unexpected uio from NFS server");
1623 dpStart
= (struct dirent
*)
1624 (uio
->uio_iov
->iov_base
- (uio
->uio_offset
- off
));
1625 dpEnd
= (struct dirent
*) uio
->uio_iov
->iov_base
;
1626 for (dp
= dpStart
, ncookies
= 0;
1627 dp
< dpEnd
&& dp
->d_reclen
!= 0;
1628 dp
= (struct dirent
*)((caddr_t
)dp
+ dp
->d_reclen
))
1630 MALLOC(cookies
, u_long
*, ncookies
* sizeof(u_long
), M_TEMP
,
1632 for (dp
= dpStart
, cookiep
= cookies
;
1634 dp
= (struct dirent
*)((caddr_t
) dp
+ dp
->d_reclen
)) {
1635 off
+= dp
->d_reclen
;
1636 *cookiep
++ = (u_long
) off
;
1638 *ap
->a_ncookies
= ncookies
;
1639 *ap
->a_cookies
= cookies
;
1641 uio
->uio_resid
+= lost
;
1643 *ap
->a_eofflag
= VTOI(ap
->a_vp
)->i_size
<= uio
->uio_offset
;
1648 * Return target name of a symbolic link
1652 struct vop_readlink_args
/* {
1655 struct ucred *a_cred;
1658 register struct vnode
*vp
= ap
->a_vp
;
1659 register struct inode
*ip
= VTOI(vp
);
1663 if (isize
< vp
->v_mount
->mnt_maxsymlinklen
) {
1664 uiomove((char *)ip
->i_shortlink
, isize
, ap
->a_uio
);
1667 return (VOP_READ(vp
, ap
->a_uio
, 0, ap
->a_cred
));
1671 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
1672 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
1677 struct vop_abortop_args
/* {
1678 struct vnode *a_dvp;
1679 struct componentname *a_cnp;
1682 if ((ap
->a_cnp
->cn_flags
& (HASBUF
| SAVESTART
)) == HASBUF
)
1683 FREE_ZONE(ap
->a_cnp
->cn_pnbuf
, ap
->a_cnp
->cn_pnlen
, M_NAMEI
);
1688 * Lock an inode. If its already locked, set the WANT bit and sleep.
1692 struct vop_lock_args
/* {
1698 struct vnode
*vp
= ap
->a_vp
;
1700 if (VTOI(vp
) == (struct inode
*)NULL
)
1701 panic("inode in vnode is null\n");
1702 return (lockmgr(&VTOI(vp
)->i_lock
, ap
->a_flags
, &vp
->v_interlock
,
1711 struct vop_unlock_args
/* {
1717 struct vnode
*vp
= ap
->a_vp
;
1719 return (lockmgr(&VTOI(vp
)->i_lock
, ap
->a_flags
| LK_RELEASE
,
1720 &vp
->v_interlock
, ap
->a_p
));
1724 * Check for a locked inode.
1728 struct vop_islocked_args
/* {
1733 return (lockstatus(&VTOI(ap
->a_vp
)->i_lock
));
1737 * Calculate the logical to physical mapping if not done already,
1738 * then call the device strategy routine.
1742 struct vop_strategy_args
/* {
1746 register struct buf
*bp
= ap
->a_bp
;
1747 register struct vnode
*vp
= bp
->b_vp
;
1748 register struct inode
*ip
;
1752 if ( !(bp
->b_flags
& B_VECTORLIST
)) {
1753 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
1754 panic("ufs_strategy: spec");
1757 if (bp
->b_flags
& B_PAGELIST
) {
1759 * if we have a page list associated with this bp,
1760 * then go through cluste_bp since it knows how to
1761 * deal with a page request that might span non-contiguous
1762 * physical blocks on the disk...
1765 if (bp
->b_blkno
== bp
->b_lblkno
) {
1766 if (error
= VOP_BMAP(vp
, bp
->b_lblkno
, NULL
,
1767 &bp
->b_blkno
, NULL
)) {
1768 bp
->b_error
= error
;
1769 bp
->b_flags
|= B_ERROR
;
1775 error
= cluster_bp(bp
);
1777 bp
->b_dev
= vp
->v_rdev
;
1782 if (bp
->b_blkno
== bp
->b_lblkno
) {
1784 VOP_BMAP(vp
, bp
->b_lblkno
, NULL
, &bp
->b_blkno
, NULL
)) {
1785 bp
->b_error
= error
;
1786 bp
->b_flags
|= B_ERROR
;
1790 if ((long)bp
->b_blkno
== -1)
1793 if ((long)bp
->b_blkno
== -1) {
1801 bp
->b_dev
= vp
->v_rdev
;
1802 VOCALL (vp
->v_op
, VOFFSET(vop_strategy
), ap
);
1807 * Print out the contents of an inode.
1811 struct vop_print_args
/* {
1815 register struct vnode
*vp
= ap
->a_vp
;
1816 register struct inode
*ip
= VTOI(vp
);
1818 printf("tag VT_UFS, ino %d, on dev %d, %d", ip
->i_number
,
1819 major(ip
->i_dev
), minor(ip
->i_dev
));
1821 if (vp
->v_type
== VFIFO
)
1824 lockmgr_printinfo(&ip
->i_lock
);
1830 * Read wrapper for special devices.
1834 struct vop_read_args
/* {
1838 struct ucred *a_cred;
1845 VTOI(ap
->a_vp
)->i_flag
|= IN_ACCESS
;
1846 return (VOCALL (spec_vnodeop_p
, VOFFSET(vop_read
), ap
));
1850 * Write wrapper for special devices.
1854 struct vop_write_args
/* {
1858 struct ucred *a_cred;
1863 * Set update and change flags.
1865 VTOI(ap
->a_vp
)->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1866 return (VOCALL (spec_vnodeop_p
, VOFFSET(vop_write
), ap
));
1870 * Close wrapper for special devices.
1872 * Update the times on the inode then do device close.
1876 struct vop_close_args
/* {
1879 struct ucred *a_cred;
1883 struct vnode
*vp
= ap
->a_vp
;
1884 struct inode
*ip
= VTOI(vp
);
1886 simple_lock(&vp
->v_interlock
);
1887 if (ap
->a_vp
->v_usecount
> 1)
1888 ITIMES(ip
, &time
, &time
);
1889 simple_unlock(&vp
->v_interlock
);
1890 return (VOCALL (spec_vnodeop_p
, VOFFSET(vop_close
), ap
));
1895 * Read wrapper for fifo's
1899 struct vop_read_args
/* {
1903 struct ucred *a_cred;
1906 extern int (**fifo_vnodeop_p
)(void *);
1911 VTOI(ap
->a_vp
)->i_flag
|= IN_ACCESS
;
1912 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vop_read
), ap
));
1916 * Write wrapper for fifo's.
1920 struct vop_write_args
/* {
1924 struct ucred *a_cred;
1927 extern int (**fifo_vnodeop_p
)(void *);
1930 * Set update and change flags.
1932 VTOI(ap
->a_vp
)->i_flag
|= IN_CHANGE
| IN_UPDATE
;
1933 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vop_write
), ap
));
1937 * Close wrapper for fifo's.
1939 * Update the times on the inode then do device close.
1942 struct vop_close_args
/* {
1945 struct ucred *a_cred;
1949 extern int (**fifo_vnodeop_p
)(void *);
1950 struct vnode
*vp
= ap
->a_vp
;
1951 struct inode
*ip
= VTOI(vp
);
1953 simple_lock(&vp
->v_interlock
);
1954 if (ap
->a_vp
->v_usecount
> 1)
1955 ITIMES(ip
, &time
, &time
);
1956 simple_unlock(&vp
->v_interlock
);
1957 return (VOCALL (fifo_vnodeop_p
, VOFFSET(vop_close
), ap
));
1962 * Return POSIX pathconf information applicable to ufs filesystems.
1965 struct vop_pathconf_args
/* {
1972 switch (ap
->a_name
) {
1974 *ap
->a_retval
= LINK_MAX
;
1977 *ap
->a_retval
= NAME_MAX
;
1980 *ap
->a_retval
= PATH_MAX
;
1983 *ap
->a_retval
= PIPE_BUF
;
1985 case _PC_CHOWN_RESTRICTED
:
1998 * Advisory record locking support
2002 struct vop_advlock_args
/* {
2010 register struct inode
*ip
= VTOI(ap
->a_vp
);
2011 register struct flock
*fl
= ap
->a_fl
;
2012 register struct lockf
*lock
;
2017 * Avoid the common case of unlocking when inode has no locks.
2019 if (ip
->i_lockf
== (struct lockf
*)0) {
2020 if (ap
->a_op
!= F_SETLK
) {
2021 fl
->l_type
= F_UNLCK
;
2026 * Convert the flock structure into a start and end.
2028 switch (fl
->l_whence
) {
2033 * Caller is responsible for adding any necessary offset
2034 * when SEEK_CUR is used.
2036 start
= fl
->l_start
;
2040 start
= ip
->i_size
+ fl
->l_start
;
2051 end
= start
+ fl
->l_len
- 1;
2053 * Create the lockf structure
2055 MALLOC(lock
, struct lockf
*, sizeof *lock
, M_LOCKF
, M_WAITOK
);
2056 lock
->lf_start
= start
;
2058 lock
->lf_id
= ap
->a_id
;
2059 lock
->lf_inode
= ip
;
2060 lock
->lf_type
= fl
->l_type
;
2061 lock
->lf_next
= (struct lockf
*)0;
2062 TAILQ_INIT(&lock
->lf_blkhd
);
2063 lock
->lf_flags
= ap
->a_flags
;
2065 * Do the requested operation.
2069 return (lf_setlock(lock
));
2072 error
= lf_clearlock(lock
);
2073 FREE(lock
, M_LOCKF
);
2077 error
= lf_getlock(lock
, fl
);
2078 FREE(lock
, M_LOCKF
);
2082 _FREE(lock
, M_LOCKF
);
2089 * Initialize the vnode associated with a new inode, handle aliased
2093 ufs_vinit(mntp
, specops
, fifoops
, vpp
)
2099 struct proc
*p
= current_proc(); /* XXX */
2101 struct vnode
*vp
, *nvp
;
2105 switch(vp
->v_type
= IFTOVT(ip
->i_mode
)) {
2109 if (nvp
= checkalias(vp
, ip
->i_rdev
, mntp
)) {
2111 * Discard unneeded vnode, but save its inode.
2112 * Note that the lock is carried over in the inode
2113 * to the replacement vnode.
2115 nvp
->v_data
= vp
->v_data
;
2117 vp
->v_op
= spec_vnodeop_p
;
2121 * Reinitialize aliased inode.
2132 return (EOPNOTSUPP
);
2142 if (ip
->i_number
== ROOTINO
)
2143 vp
->v_flag
|= VROOT
;
2145 * Initialize modrev times
2147 SETHIGH(ip
->i_modrev
, time
.tv_sec
);
2148 SETLOW(ip
->i_modrev
, time
.tv_usec
* 4294);
2154 * Allocate a new inode.
2157 ufs_makeinode(mode
, dvp
, vpp
, cnp
)
2161 struct componentname
*cnp
;
2163 register struct inode
*ip
, *pdir
;
2170 if ((cnp
->cn_flags
& HASBUF
) == 0)
2171 panic("ufs_makeinode: no name");
2174 if ((mode
& IFMT
) == 0)
2177 if (error
= VOP_VALLOC(dvp
, mode
, cnp
->cn_cred
, &tvp
)) {
2178 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2183 ip
->i_gid
= pdir
->i_gid
;
2184 if ((mode
& IFMT
) == IFLNK
)
2185 ip
->i_uid
= pdir
->i_uid
;
2187 ip
->i_uid
= cnp
->cn_cred
->cr_uid
;
2189 if ((error
= getinoquota(ip
)) ||
2190 (error
= chkiq(ip
, 1, cnp
->cn_cred
, 0))) {
2191 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2192 VOP_VFREE(tvp
, ip
->i_number
, mode
);
2198 ip
->i_flag
|= IN_ACCESS
| IN_CHANGE
| IN_UPDATE
;
2200 tvp
->v_type
= IFTOVT(mode
); /* Rest init'd in getnewvnode(). */
2202 if ((ip
->i_mode
& ISGID
) && !groupmember(ip
->i_gid
, cnp
->cn_cred
) &&
2203 suser(cnp
->cn_cred
, NULL
))
2204 ip
->i_mode
&= ~ISGID
;
2206 if (cnp
->cn_flags
& ISWHITEOUT
)
2207 ip
->i_flags
|= UF_OPAQUE
;
2210 * initialize UBC before calling VOP_UPDATE and ufs_direnter
2211 * Not doing so introduces probelms in handling error from
2213 * It results in a "vget: stolen ubc_info" panic due to attempt
2214 * to shutdown uninitialized UBC.
2216 if (UBCINFOMISSING(tvp
) || UBCINFORECLAIMED(tvp
))
2220 * Make sure inode goes to disk before directory entry.
2223 if (error
= VOP_UPDATE(tvp
, &tv
, &tv
, 1))
2225 if (error
= ufs_direnter(ip
, dvp
, cnp
))
2227 if ((cnp
->cn_flags
& SAVESTART
) == 0)
2228 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2236 * Write error occurred trying to update the inode
2237 * or the directory so must deallocate the inode.
2239 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2242 ip
->i_flag
|= IN_CHANGE
;