<sys/wait.h>: Provide and use siginfo_t and union sigval.
[dragonfly.git] / sys / vfs / ufs / ufs_vnops.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
dc71b7ab 18 * 3. Neither the name of the University nor the names of its contributors
984263bc
MD
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
35 * $FreeBSD: src/sys/ufs/ufs/ufs_vnops.c,v 1.131.2.8 2003/01/02 17:26:19 bde Exp $
36 */
37
38#include "opt_quota.h"
39#include "opt_suiddir.h"
40#include "opt_ufs.h"
41
42#include <sys/param.h>
43#include <sys/systm.h>
13dd34d8 44#include <sys/uio.h>
984263bc
MD
45#include <sys/kernel.h>
46#include <sys/fcntl.h>
47#include <sys/stat.h>
48#include <sys/buf.h>
49#include <sys/proc.h>
895c1f85 50#include <sys/priv.h>
dadab5e9 51#include <sys/namei.h>
984263bc
MD
52#include <sys/mount.h>
53#include <sys/unistd.h>
54#include <sys/vnode.h>
55#include <sys/malloc.h>
56#include <sys/dirent.h>
57#include <sys/lockf.h>
58#include <sys/event.h>
59#include <sys/conf.h>
60
61#include <sys/file.h> /* XXX */
21c8b4bd 62#include <sys/jail.h>
984263bc
MD
63
64#include <vm/vm.h>
65#include <vm/vm_extern.h>
66
1f2de5d4 67#include <vfs/fifofs/fifo.h>
984263bc 68
1f2de5d4
MD
69#include "quota.h"
70#include "inode.h"
71#include "dir.h"
72#include "ufsmount.h"
73#include "ufs_extern.h"
ac690a1d 74#include "ffs_extern.h"
b0d18f7d 75#include "fs.h"
984263bc 76#ifdef UFS_DIRHASH
1f2de5d4 77#include "dirhash.h"
984263bc
MD
78#endif
79
a6ee311a
RG
80static int ufs_access (struct vop_access_args *);
81static int ufs_advlock (struct vop_advlock_args *);
87de5057
MD
82static int ufs_chmod (struct vnode *, int, struct ucred *);
83static int ufs_chown (struct vnode *, uid_t, gid_t, struct ucred *);
a6ee311a 84static int ufs_close (struct vop_close_args *);
e62afb5f 85static int ufs_create (struct vop_old_create_args *);
a6ee311a 86static int ufs_getattr (struct vop_getattr_args *);
e62afb5f 87static int ufs_link (struct vop_old_link_args *);
a6ee311a 88static int ufs_makeinode (int mode, struct vnode *, struct vnode **, struct componentname *);
349433c9 89static int ufs_markatime (struct vop_markatime_args *);
a6ee311a 90static int ufs_missingop (struct vop_generic_args *ap);
e62afb5f
MD
91static int ufs_mkdir (struct vop_old_mkdir_args *);
92static int ufs_mknod (struct vop_old_mknod_args *);
a6ee311a
RG
93static int ufs_print (struct vop_print_args *);
94static int ufs_readdir (struct vop_readdir_args *);
95static int ufs_readlink (struct vop_readlink_args *);
e62afb5f
MD
96static int ufs_remove (struct vop_old_remove_args *);
97static int ufs_rename (struct vop_old_rename_args *);
98static int ufs_rmdir (struct vop_old_rmdir_args *);
a6ee311a
RG
99static int ufs_setattr (struct vop_setattr_args *);
100static int ufs_strategy (struct vop_strategy_args *);
e62afb5f
MD
101static int ufs_symlink (struct vop_old_symlink_args *);
102static int ufs_whiteout (struct vop_old_whiteout_args *);
a6ee311a
RG
103static int ufsfifo_close (struct vop_close_args *);
104static int ufsfifo_kqfilter (struct vop_kqfilter_args *);
105static int ufsfifo_read (struct vop_read_args *);
106static int ufsfifo_write (struct vop_write_args *);
a6ee311a
RG
107static int filt_ufsread (struct knote *kn, long hint);
108static int filt_ufswrite (struct knote *kn, long hint);
109static int filt_ufsvnode (struct knote *kn, long hint);
110static void filt_ufsdetach (struct knote *kn);
111static int ufs_kqfilter (struct vop_kqfilter_args *ap);
984263bc 112
984263bc 113#define VN_KNOTE(vp, b) \
5b22f1a7 114 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, (b))
984263bc 115
e088dc32
JS
116#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
117
984263bc
MD
118/*
119 * A virgin directory (no blushing please).
120 */
121static struct dirtemplate mastertemplate = {
122 0, 12, DT_DIR, 1, ".",
123 0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
124};
125static struct odirtemplate omastertemplate = {
126 0, 12, 1, ".",
127 0, DIRBLKSIZ - 12, 2, ".."
128};
129
130void
0973c589 131ufs_itimes(struct vnode *vp)
984263bc
MD
132{
133 struct inode *ip;
134 struct timespec ts;
135
136 ip = VTOI(vp);
137 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
138 return;
139 if ((vp->v_type == VBLK || vp->v_type == VCHR) && !DOINGSOFTDEP(vp))
140 ip->i_flag |= IN_LAZYMOD;
141 else
142 ip->i_flag |= IN_MODIFIED;
723be147 143
984263bc
MD
144 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
145 vfs_timestamp(&ts);
146 if (ip->i_flag & IN_ACCESS) {
712774a1
MD
147 ip->i_atime = (uint32_t)ts.tv_sec;
148 ip->i_atime_ext = ts.tv_sec >> 32;
984263bc
MD
149 ip->i_atimensec = ts.tv_nsec;
150 }
723be147 151 if (ip->i_flag & IN_CHANGE) {
712774a1
MD
152 ip->i_ctime = (uint32_t)ts.tv_sec;
153 ip->i_ctime_ext = ts.tv_sec >> 32;
723be147
MD
154 ip->i_ctimensec = ts.tv_nsec;
155 }
984263bc 156 if (ip->i_flag & IN_UPDATE) {
fa4a12c4
MD
157 if (ip->i_flag & IN_NOCOPYWRITE) {
158 if (vp->v_flag & VLASTWRITETS) {
712774a1
MD
159 ip->i_mtime = (uint32_t)
160 vp->v_lastwrite_ts.tv_sec;
161 ip->i_mtime_ext =
162 vp->v_lastwrite_ts.tv_sec >> 32;
fa4a12c4
MD
163 ip->i_mtimensec =
164 vp->v_lastwrite_ts.tv_nsec;
165 }
166 } else {
712774a1
MD
167 ip->i_mtime = (uint32_t)ts.tv_sec;
168 ip->i_mtime_ext = ts.tv_sec >> 32;
fa4a12c4 169 ip->i_mtimensec = ts.tv_nsec;
723be147 170 }
984263bc
MD
171 ip->i_modrev++;
172 }
984263bc
MD
173 }
174 ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
175}
176
177/*
178 * Create a regular file
0973c589
CP
179 *
180 * ufs_create(struct vnode *a_dvp, struct vnode **a_vpp,
181 * struct componentname *a_cnp, struct vattr *a_vap)
984263bc 182 */
0961aa92 183static
984263bc 184int
e62afb5f 185ufs_create(struct vop_old_create_args *ap)
984263bc
MD
186{
187 int error;
188
189 error =
190 ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
191 ap->a_dvp, ap->a_vpp, ap->a_cnp);
192 if (error)
193 return (error);
194 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
195 return (0);
196}
197
198/*
199 * Mknod vnode call
0973c589
CP
200 *
201 * ufs_mknod(struct vnode *a_dvp, struct vnode **a_vpp,
202 * struct componentname *a_cnp, struct vattr *a_vap)
984263bc
MD
203 */
204/* ARGSUSED */
0961aa92 205static
984263bc 206int
e62afb5f 207ufs_mknod(struct vop_old_mknod_args *ap)
984263bc
MD
208{
209 struct vattr *vap = ap->a_vap;
210 struct vnode **vpp = ap->a_vpp;
211 struct inode *ip;
212 ino_t ino;
213 int error;
214
0e9b9130
MD
215 /*
216 * UFS cannot represent the entire major/minor range supported by
217 * the kernel.
218 */
219 if (vap->va_rmajor != VNOVAL &&
220 makeudev(vap->va_rmajor, vap->va_rminor) == NOUDEV) {
221 return(EINVAL);
222 }
223
c0515afc
MD
224 /* no special directory support */
225 if (vap->va_type == VDIR)
226 return(EINVAL);
227
984263bc
MD
228 error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
229 ap->a_dvp, vpp, ap->a_cnp);
230 if (error)
231 return (error);
232 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
233 ip = VTOI(*vpp);
234 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
0e9b9130 235 if (vap->va_rmajor != VNOVAL) {
984263bc
MD
236 /*
237 * Want to be able to use this to make badblock
238 * inodes, so don't truncate the dev number.
239 */
0e9b9130 240 ip->i_rdev = makeudev(vap->va_rmajor, vap->va_rminor);
984263bc
MD
241 }
242 /*
243 * Remove inode, then reload it through VFS_VGET so it is
244 * checked to see if it is an alias of an existing entry in
245 * the inode cache.
246 */
984263bc
MD
247 (*vpp)->v_type = VNON;
248 ino = ip->i_number; /* Save this before vgone() invalidates ip. */
3c37c940 249 vgone_vxlocked(*vpp);
5fd012e0 250 vput(*vpp);
b9b0a6d0 251 error = VFS_VGET(ap->a_dvp->v_mount, NULL, ino, vpp);
984263bc
MD
252 if (error) {
253 *vpp = NULL;
254 return (error);
255 }
256 return (0);
257}
258
984263bc
MD
259/*
260 * Close called.
261 *
262 * Update the times on the inode.
0973c589 263 *
b478fdce 264 * ufs_close(struct vnode *a_vp, int a_fflag)
984263bc
MD
265 */
266/* ARGSUSED */
0961aa92 267static
984263bc 268int
0973c589 269ufs_close(struct vop_close_args *ap)
984263bc 270{
3ff2135f 271 struct vnode *vp = ap->a_vp;
984263bc 272
ee173d09 273 if (VREFCNT(vp) > 1)
984263bc 274 ufs_itimes(vp);
8ddc6004 275 return (vop_stdclose(ap));
984263bc
MD
276}
277
0973c589 278/*
b478fdce 279 * ufs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred)
0973c589 280 */
0961aa92 281static
984263bc 282int
0973c589 283ufs_access(struct vop_access_args *ap)
984263bc
MD
284{
285 struct vnode *vp = ap->a_vp;
286 struct inode *ip = VTOI(vp);
984263bc 287 int error;
984263bc 288
795ecc74
NT
289#ifdef QUOTA
290 if (ap->a_mode & VWRITE) {
984263bc
MD
291 switch (vp->v_type) {
292 case VDIR:
293 case VLNK:
294 case VREG:
50e58362 295 if ((error = ufs_getinoquota(ip)) != 0)
984263bc 296 return (error);
984263bc
MD
297 break;
298 default:
299 break;
300 }
301 }
3a907475 302#endif
984263bc 303
795ecc74
NT
304 error = vop_helper_access(ap, ip->i_uid, ip->i_gid, ip->i_mode, 0);
305 return (error);
984263bc
MD
306}
307
0973c589 308/*
b478fdce 309 * ufs_getattr(struct vnode *a_vp, struct vattr *a_vap)
0973c589 310 */
984263bc 311/* ARGSUSED */
0961aa92 312static
984263bc 313int
0973c589 314ufs_getattr(struct vop_getattr_args *ap)
984263bc 315{
3ff2135f
RG
316 struct vnode *vp = ap->a_vp;
317 struct inode *ip = VTOI(vp);
318 struct vattr *vap = ap->a_vap;
984263bc
MD
319
320 ufs_itimes(vp);
321 /*
322 * Copy from inode table
323 */
324 vap->va_fsid = dev2udev(ip->i_dev);
325 vap->va_fileid = ip->i_number;
326 vap->va_mode = ip->i_mode & ~IFMT;
327 vap->va_nlink = VFSTOUFS(vp->v_mount)->um_i_effnlink_valid ?
328 ip->i_effnlink : ip->i_nlink;
329 vap->va_uid = ip->i_uid;
330 vap->va_gid = ip->i_gid;
0e9b9130
MD
331 vap->va_rmajor = umajor(ip->i_rdev);
332 vap->va_rminor = uminor(ip->i_rdev);
984263bc 333 vap->va_size = ip->i_din.di_size;
712774a1
MD
334 vap->va_atime.tv_sec =
335 (time_t)(ip->i_atime | ((uint64_t)ip->i_atime_ext << 32));
984263bc 336 vap->va_atime.tv_nsec = ip->i_atimensec;
712774a1
MD
337 vap->va_mtime.tv_sec =
338 (time_t)(ip->i_mtime | ((uint64_t)ip->i_mtime_ext << 32));
984263bc 339 vap->va_mtime.tv_nsec = ip->i_mtimensec;
712774a1
MD
340 vap->va_ctime.tv_sec =
341 (time_t)(ip->i_ctime | ((uint64_t)ip->i_ctime_ext << 32));
984263bc
MD
342 vap->va_ctime.tv_nsec = ip->i_ctimensec;
343 vap->va_flags = ip->i_flags;
344 vap->va_gen = ip->i_gen;
345 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
346 vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
347 vap->va_type = IFTOVT(ip->i_mode);
348 vap->va_filerev = ip->i_modrev;
349 return (0);
350}
351
349433c9
MD
352static
353int
354ufs_markatime(struct vop_markatime_args *ap)
355{
356 struct vnode *vp = ap->a_vp;
357 struct inode *ip = VTOI(vp);
358
359 if (vp->v_mount->mnt_flag & MNT_RDONLY)
360 return (EROFS);
361 if (vp->v_mount->mnt_flag & MNT_NOATIME)
362 return (0);
363 ip->i_flag |= IN_ACCESS;
364 VN_KNOTE(vp, NOTE_ATTRIB);
365 return (0);
366}
367
984263bc
MD
368/*
369 * Set attribute vnode op. called from several syscalls
0973c589
CP
370 *
371 * ufs_setattr(struct vnode *a_vp, struct vattr *a_vap,
b478fdce 372 * struct ucred *a_cred)
984263bc 373 */
0961aa92 374static
984263bc 375int
0973c589 376ufs_setattr(struct vop_setattr_args *ap)
984263bc
MD
377{
378 struct vattr *vap = ap->a_vap;
379 struct vnode *vp = ap->a_vp;
380 struct inode *ip = VTOI(vp);
381 struct ucred *cred = ap->a_cred;
984263bc
MD
382 int error;
383
384 /*
385 * Check for unsettable attributes.
386 */
387 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
388 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
0e9b9130 389 (vap->va_blocksize != VNOVAL) || (vap->va_rmajor != VNOVAL) ||
984263bc
MD
390 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
391 return (EINVAL);
392 }
393 if (vap->va_flags != VNOVAL) {
394 if (vp->v_mount->mnt_flag & MNT_RDONLY)
395 return (EROFS);
396 if (cred->cr_uid != ip->i_uid &&
db813a0c 397 (error = priv_check_cred(cred, PRIV_VFS_SETATTR, 0)))
984263bc 398 return (error);
21c8b4bd
MD
399 /*
400 * Note that a root chflags becomes a user chflags when
401 * we are jailed, unless the jail.chflags_allowed sysctl
402 * is set.
403 */
404 if (cred->cr_uid == 0 &&
405 (!jailed(cred) || jail_chflags_allowed)) {
984263bc
MD
406 if ((ip->i_flags
407 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) &&
408 securelevel > 0)
409 return (EPERM);
410 ip->i_flags = vap->va_flags;
411 } else {
412 if (ip->i_flags
413 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
414 (vap->va_flags & UF_SETTABLE) != vap->va_flags)
415 return (EPERM);
416 ip->i_flags &= SF_SETTABLE;
417 ip->i_flags |= (vap->va_flags & UF_SETTABLE);
418 }
419 ip->i_flag |= IN_CHANGE;
420 if (vap->va_flags & (IMMUTABLE | APPEND))
421 return (0);
422 }
423 if (ip->i_flags & (IMMUTABLE | APPEND))
424 return (EPERM);
425 /*
426 * Go through the fields and update iff not VNOVAL.
427 */
428 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
429 if (vp->v_mount->mnt_flag & MNT_RDONLY)
430 return (EROFS);
87de5057 431 if ((error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred)) != 0)
984263bc
MD
432 return (error);
433 }
434 if (vap->va_size != VNOVAL) {
435 /*
f719c866 436 * Disallow write attempts on read-only filesystems;
984263bc 437 * unless the file is a socket, fifo, or a block or
f719c866 438 * character device resident on the filesystem.
984263bc
MD
439 */
440 switch (vp->v_type) {
441 case VDIR:
442 return (EISDIR);
443 case VLNK:
444 case VREG:
445 if (vp->v_mount->mnt_flag & MNT_RDONLY)
446 return (EROFS);
447 break;
448 default:
449 break;
450 }
ac690a1d 451 if ((error = ffs_truncate(vp, vap->va_size, 0, cred)) != 0)
984263bc
MD
452 return (error);
453 }
454 ip = VTOI(vp);
455 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
456 if (vp->v_mount->mnt_flag & MNT_RDONLY)
457 return (EROFS);
458 if (cred->cr_uid != ip->i_uid &&
db813a0c 459 (error = priv_check_cred(cred, PRIV_VFS_SETATTR, 0)) &&
984263bc 460 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
cb66845a 461 (error = VOP_EACCESS(vp, VWRITE, cred))))
984263bc
MD
462 return (error);
463 if (vap->va_atime.tv_sec != VNOVAL)
464 ip->i_flag |= IN_ACCESS;
465 if (vap->va_mtime.tv_sec != VNOVAL)
466 ip->i_flag |= IN_CHANGE | IN_UPDATE;
467 ufs_itimes(vp);
468 if (vap->va_atime.tv_sec != VNOVAL) {
712774a1
MD
469 ip->i_atime = (uint32_t)vap->va_atime.tv_sec;
470 ip->i_atime_ext = vap->va_atime.tv_sec >> 32;
984263bc
MD
471 ip->i_atimensec = vap->va_atime.tv_nsec;
472 }
473 if (vap->va_mtime.tv_sec != VNOVAL) {
712774a1
MD
474 ip->i_mtime = (uint32_t)vap->va_mtime.tv_sec;
475 ip->i_mtime_ext = vap->va_mtime.tv_sec >> 32;
984263bc 476 ip->i_mtimensec = vap->va_mtime.tv_nsec;
fa4a12c4 477 vclrflags(vp, VLASTWRITETS);
984263bc 478 }
ac690a1d 479 error = ffs_update(vp, 0);
984263bc
MD
480 if (error)
481 return (error);
482 }
483 error = 0;
484 if (vap->va_mode != (mode_t)VNOVAL) {
485 if (vp->v_mount->mnt_flag & MNT_RDONLY)
486 return (EROFS);
87de5057 487 error = ufs_chmod(vp, (int)vap->va_mode, cred);
984263bc
MD
488 }
489 VN_KNOTE(vp, NOTE_ATTRIB);
490 return (error);
491}
492
493/*
494 * Change the mode on a file.
495 * Inode must be locked before calling.
496 */
497static int
87de5057 498ufs_chmod(struct vnode *vp, int mode, struct ucred *cred)
984263bc 499{
3ff2135f 500 struct inode *ip = VTOI(vp);
984263bc 501 int error;
cd65363e 502 mode_t cur_mode = ip->i_mode;
984263bc 503
cd65363e
MD
504 error = vop_helper_chmod(vp, mode, cred, ip->i_uid, ip->i_gid,
505 &cur_mode);
506 if (error)
507 return (error);
508#if 0
984263bc 509 if (cred->cr_uid != ip->i_uid) {
b6a1a081 510 error = priv_check_cred(cred, PRIV_VFS_CHMOD, 0);
984263bc
MD
511 if (error)
512 return (error);
513 }
514 if (cred->cr_uid) {
515 if (vp->v_type != VDIR && (mode & S_ISTXT))
516 return (EFTYPE);
517 if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
518 return (EPERM);
519 }
cd65363e
MD
520#endif
521 ip->i_mode = cur_mode;
984263bc
MD
522 ip->i_flag |= IN_CHANGE;
523 return (0);
524}
525
526/*
527 * Perform chown operation on inode ip;
528 * inode must be locked prior to call.
529 */
530static int
87de5057 531ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred)
984263bc 532{
3ff2135f 533 struct inode *ip = VTOI(vp);
984263bc
MD
534 uid_t ouid;
535 gid_t ogid;
536 int error = 0;
537#ifdef QUOTA
3ff2135f 538 int i;
984263bc
MD
539 long change;
540#endif
541
542 if (uid == (uid_t)VNOVAL)
543 uid = ip->i_uid;
544 if (gid == (gid_t)VNOVAL)
545 gid = ip->i_gid;
546 /*
547 * If we don't own the file, are trying to change the owner
548 * of the file, or are not a member of the target group,
549 * the caller must be superuser or the call fails.
550 */
551 if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
a10e3626 552 (gid != ip->i_gid && !(cred->cr_gid == gid ||
ad23467e 553 groupmember(gid, cred)))) &&
b6a1a081 554 (error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0)))
984263bc
MD
555 return (error);
556 ogid = ip->i_gid;
557 ouid = ip->i_uid;
558#ifdef QUOTA
50e58362 559 if ((error = ufs_getinoquota(ip)) != 0)
984263bc
MD
560 return (error);
561 if (ouid == uid) {
50e58362 562 ufs_dqrele(vp, ip->i_dquot[USRQUOTA]);
984263bc
MD
563 ip->i_dquot[USRQUOTA] = NODQUOT;
564 }
565 if (ogid == gid) {
50e58362 566 ufs_dqrele(vp, ip->i_dquot[GRPQUOTA]);
984263bc
MD
567 ip->i_dquot[GRPQUOTA] = NODQUOT;
568 }
569 change = ip->i_blocks;
50e58362
MD
570 (void) ufs_chkdq(ip, -change, cred, CHOWN);
571 (void) ufs_chkiq(ip, -1, cred, CHOWN);
984263bc 572 for (i = 0; i < MAXQUOTAS; i++) {
50e58362 573 ufs_dqrele(vp, ip->i_dquot[i]);
984263bc
MD
574 ip->i_dquot[i] = NODQUOT;
575 }
576#endif
577 ip->i_gid = gid;
578 ip->i_uid = uid;
579#ifdef QUOTA
50e58362 580 if ((error = ufs_getinoquota(ip)) == 0) {
984263bc 581 if (ouid == uid) {
50e58362 582 ufs_dqrele(vp, ip->i_dquot[USRQUOTA]);
984263bc
MD
583 ip->i_dquot[USRQUOTA] = NODQUOT;
584 }
585 if (ogid == gid) {
50e58362 586 ufs_dqrele(vp, ip->i_dquot[GRPQUOTA]);
984263bc
MD
587 ip->i_dquot[GRPQUOTA] = NODQUOT;
588 }
50e58362
MD
589 if ((error = ufs_chkdq(ip, change, cred, CHOWN)) == 0) {
590 if ((error = ufs_chkiq(ip, 1, cred, CHOWN)) == 0)
984263bc
MD
591 goto good;
592 else
50e58362 593 (void)ufs_chkdq(ip, -change, cred, CHOWN|FORCE);
984263bc
MD
594 }
595 for (i = 0; i < MAXQUOTAS; i++) {
50e58362 596 ufs_dqrele(vp, ip->i_dquot[i]);
984263bc
MD
597 ip->i_dquot[i] = NODQUOT;
598 }
599 }
600 ip->i_gid = ogid;
601 ip->i_uid = ouid;
50e58362 602 if (ufs_getinoquota(ip) == 0) {
984263bc 603 if (ouid == uid) {
50e58362 604 ufs_dqrele(vp, ip->i_dquot[USRQUOTA]);
984263bc
MD
605 ip->i_dquot[USRQUOTA] = NODQUOT;
606 }
607 if (ogid == gid) {
50e58362 608 ufs_dqrele(vp, ip->i_dquot[GRPQUOTA]);
984263bc
MD
609 ip->i_dquot[GRPQUOTA] = NODQUOT;
610 }
50e58362
MD
611 (void) ufs_chkdq(ip, change, cred, FORCE|CHOWN);
612 (void) ufs_chkiq(ip, 1, cred, FORCE|CHOWN);
613 (void) ufs_getinoquota(ip);
984263bc
MD
614 }
615 return (error);
616good:
50e58362 617 if (ufs_getinoquota(ip))
984263bc
MD
618 panic("ufs_chown: lost quota");
619#endif /* QUOTA */
620 ip->i_flag |= IN_CHANGE;
621 if (cred->cr_uid != 0 && (ouid != uid || ogid != gid))
622 ip->i_mode &= ~(ISUID | ISGID);
623 return (0);
624}
625
0973c589
CP
626/*
627 * ufs_remove(struct vnode *a_dvp, struct vnode *a_vp,
628 * struct componentname *a_cnp)
629 */
0961aa92 630static
984263bc 631int
e62afb5f 632ufs_remove(struct vop_old_remove_args *ap)
984263bc
MD
633{
634 struct inode *ip;
635 struct vnode *vp = ap->a_vp;
636 struct vnode *dvp = ap->a_dvp;
637 int error;
638
639 ip = VTOI(vp);
3a907475 640#if 0 /* handled by kernel now */
984263bc
MD
641 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
642 (VTOI(dvp)->i_flags & APPEND)) {
643 error = EPERM;
644 goto out;
645 }
3a907475 646#endif
984263bc
MD
647 error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
648 VN_KNOTE(vp, NOTE_DELETE);
649 VN_KNOTE(dvp, NOTE_WRITE);
3a907475 650#if 0
984263bc 651out:
3a907475 652#endif
984263bc
MD
653 return (error);
654}
655
656/*
657 * link vnode call
0973c589
CP
658 *
659 * ufs_link(struct vnode *a_tdvp, struct vnode *a_vp,
660 * struct componentname *a_cnp)
984263bc 661 */
0961aa92 662static
984263bc 663int
e62afb5f 664ufs_link(struct vop_old_link_args *ap)
984263bc
MD
665{
666 struct vnode *vp = ap->a_vp;
667 struct vnode *tdvp = ap->a_tdvp;
668 struct componentname *cnp = ap->a_cnp;
984263bc
MD
669 struct inode *ip;
670 struct direct newdir;
671 int error;
672
984263bc
MD
673 if (tdvp->v_mount != vp->v_mount) {
674 error = EXDEV;
675 goto out2;
676 }
b458d1ab
MD
677 if (tdvp != vp) {
678 error = vn_lock(vp, LK_EXCLUSIVE | LK_FAILRECLAIM);
679 if (error)
680 goto out2;
984263bc
MD
681 }
682 ip = VTOI(vp);
683 if ((nlink_t)ip->i_nlink >= LINK_MAX) {
684 error = EMLINK;
685 goto out1;
686 }
3a907475 687#if 0 /* handled by kernel now, also DragonFly allows this */
984263bc
MD
688 if (ip->i_flags & (IMMUTABLE | APPEND)) {
689 error = EPERM;
690 goto out1;
691 }
3a907475 692#endif
984263bc
MD
693 ip->i_effnlink++;
694 ip->i_nlink++;
695 ip->i_flag |= IN_CHANGE;
696 if (DOINGSOFTDEP(vp))
697 softdep_change_linkcnt(ip);
ac690a1d 698 error = ffs_update(vp, !(DOINGSOFTDEP(vp) | DOINGASYNC(vp)));
984263bc
MD
699 if (!error) {
700 ufs_makedirentry(ip, cnp, &newdir);
701 error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL);
702 }
703
704 if (error) {
705 ip->i_effnlink--;
706 ip->i_nlink--;
707 ip->i_flag |= IN_CHANGE;
708 if (DOINGSOFTDEP(vp))
709 softdep_change_linkcnt(ip);
710 }
711out1:
712 if (tdvp != vp)
a11aaa81 713 vn_unlock(vp);
984263bc
MD
714out2:
715 VN_KNOTE(vp, NOTE_LINK);
716 VN_KNOTE(tdvp, NOTE_WRITE);
717 return (error);
718}
719
720/*
721 * whiteout vnode call
0973c589
CP
722 *
723 * ufs_whiteout(struct vnode *a_dvp, struct componentname *a_cnp, int a_flags)
984263bc 724 */
0961aa92 725static
984263bc 726int
e62afb5f 727ufs_whiteout(struct vop_old_whiteout_args *ap)
984263bc
MD
728{
729 struct vnode *dvp = ap->a_dvp;
730 struct componentname *cnp = ap->a_cnp;
731 struct direct newdir;
732 int error = 0;
733
734 switch (ap->a_flags) {
2b69e610 735 case NAMEI_LOOKUP:
984263bc
MD
736 /* 4.4 format directories support whiteout operations */
737 if (dvp->v_mount->mnt_maxsymlinklen > 0)
738 return (0);
739 return (EOPNOTSUPP);
740
2b69e610 741 case NAMEI_CREATE:
984263bc
MD
742 /* create a new directory whiteout */
743#ifdef DIAGNOSTIC
984263bc
MD
744 if (dvp->v_mount->mnt_maxsymlinklen <= 0)
745 panic("ufs_whiteout: old format filesystem");
746#endif
747
c309c6d4 748 newdir.d_ino = UFS_WINO;
984263bc
MD
749 newdir.d_namlen = cnp->cn_namelen;
750 bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
751 newdir.d_type = DT_WHT;
752 error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL);
753 break;
754
2b69e610 755 case NAMEI_DELETE:
984263bc
MD
756 /* remove an existing directory whiteout */
757#ifdef DIAGNOSTIC
758 if (dvp->v_mount->mnt_maxsymlinklen <= 0)
759 panic("ufs_whiteout: old format filesystem");
760#endif
761
2b69e610 762 cnp->cn_flags &= ~CNP_DOWHITEOUT;
984263bc
MD
763 error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
764 break;
765 default:
766 panic("ufs_whiteout: unknown op");
767 }
768 return (error);
769}
770
771/*
772 * Rename system call.
773 * rename("foo", "bar");
774 * is essentially
775 * unlink("bar");
776 * link("foo", "bar");
777 * unlink("foo");
778 * but ``atomically''. Can't do full commit without saving state in the
779 * inode on disk which isn't feasible at this time. Best we can do is
780 * always guarantee the target exists.
781 *
782 * Basic algorithm is:
783 *
784 * 1) Bump link count on source while we're linking it to the
785 * target. This also ensure the inode won't be deleted out
786 * from underneath us while we work (it may be truncated by
787 * a concurrent `trunc' or `open' for creation).
788 * 2) Link source to destination. If destination already exists,
789 * delete it first.
790 * 3) Unlink source reference to inode if still around. If a
791 * directory was moved and the parent of the destination
792 * is different from the source, patch the ".." entry in the
793 * directory.
0973c589
CP
794 *
795 * ufs_rename(struct vnode *a_fdvp, struct vnode *a_fvp,
796 * struct componentname *a_fcnp, struct vnode *a_tdvp,
797 * struct vnode *a_tvp, struct componentname *a_tcnp)
984263bc 798 */
0961aa92 799static
984263bc 800int
e62afb5f 801ufs_rename(struct vop_old_rename_args *ap)
984263bc
MD
802{
803 struct vnode *tvp = ap->a_tvp;
3ff2135f 804 struct vnode *tdvp = ap->a_tdvp;
984263bc
MD
805 struct vnode *fvp = ap->a_fvp;
806 struct vnode *fdvp = ap->a_fdvp;
807 struct componentname *tcnp = ap->a_tcnp;
808 struct componentname *fcnp = ap->a_fcnp;
984263bc
MD
809 struct inode *ip, *xp, *dp;
810 struct direct newdir;
9ab06300
MD
811 ino_t oldparent = 0, newparent = 0;
812 int doingdirectory = 0;
984263bc
MD
813 int error = 0, ioflag;
814
984263bc
MD
815 /*
816 * Check for cross-device rename.
817 */
818 if ((fvp->v_mount != tdvp->v_mount) ||
819 (tvp && (fvp->v_mount != tvp->v_mount))) {
820 error = EXDEV;
821abortit:
822 if (tdvp == tvp)
823 vrele(tdvp);
824 else
825 vput(tdvp);
826 if (tvp)
827 vput(tvp);
828 vrele(fdvp);
829 vrele(fvp);
830 return (error);
831 }
832
3a907475 833#if 0 /* handled by kernel now */
984263bc
MD
834 if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
835 (VTOI(tdvp)->i_flags & APPEND))) {
836 error = EPERM;
837 goto abortit;
838 }
3a907475 839#endif
984263bc
MD
840
841 /*
842 * Renaming a file to itself has no effect. The upper layers should
843 * not call us in that case. Temporarily just warn if they do.
844 */
845 if (fvp == tvp) {
086c1d7e 846 kprintf("ufs_rename: fvp == tvp (can't happen)\n");
984263bc
MD
847 error = 0;
848 goto abortit;
849 }
850
b458d1ab
MD
851 error = vn_lock(fvp, LK_EXCLUSIVE | LK_FAILRECLAIM);
852 if (error)
984263bc 853 goto abortit;
fad57d0e
MD
854
855 /*
856 * Note: now that fvp is locked we have to be sure to unlock it before
857 * using the 'abortit' target.
858 */
984263bc
MD
859 dp = VTOI(fdvp);
860 ip = VTOI(fvp);
861 if (ip->i_nlink >= LINK_MAX) {
a11aaa81 862 vn_unlock(fvp);
984263bc
MD
863 error = EMLINK;
864 goto abortit;
865 }
3a907475 866#if 0 /* handled by kernel now */
984263bc
MD
867 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
868 || (dp->i_flags & APPEND)) {
a11aaa81 869 vn_unlock(fvp);
984263bc
MD
870 error = EPERM;
871 goto abortit;
872 }
3a907475 873#endif
984263bc
MD
874 if ((ip->i_mode & IFMT) == IFDIR) {
875 /*
876 * Avoid ".", "..", and aliases of "." for obvious reasons.
877 */
878 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
2b69e610 879 dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & CNP_ISDOTDOT ||
984263bc 880 (ip->i_flag & IN_RENAME)) {
a11aaa81 881 vn_unlock(fvp);
984263bc
MD
882 error = EINVAL;
883 goto abortit;
884 }
885 ip->i_flag |= IN_RENAME;
886 oldparent = dp->i_number;
887 doingdirectory = 1;
888 }
889 VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */
984263bc
MD
890
891 /*
fad57d0e
MD
892 * fvp still locked. ip->i_flag has IN_RENAME set if doingdirectory.
893 * Cleanup fvp requirements so we can unlock it.
894 *
895 * tvp and tdvp are locked. tvp may be NULL. Now that dp and xp
896 * is setup we can use the 'bad' target if we unlock fvp. We cannot
897 * use the abortit target anymore because of IN_RENAME.
984263bc
MD
898 */
899 dp = VTOI(tdvp);
984263bc
MD
900 if (tvp)
901 xp = VTOI(tvp);
fad57d0e
MD
902 else
903 xp = NULL;
984263bc
MD
904
905 /*
906 * 1) Bump link count while we're moving stuff
907 * around. If we crash somewhere before
908 * completing our work, the link count
909 * may be wrong, but correctable.
910 */
911 ip->i_effnlink++;
912 ip->i_nlink++;
913 ip->i_flag |= IN_CHANGE;
914 if (DOINGSOFTDEP(fvp))
915 softdep_change_linkcnt(ip);
ac690a1d 916 if ((error = ffs_update(fvp, !(DOINGSOFTDEP(fvp) |
984263bc 917 DOINGASYNC(fvp)))) != 0) {
a11aaa81 918 vn_unlock(fvp);
984263bc
MD
919 goto bad;
920 }
921
922 /*
923 * If ".." must be changed (ie the directory gets a new
924 * parent) then the source directory must not be in the
925 * directory heirarchy above the target, as this would
926 * orphan everything below the source directory. Also
927 * the user must have write permission in the source so
928 * as to be able to change "..". We must repeat the call
929 * to namei, as the parent directory is unlocked by the
930 * call to checkpath().
931 */
cb66845a 932 error = VOP_EACCESS(fvp, VWRITE, tcnp->cn_cred);
a11aaa81 933 vn_unlock(fvp);
fad57d0e
MD
934
935 /*
936 * We are now back to where we were in that fvp, fdvp are unlocked
937 * and tvp, tdvp are locked. tvp may be NULL. IN_RENAME may be
938 * set. Only the bad target or, if we clean up tvp and tdvp, the
939 * out target, may be used.
940 */
984263bc
MD
941 if (oldparent != dp->i_number)
942 newparent = dp->i_number;
943 if (doingdirectory && newparent) {
944 if (error) /* write access check above */
945 goto bad;
fad57d0e
MD
946
947 /*
948 * Once we start messing with tvp and tdvp we cannot use the
949 * 'bad' target, only finish cleaning tdvp and tvp up and
950 * use the 'out' target.
951 *
952 * This cleans up tvp.
953 */
954 if (xp != NULL) {
984263bc 955 vput(tvp);
fad57d0e
MD
956 xp = NULL;
957 }
958
959 /*
960 * This is a real mess. ufs_checkpath vput's the target
961 * directory so retain an extra ref and note that tdvp will
962 * lose its lock on return. This leaves us with one good
963 * ref after ufs_checkpath returns.
964 */
965 vref(tdvp);
984263bc 966 error = ufs_checkpath(ip, dp, tcnp->cn_cred);
fad57d0e
MD
967 tcnp->cn_flags |= CNP_PDIRUNLOCK;
968 if (error) {
969 vrele(tdvp);
984263bc 970 goto out;
fad57d0e
MD
971 }
972
973 /*
974 * relookup no longer messes with tdvp's refs. tdvp must be
975 * unlocked on entry and will be locked on a successful
976 * return.
977 */
984263bc 978 error = relookup(tdvp, &tvp, tcnp);
fad57d0e
MD
979 if (error) {
980 if (tcnp->cn_flags & CNP_PDIRUNLOCK)
981 vrele(tdvp);
982 else
983 vput(tdvp);
984263bc 984 goto out;
fad57d0e
MD
985 }
986 KKASSERT((tcnp->cn_flags & CNP_PDIRUNLOCK) == 0);
984263bc 987 dp = VTOI(tdvp);
984263bc
MD
988 if (tvp)
989 xp = VTOI(tvp);
990 }
fad57d0e
MD
991
992 /*
993 * We are back to fvp, fdvp unlocked, tvp, tdvp locked. tvp may
994 * be NULL (xp will also be NULL in that case), and IN_RENAME will
995 * be set if doingdirectory. This means we can use the 'bad' target
996 * again.
997 */
998
984263bc
MD
999 /*
1000 * 2) If target doesn't exist, link the target
1001 * to the source and unlink the source.
1002 * Otherwise, rewrite the target directory
1003 * entry to reference the source inode and
1004 * expunge the original entry's existence.
1005 */
1006 if (xp == NULL) {
1007 if (dp->i_dev != ip->i_dev)
1008 panic("ufs_rename: EXDEV");
1009 /*
1010 * Account for ".." in new directory.
1011 * When source and destination have the same
1012 * parent we don't fool with the link count.
1013 */
1014 if (doingdirectory && newparent) {
1015 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1016 error = EMLINK;
1017 goto bad;
1018 }
1019 dp->i_effnlink++;
1020 dp->i_nlink++;
1021 dp->i_flag |= IN_CHANGE;
1022 if (DOINGSOFTDEP(tdvp))
1023 softdep_change_linkcnt(dp);
ac690a1d 1024 error = ffs_update(tdvp, !(DOINGSOFTDEP(tdvp) |
984263bc
MD
1025 DOINGASYNC(tdvp)));
1026 if (error)
1027 goto bad;
1028 }
1029 ufs_makedirentry(ip, tcnp, &newdir);
1030 error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL);
1031 if (error) {
1032 if (doingdirectory && newparent) {
1033 dp->i_effnlink--;
1034 dp->i_nlink--;
1035 dp->i_flag |= IN_CHANGE;
1036 if (DOINGSOFTDEP(tdvp))
1037 softdep_change_linkcnt(dp);
ac690a1d 1038 (void)ffs_update(tdvp, 1);
984263bc
MD
1039 }
1040 goto bad;
1041 }
1042 VN_KNOTE(tdvp, NOTE_WRITE);
1043 vput(tdvp);
1044 } else {
1045 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1046 panic("ufs_rename: EXDEV");
1047 /*
1048 * Short circuit rename(foo, foo).
1049 */
1050 if (xp->i_number == ip->i_number)
1051 panic("ufs_rename: same file");
1052 /*
1053 * If the parent directory is "sticky", then the user must
1054 * own the parent directory, or the destination of the rename,
1055 * otherwise the destination may not be changed (except by
1056 * root). This implements append-only directories.
1057 */
1058 if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
1059 tcnp->cn_cred->cr_uid != dp->i_uid &&
1060 xp->i_uid != tcnp->cn_cred->cr_uid) {
1061 error = EPERM;
1062 goto bad;
1063 }
1064 /*
1065 * Target must be empty if a directory and have no links
1066 * to it. Also, ensure source and target are compatible
1067 * (both directories, or both not directories).
8e005a45
MD
1068 *
1069 * Purge the file or directory being replaced from the
1070 * nameccache.
984263bc
MD
1071 */
1072 if ((xp->i_mode&IFMT) == IFDIR) {
1073 if ((xp->i_effnlink > 2) ||
1074 !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
1075 error = ENOTEMPTY;
1076 goto bad;
1077 }
1078 if (!doingdirectory) {
1079 error = ENOTDIR;
1080 goto bad;
1081 }
fad57d0e 1082 /* cache_purge removed - handled by VFS compat layer */
8e005a45 1083 } else if (doingdirectory == 0) {
fad57d0e 1084 /* cache_purge removed - handled by VFS compat layer */
8e005a45 1085 } else {
984263bc
MD
1086 error = EISDIR;
1087 goto bad;
1088 }
9ab06300
MD
1089 /*
1090 * note: inode passed to ufs_dirrewrite() is 0 for a
1091 * non-directory file rename, 1 for a directory rename
1092 * in the same directory, and > 1 for an inode representing
1093 * the new directory.
1094 */
984263bc
MD
1095 error = ufs_dirrewrite(dp, xp, ip->i_number,
1096 IFTODT(ip->i_mode),
9ab06300
MD
1097 (doingdirectory && newparent) ?
1098 newparent : (ino_t)doingdirectory);
984263bc
MD
1099 if (error)
1100 goto bad;
1101 if (doingdirectory) {
1102 if (!newparent) {
1103 dp->i_effnlink--;
1104 if (DOINGSOFTDEP(tdvp))
1105 softdep_change_linkcnt(dp);
1106 }
1107 xp->i_effnlink--;
1108 if (DOINGSOFTDEP(tvp))
1109 softdep_change_linkcnt(xp);
1110 }
1111 if (doingdirectory && !DOINGSOFTDEP(tvp)) {
1112 /*
1113 * Truncate inode. The only stuff left in the directory
1114 * is "." and "..". The "." reference is inconsequential
1115 * since we are quashing it. We have removed the "."
1116 * reference and the reference in the parent directory,
1117 * but there may be other hard links. The soft
1118 * dependency code will arrange to do these operations
1119 * after the parent directory entry has been deleted on
1120 * disk, so when running with that code we avoid doing
1121 * them now.
1122 */
1123 if (!newparent) {
1124 dp->i_nlink--;
1125 dp->i_flag |= IN_CHANGE;
1126 }
1127 xp->i_nlink--;
1128 xp->i_flag |= IN_CHANGE;
1129 ioflag = DOINGASYNC(tvp) ? 0 : IO_SYNC;
ac690a1d 1130 error = ffs_truncate(tvp, (off_t)0, ioflag,
87de5057
MD
1131 tcnp->cn_cred);
1132 if (error)
984263bc
MD
1133 goto bad;
1134 }
1135 VN_KNOTE(tdvp, NOTE_WRITE);
1136 vput(tdvp);
1137 VN_KNOTE(tvp, NOTE_DELETE);
1138 vput(tvp);
1139 xp = NULL;
1140 }
1141
fad57d0e
MD
1142 /*
1143 * tvp and tdvp have been cleaned up. only fvp and fdvp (both
1144 * unlocked) remain. We are about to overwrite fvp but we have to
1145 * keep 'ip' intact so we cannot release the old fvp, which is still
1146 * refd and accessible via ap->a_fvp.
1147 *
1148 * This means we cannot use either 'bad' or 'out' to cleanup any
1149 * more.
1150 */
1151
984263bc
MD
1152 /*
1153 * 3) Unlink the source.
1154 */
2b69e610 1155 fcnp->cn_flags &= ~CNP_MODMASK;
fad57d0e 1156 fcnp->cn_flags |= CNP_LOCKPARENT;
984263bc 1157 error = relookup(fdvp, &fvp, fcnp);
fad57d0e 1158 if (error || fvp == NULL) {
984263bc 1159 /*
fad57d0e
MD
1160 * From name has disappeared. IN_RENAME will not be set if
1161 * we get past the panic so we don't have to clean it up.
984263bc
MD
1162 */
1163 if (doingdirectory)
1164 panic("ufs_rename: lost dir entry");
1165 vrele(ap->a_fvp);
fad57d0e
MD
1166 if (fcnp->cn_flags & CNP_PDIRUNLOCK)
1167 vrele(fdvp);
1168 else
1169 vput(fdvp);
1170 return(0);
984263bc 1171 }
fad57d0e
MD
1172 KKASSERT((fcnp->cn_flags & CNP_PDIRUNLOCK) == 0);
1173
1174 /*
1175 * fdvp and fvp are locked.
1176 */
1177 xp = VTOI(fvp);
1178 dp = VTOI(fdvp);
1179
984263bc
MD
1180 /*
1181 * Ensure that the directory entry still exists and has not
1182 * changed while the new name has been entered. If the source is
1183 * a file then the entry may have been unlinked or renamed. In
1184 * either case there is no further work to be done. If the source
1185 * is a directory then it cannot have been rmdir'ed; the IN_RENAME
1186 * flag ensures that it cannot be moved by another rename or removed
fad57d0e 1187 * by a rmdir. Cleanup IN_RENAME.
984263bc
MD
1188 */
1189 if (xp != ip) {
1190 if (doingdirectory)
1191 panic("ufs_rename: lost dir entry");
1192 } else {
1193 /*
1194 * If the source is a directory with a
1195 * new parent, the link count of the old
1196 * parent directory must be decremented
1197 * and ".." set to point to the new parent.
1198 */
1199 if (doingdirectory && newparent) {
1200 xp->i_offset = mastertemplate.dot_reclen;
1201 ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0);
fad57d0e 1202 /* cache_purge removed - handled by VFS compat layer */
984263bc
MD
1203 }
1204 error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
1205 xp->i_flag &= ~IN_RENAME;
1206 }
8e005a45 1207
984263bc 1208 VN_KNOTE(fvp, NOTE_RENAME);
fad57d0e
MD
1209 vput(fdvp);
1210 vput(fvp);
984263bc
MD
1211 vrele(ap->a_fvp);
1212 return (error);
1213
1214bad:
1215 if (xp)
1216 vput(ITOV(xp));
1217 vput(ITOV(dp));
1218out:
1219 if (doingdirectory)
1220 ip->i_flag &= ~IN_RENAME;
b458d1ab 1221 if (vn_lock(fvp, LK_EXCLUSIVE | LK_FAILRECLAIM) == 0) {
984263bc
MD
1222 ip->i_effnlink--;
1223 ip->i_nlink--;
1224 ip->i_flag |= IN_CHANGE;
1225 ip->i_flag &= ~IN_RENAME;
1226 if (DOINGSOFTDEP(fvp))
1227 softdep_change_linkcnt(ip);
1228 vput(fvp);
fad57d0e 1229 } else {
984263bc 1230 vrele(fvp);
fad57d0e 1231 }
984263bc
MD
1232 return (error);
1233}
1234
1235/*
1236 * Mkdir system call
0973c589
CP
1237 *
1238 * ufs_mkdir(struct vnode *a_dvp, struct vnode **a_vpp,
1239 * struct componentname *a_cnp, struct vattr *a_vap)
984263bc 1240 */
0961aa92 1241static
984263bc 1242int
e62afb5f 1243ufs_mkdir(struct vop_old_mkdir_args *ap)
984263bc 1244{
3ff2135f
RG
1245 struct vnode *dvp = ap->a_dvp;
1246 struct vattr *vap = ap->a_vap;
1247 struct componentname *cnp = ap->a_cnp;
1248 struct inode *ip, *dp;
984263bc
MD
1249 struct vnode *tvp;
1250 struct buf *bp;
1251 struct dirtemplate dirtemplate, *dtp;
1252 struct direct newdir;
1253 int error, dmode;
1254 long blkoff;
1255
984263bc
MD
1256 dp = VTOI(dvp);
1257 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1258 error = EMLINK;
1259 goto out;
1260 }
1261 dmode = vap->va_mode & 0777;
1262 dmode |= IFDIR;
1263 /*
1264 * Must simulate part of ufs_makeinode here to acquire the inode,
1265 * but not have it entered in the parent directory. The entry is
1266 * made later after writing "." and ".." entries.
1267 */
ac690a1d 1268 error = ffs_valloc(dvp, dmode, cnp->cn_cred, &tvp);
984263bc
MD
1269 if (error)
1270 goto out;
1271 ip = VTOI(tvp);
1272 ip->i_gid = dp->i_gid;
1273#ifdef SUIDDIR
1274 {
1275#ifdef QUOTA
1276 struct ucred ucred, *ucp;
1277 ucp = cnp->cn_cred;
1278#endif
1279 /*
1280 * If we are hacking owners here, (only do this where told to)
1281 * and we are not giving it TO root, (would subvert quotas)
1282 * then go ahead and give it to the other user.
1283 * The new directory also inherits the SUID bit.
1284 * If user's UID and dir UID are the same,
1285 * 'give it away' so that the SUID is still forced on.
1286 */
1287 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
1288 (dp->i_mode & ISUID) && dp->i_uid) {
1289 dmode |= ISUID;
1290 ip->i_uid = dp->i_uid;
1291#ifdef QUOTA
1292 if (dp->i_uid != cnp->cn_cred->cr_uid) {
1293 /*
1294 * Make sure the correct user gets charged
1295 * for the space.
1296 * Make a dummy credential for the victim.
1297 * XXX This seems to never be accessed out of
1298 * our context so a stack variable is ok.
1299 */
1300 ucred.cr_ref = 1;
1301 ucred.cr_uid = ip->i_uid;
1302 ucred.cr_ngroups = 1;
1303 ucred.cr_groups[0] = dp->i_gid;
1304 ucp = &ucred;
1305 }
1306#endif
1307 } else
1308 ip->i_uid = cnp->cn_cred->cr_uid;
1309#ifdef QUOTA
50e58362
MD
1310 if ((error = ufs_getinoquota(ip)) ||
1311 (error = ufs_chkiq(ip, 1, ucp, 0))) {
ac690a1d 1312 ffs_vfree(tvp, ip->i_number, dmode);
984263bc
MD
1313 vput(tvp);
1314 return (error);
1315 }
1316#endif
1317 }
1318#else /* !SUIDDIR */
1319 ip->i_uid = cnp->cn_cred->cr_uid;
1320#ifdef QUOTA
50e58362
MD
1321 if ((error = ufs_getinoquota(ip)) ||
1322 (error = ufs_chkiq(ip, 1, cnp->cn_cred, 0))) {
ac690a1d 1323 ffs_vfree(tvp, ip->i_number, dmode);
984263bc
MD
1324 vput(tvp);
1325 return (error);
1326 }
1327#endif
1328#endif /* !SUIDDIR */
1329 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1330 ip->i_mode = dmode;
1331 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
1332 ip->i_effnlink = 2;
1333 ip->i_nlink = 2;
1334 if (DOINGSOFTDEP(tvp))
1335 softdep_change_linkcnt(ip);
2b69e610 1336 if (cnp->cn_flags & CNP_ISWHITEOUT)
984263bc
MD
1337 ip->i_flags |= UF_OPAQUE;
1338
1339 /*
1340 * Bump link count in parent directory to reflect work done below.
1341 * Should be done before reference is created so cleanup is
1342 * possible if we crash.
1343 */
1344 dp->i_effnlink++;
1345 dp->i_nlink++;
1346 dp->i_flag |= IN_CHANGE;
1347 if (DOINGSOFTDEP(dvp))
1348 softdep_change_linkcnt(dp);
ac690a1d 1349 error = ffs_update(tvp, !(DOINGSOFTDEP(dvp) | DOINGASYNC(dvp)));
984263bc
MD
1350 if (error)
1351 goto bad;
1352
83a5effe
MD
1353 /*
1354 * The vnode must have a VM object in order to issue buffer cache
1355 * ops on it.
1356 */
b0d18f7d 1357 vinitvmio(tvp, DIRBLKSIZ, DIRBLKSIZ, -1);
83a5effe 1358
984263bc
MD
1359 /*
1360 * Initialize directory with "." and ".." from static template.
1361 */
83a5effe 1362 if (dvp->v_mount->mnt_maxsymlinklen > 0)
984263bc
MD
1363 dtp = &mastertemplate;
1364 else
1365 dtp = (struct dirtemplate *)&omastertemplate;
1366 dirtemplate = *dtp;
1367 dirtemplate.dot_ino = ip->i_number;
1368 dirtemplate.dotdot_ino = dp->i_number;
3bb7eedb 1369 nvnode_pager_setsize(tvp, DIRBLKSIZ, DIRBLKSIZ, -1);
83a5effe
MD
1370 error = VOP_BALLOC(tvp, 0LL, DIRBLKSIZ, cnp->cn_cred, B_CLRBUF, &bp);
1371 if (error)
984263bc
MD
1372 goto bad;
1373 ip->i_size = DIRBLKSIZ;
1374 ip->i_flag |= IN_CHANGE | IN_UPDATE;
984263bc
MD
1375 bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
1376 if (DOINGSOFTDEP(tvp)) {
1377 /*
1378 * Ensure that the entire newly allocated block is a
1379 * valid directory so that future growth within the
1380 * block does not have to ensure that the block is
1381 * written before the inode.
1382 */
1383 blkoff = DIRBLKSIZ;
1384 while (blkoff < bp->b_bcount) {
1385 ((struct direct *)
1386 (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
1387 blkoff += DIRBLKSIZ;
1388 }
1389 }
ac690a1d 1390 if ((error = ffs_update(tvp, !(DOINGSOFTDEP(tvp) |
984263bc 1391 DOINGASYNC(tvp)))) != 0) {
62cfda27 1392 bwrite(bp);
984263bc
MD
1393 goto bad;
1394 }
1395 /*
1396 * Directory set up, now install its entry in the parent directory.
1397 *
1398 * If we are not doing soft dependencies, then we must write out the
1399 * buffer containing the new directory body before entering the new
1400 * name in the parent. If we are doing soft dependencies, then the
1401 * buffer containing the new directory body will be passed to and
1402 * released in the soft dependency code after the code has attached
1403 * an appropriate ordering dependency to the buffer which ensures that
1404 * the buffer is written before the new name is written in the parent.
1405 */
1406 if (DOINGASYNC(dvp))
1407 bdwrite(bp);
62cfda27 1408 else if (!DOINGSOFTDEP(dvp) && (error = bwrite(bp)) != 0)
984263bc
MD
1409 goto bad;
1410 ufs_makedirentry(ip, cnp, &newdir);
1411 error = ufs_direnter(dvp, tvp, &newdir, cnp, bp);
1412
1413bad:
1414 if (error == 0) {
1415 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1416 *ap->a_vpp = tvp;
1417 } else {
1418 dp->i_effnlink--;
1419 dp->i_nlink--;
1420 dp->i_flag |= IN_CHANGE;
1421 if (DOINGSOFTDEP(dvp))
1422 softdep_change_linkcnt(dp);
1423 /*
1424 * No need to do an explicit VOP_TRUNCATE here, vrele will
1425 * do this for us because we set the link count to 0.
1426 */
1427 ip->i_effnlink = 0;
1428 ip->i_nlink = 0;
1429 ip->i_flag |= IN_CHANGE;
1430 if (DOINGSOFTDEP(tvp))
1431 softdep_change_linkcnt(ip);
1432 vput(tvp);
1433 }
1434out:
1435 return (error);
1436}
1437
1438/*
1439 * Rmdir system call.
0973c589
CP
1440 *
1441 * ufs_rmdir(struct vnode *a_dvp, struct vnode *a_vp,
1442 * struct componentname *a_cnp)
984263bc 1443 */
0961aa92 1444static
984263bc 1445int
e62afb5f 1446ufs_rmdir(struct vop_old_rmdir_args *ap)
984263bc
MD
1447{
1448 struct vnode *vp = ap->a_vp;
1449 struct vnode *dvp = ap->a_dvp;
1450 struct componentname *cnp = ap->a_cnp;
1451 struct inode *ip, *dp;
1452 int error, ioflag;
1453
1454 ip = VTOI(vp);
1455 dp = VTOI(dvp);
1456
1457 /*
1458 * Do not remove a directory that is in the process of being renamed.
1459 * Verify the directory is empty (and valid). Rmdir ".." will not be
1460 * valid since ".." will contain a reference to the current directory
1461 * and thus be non-empty. Do not allow the removal of mounted on
1462 * directories (this can happen when an NFS exported filesystem
1463 * tries to remove a locally mounted on directory).
1464 */
1465 error = 0;
1466 if (ip->i_flag & IN_RENAME) {
1467 error = EINVAL;
1468 goto out;
1469 }
1470 if (ip->i_effnlink != 2 ||
1471 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1472 error = ENOTEMPTY;
1473 goto out;
1474 }
3a907475 1475#if 0 /* handled by kernel now */
984263bc
MD
1476 if ((dp->i_flags & APPEND)
1477 || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
1478 error = EPERM;
1479 goto out;
1480 }
3a907475 1481#endif
984263bc
MD
1482 /*
1483 * Delete reference to directory before purging
1484 * inode. If we crash in between, the directory
1485 * will be reattached to lost+found,
1486 */
1487 dp->i_effnlink--;
1488 ip->i_effnlink--;
1489 if (DOINGSOFTDEP(vp)) {
1490 softdep_change_linkcnt(dp);
1491 softdep_change_linkcnt(ip);
1492 }
1493 error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
1494 if (error) {
1495 dp->i_effnlink++;
1496 ip->i_effnlink++;
1497 if (DOINGSOFTDEP(vp)) {
1498 softdep_change_linkcnt(dp);
1499 softdep_change_linkcnt(ip);
1500 }
1501 goto out;
1502 }
1503 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
984263bc
MD
1504 /*
1505 * Truncate inode. The only stuff left in the directory is "." and
1506 * "..". The "." reference is inconsequential since we are quashing
1507 * it. The soft dependency code will arrange to do these operations
1508 * after the parent directory entry has been deleted on disk, so
1509 * when running with that code we avoid doing them now.
1510 */
1511 if (!DOINGSOFTDEP(vp)) {
1512 dp->i_nlink--;
1513 dp->i_flag |= IN_CHANGE;
1514 ip->i_nlink--;
1515 ip->i_flag |= IN_CHANGE;
1516 ioflag = DOINGASYNC(vp) ? 0 : IO_SYNC;
ac690a1d 1517 error = ffs_truncate(vp, (off_t)0, ioflag, cnp->cn_cred);
984263bc 1518 }
fad57d0e 1519 /* cache_purge removed - handled by VFS compat layer */
984263bc
MD
1520#ifdef UFS_DIRHASH
1521 /* Kill any active hash; i_effnlink == 0, so it will not come back. */
1522 if (ip->i_dirhash != NULL)
1523 ufsdirhash_free(ip);
1524#endif
1525out:
1526 VN_KNOTE(vp, NOTE_DELETE);
1527 return (error);
1528}
1529
1530/*
1531 * symlink -- make a symbolic link
0973c589
CP
1532 *
1533 * ufs_symlink(struct vnode *a_dvp, struct vnode **a_vpp,
1534 * struct componentname *a_cnp, struct vattr *a_vap,
1535 * char *a_target)
984263bc 1536 */
0961aa92 1537static
984263bc 1538int
e62afb5f 1539ufs_symlink(struct vop_old_symlink_args *ap)
984263bc 1540{
3ff2135f
RG
1541 struct vnode *vp, **vpp = ap->a_vpp;
1542 struct inode *ip;
984263bc
MD
1543 int len, error;
1544
1545 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
83a5effe 1546 vpp, ap->a_cnp);
984263bc
MD
1547 if (error)
1548 return (error);
1549 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1550 vp = *vpp;
1551 len = strlen(ap->a_target);
1552 if (len < vp->v_mount->mnt_maxsymlinklen) {
1553 ip = VTOI(vp);
1554 bcopy(ap->a_target, (char *)ip->i_shortlink, len);
1555 ip->i_size = len;
1556 ip->i_flag |= IN_CHANGE | IN_UPDATE;
83a5effe
MD
1557 } else {
1558 /*
1559 * Make sure we have a VM object in order to use
1560 * the buffer cache.
1561 */
1562 if (vp->v_object == NULL)
b0d18f7d 1563 vinitvmio(vp, 0, PAGE_SIZE, -1);
984263bc 1564 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
83a5effe 1565 UIO_SYSSPACE, IO_NODELOCKED,
87de5057 1566 ap->a_cnp->cn_cred, NULL);
83a5effe 1567 }
984263bc
MD
1568 if (error)
1569 vput(vp);
1570 return (error);
1571}
1572
1573/*
1574 * Vnode op for reading directories.
1575 *
0973c589 1576 * ufs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
84009d92 1577 * int *a_eofflag, int *ncookies, off_t **a_cookies)
984263bc 1578 */
0961aa92 1579static
984263bc 1580int
0973c589 1581ufs_readdir(struct vop_readdir_args *ap)
984263bc 1582{
3ff2135f 1583 struct uio *uio = ap->a_uio;
7f8e5940 1584 struct vnode *vp = ap->a_vp;
fb0466c9
MD
1585 struct direct *dp;
1586 struct buf *bp;
1587 int retval;
1588 int error;
1589 int offset; /* offset into buffer cache buffer */
1590 int eoffset; /* end of buffer clipped to file EOF */
1591 int pickup; /* pickup point */
7f8e5940 1592 int ncookies;
fb0466c9 1593 int cookie_index;
84009d92 1594 off_t *cookies;
984263bc 1595
fb0466c9
MD
1596 if (uio->uio_offset < 0)
1597 return (EINVAL);
e088dc32 1598 /*
fb0466c9
MD
1599 * Guess the number of cookies needed. Make sure we compute at
1600 * least 1, and no more then a reasonable limit.
e088dc32 1601 */
fb0466c9
MD
1602 if (ap->a_ncookies) {
1603 ncookies = uio->uio_resid / 16 + 1;
1604 if (ncookies > 1024)
1605 ncookies = 1024;
84009d92 1606 cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
fb0466c9
MD
1607 } else {
1608 ncookies = -1; /* force conditionals below */
1609 cookies = NULL;
1610 }
1611 cookie_index = 0;
1612
b458d1ab
MD
1613 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM);
1614 if (error)
885ecb13
MD
1615 return (error);
1616
fb0466c9
MD
1617 /*
1618 * Past or at EOF
1619 */
1620 if (uio->uio_offset >= VTOI(vp)->i_size) {
1621 if (ap->a_eofflag)
1622 *ap->a_eofflag = 1;
1623 if (ap->a_ncookies) {
1624 *ap->a_ncookies = cookie_index;
1625 *ap->a_cookies = cookies;
1626 }
885ecb13 1627 goto done;
fb0466c9
MD
1628 }
1629
1630 /*
1631 * Loop until we run out of cookies, we run out of user buffer,
1632 * or we hit the directory EOF.
1633 *
1634 * Always start scans at the beginning of the buffer, don't trust
1635 * the offset supplied by userland.
1636 */
9ba4b517 1637 while ((error = ffs_blkatoff_ra(vp, uio->uio_offset, NULL, &bp, 2)) == 0) {
fb0466c9
MD
1638 pickup = (int)(uio->uio_offset - bp->b_loffset);
1639 offset = 0;
1640 retval = 0;
1641 if (bp->b_loffset + bp->b_bcount > VTOI(vp)->i_size)
1642 eoffset = (int)(VTOI(vp)->i_size - bp->b_loffset);
1643 else
1644 eoffset = bp->b_bcount;
1645
1646 while (offset < eoffset) {
1647 dp = (struct direct *)(bp->b_data + offset);
1648 if (dp->d_reclen <= 0 || (dp->d_reclen & 3) ||
1649 offset + dp->d_reclen > bp->b_bcount) {
82fd1984
JS
1650 error = EIO;
1651 break;
1652 }
fb0466c9
MD
1653 if (offsetof(struct direct, d_name[dp->d_namlen]) > dp->d_reclen) {
1654 error = EIO;
1655 break;
1656 }
1657 if (offset < pickup) {
1658 offset += dp->d_reclen;
1659 continue;
1660 }
e088dc32 1661#if BYTE_ORDER == LITTLE_ENDIAN
7f8e5940 1662 if (OFSFMT(vp)) {
82fd1984
JS
1663 retval = vop_write_dirent(&error, uio,
1664 dp->d_ino, dp->d_namlen, dp->d_type,
1665 dp->d_name);
e088dc32
JS
1666 } else
1667#endif
1668 {
82fd1984
JS
1669 retval = vop_write_dirent(&error, uio,
1670 dp->d_ino, dp->d_type, dp->d_namlen,
1671 dp->d_name);
e088dc32 1672 }
82fd1984 1673 if (retval)
e088dc32 1674 break;
84009d92
MD
1675 if (cookies)
1676 cookies[cookie_index] = bp->b_loffset + offset;
fb0466c9
MD
1677 ++cookie_index;
1678 offset += dp->d_reclen;
1679 if (cookie_index == ncookies)
1680 break;
1681 }
1682
1683 /*
1684 * This will align the next loop to the beginning of the
1685 * next block, and pickup will calculate to 0.
1686 */
1687 uio->uio_offset = bp->b_loffset + offset;
1688 brelse(bp);
1689
1690 if (retval || error || cookie_index == ncookies ||
1691 uio->uio_offset >= VTOI(vp)->i_size) {
1692 break;
984263bc 1693 }
984263bc 1694 }
984263bc 1695 if (ap->a_eofflag)
7f8e5940 1696 *ap->a_eofflag = VTOI(vp)->i_size <= uio->uio_offset;
fb0466c9
MD
1697
1698 /*
1699 * Report errors only if we didn't manage to read anything
1700 */
1701 if (error && cookie_index == 0) {
1702 if (cookies) {
efda3bd0 1703 kfree(cookies, M_TEMP);
fb0466c9
MD
1704 *ap->a_ncookies = 0;
1705 *ap->a_cookies = NULL;
1706 }
1707 } else {
1708 error = 0;
1709 if (cookies) {
1710 *ap->a_ncookies = cookie_index;
1711 *ap->a_cookies = cookies;
1712 }
1713 }
885ecb13
MD
1714done:
1715 vn_unlock(vp);
e088dc32 1716 return (error);
984263bc
MD
1717}
1718
1719/*
1720 * Return target name of a symbolic link
0973c589
CP
1721 *
1722 * ufs_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
984263bc 1723 */
0961aa92 1724static
984263bc 1725int
0973c589 1726ufs_readlink(struct vop_readlink_args *ap)
984263bc 1727{
3ff2135f
RG
1728 struct vnode *vp = ap->a_vp;
1729 struct inode *ip = VTOI(vp);
984263bc
MD
1730 int isize;
1731
1732 isize = ip->i_size;
1733 if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
f719c866 1734 (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */
984263bc
MD
1735 uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
1736 return (0);
1737 }
83a5effe
MD
1738
1739 /*
1740 * Perform the equivalent of an OPEN on vp so we can issue a
1741 * VOP_READ.
1742 */
984263bc
MD
1743 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1744}
1745
1746/*
1747 * Calculate the logical to physical mapping if not done already,
1748 * then call the device strategy routine.
1749 *
1750 * In order to be able to swap to a file, the VOP_BMAP operation may not
1751 * deadlock on memory. See ufs_bmap() for details.
0973c589 1752 *
81b5c339 1753 * ufs_strategy(struct vnode *a_vp, struct bio *a_bio)
984263bc 1754 */
0961aa92 1755static
984263bc 1756int
0973c589 1757ufs_strategy(struct vop_strategy_args *ap)
984263bc 1758{
81b5c339
MD
1759 struct bio *bio = ap->a_bio;
1760 struct bio *nbio;
1761 struct buf *bp = bio->bio_buf;
3ff2135f
RG
1762 struct vnode *vp = ap->a_vp;
1763 struct inode *ip;
984263bc
MD
1764 int error;
1765
1766 ip = VTOI(vp);
1767 if (vp->v_type == VBLK || vp->v_type == VCHR)
1768 panic("ufs_strategy: spec");
81b5c339 1769 nbio = push_bio(bio);
54078292 1770 if (nbio->bio_offset == NOOFFSET) {
08daea96 1771 error = VOP_BMAP(vp, bio->bio_offset, &nbio->bio_offset,
e92ca23a 1772 NULL, NULL, bp->b_cmd);
984263bc
MD
1773 if (error) {
1774 bp->b_error = error;
1775 bp->b_flags |= B_ERROR;
81b5c339
MD
1776 /* I/O was never started on nbio, must biodone(bio) */
1777 biodone(bio);
984263bc
MD
1778 return (error);
1779 }
54078292 1780 if (nbio->bio_offset == NOOFFSET)
984263bc
MD
1781 vfs_bio_clrbuf(bp);
1782 }
54078292 1783 if (nbio->bio_offset == NOOFFSET) {
1f97d073
MD
1784 /*
1785 * We hit a hole in the file. The buffer has been zero-filled
1786 * so just biodone() it.
1787 */
81b5c339 1788 biodone(bio);
1f97d073
MD
1789 } else {
1790 vn_strategy(ip->i_devvp, nbio);
984263bc 1791 }
984263bc
MD
1792 return (0);
1793}
1794
1795/*
1796 * Print out the contents of an inode.
0973c589
CP
1797 *
1798 * ufs_print(struct vnode *a_vp)
984263bc 1799 */
0961aa92 1800static
984263bc 1801int
0973c589 1802ufs_print(struct vop_print_args *ap)
984263bc 1803{
3ff2135f
RG
1804 struct vnode *vp = ap->a_vp;
1805 struct inode *ip = VTOI(vp);
984263bc 1806
086c1d7e 1807 kprintf("tag VT_UFS, ino %lu, on dev %s (%d, %d)",
984263bc
MD
1808 (u_long)ip->i_number, devtoname(ip->i_dev), major(ip->i_dev),
1809 minor(ip->i_dev));
1810 if (vp->v_type == VFIFO)
1811 fifo_printinfo(vp);
3446c007 1812 lockmgr_printinfo(&vp->v_lock);
086c1d7e 1813 kprintf("\n");
984263bc
MD
1814 return (0);
1815}
1816
984263bc
MD
1817/*
1818 * Read wrapper for fifos.
0973c589
CP
1819 *
1820 * ufsfifo_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
1821 * struct ucred *a_cred)
984263bc 1822 */
0961aa92 1823static
984263bc 1824int
0973c589 1825ufsfifo_read(struct vop_read_args *ap)
984263bc
MD
1826{
1827 int error, resid;
1828 struct inode *ip;
1829 struct uio *uio;
1830
1831 uio = ap->a_uio;
1832 resid = uio->uio_resid;
66a1ddf5 1833 error = VOCALL(&fifo_vnode_vops, &ap->a_head);
984263bc
MD
1834 ip = VTOI(ap->a_vp);
1835 if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL &&
1836 (uio->uio_resid != resid || (error == 0 && resid != 0)))
1837 VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1838 return (error);
1839}
1840
1841/*
1842 * Write wrapper for fifos.
0973c589
CP
1843 *
1844 * ufsfifo_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
1845 * struct ucred *a_cred)
984263bc 1846 */
0961aa92 1847static
984263bc 1848int
0973c589 1849ufsfifo_write(struct vop_write_args *ap)
984263bc
MD
1850{
1851 int error, resid;
1852 struct inode *ip;
1853 struct uio *uio;
1854
1855 uio = ap->a_uio;
1856 resid = uio->uio_resid;
66a1ddf5 1857 error = VOCALL(&fifo_vnode_vops, &ap->a_head);
984263bc
MD
1858 ip = VTOI(ap->a_vp);
1859 if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0)))
1860 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
1861 return (error);
1862}
1863
1864/*
1865 * Close wrapper for fifos.
1866 *
1867 * Update the times on the inode then do device close.
0973c589 1868 *
b478fdce 1869 * ufsfifo_close(struct vnode *a_vp, int a_fflag)
984263bc 1870 */
0961aa92 1871static
984263bc 1872int
0973c589 1873ufsfifo_close(struct vop_close_args *ap)
984263bc
MD
1874{
1875 struct vnode *vp = ap->a_vp;
1876
ee173d09 1877 if (VREFCNT(vp) > 1)
984263bc 1878 ufs_itimes(vp);
66a1ddf5 1879 return (VOCALL(&fifo_vnode_vops, &ap->a_head));
984263bc
MD
1880}
1881
1882/*
1883 * Kqfilter wrapper for fifos.
1884 *
1885 * Fall through to ufs kqfilter routines if needed
1886 */
0961aa92 1887static
984263bc 1888int
0973c589 1889ufsfifo_kqfilter(struct vop_kqfilter_args *ap)
984263bc
MD
1890{
1891 int error;
1892
66a1ddf5 1893 error = VOCALL(&fifo_vnode_vops, &ap->a_head);
984263bc
MD
1894 if (error)
1895 error = ufs_kqfilter(ap);
1896 return (error);
1897}
1898
984263bc
MD
1899/*
1900 * Advisory record locking support
0973c589
CP
1901 *
1902 * ufs_advlock(struct vnode *a_vp, caddr_t a_id, int a_op, struct flock *a_fl,
1903 * int a_flags)
984263bc 1904 */
0961aa92 1905static
984263bc 1906int
0973c589 1907ufs_advlock(struct vop_advlock_args *ap)
984263bc 1908{
3ff2135f 1909 struct inode *ip = VTOI(ap->a_vp);
984263bc
MD
1910
1911 return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
1912}
1913
1914/*
1915 * Initialize the vnode associated with a new inode, handle aliased
1916 * vnodes.
3e72e117
MD
1917 *
1918 * Make sure directories have their VM object now rather then later,
1919 * saving us from having to check on all the myrid directory VOPs
1920 * that might be executed without a VOP_OPEN being performed.
984263bc
MD
1921 */
1922int
0961aa92 1923ufs_vinit(struct mount *mntp, struct vnode **vpp)
984263bc
MD
1924{
1925 struct inode *ip;
1926 struct vnode *vp;
984263bc
MD
1927
1928 vp = *vpp;
1929 ip = VTOI(vp);
57f7b636 1930
1c843a13
MD
1931 vp->v_type = IFTOVT(ip->i_mode);
1932
1933 switch(vp->v_type) {
984263bc
MD
1934 case VCHR:
1935 case VBLK:
6ddb7618 1936 vp->v_ops = &mntp->mnt_vn_spec_ops;
0e9b9130 1937 addaliasu(vp, umajor(ip->i_rdev), uminor(ip->i_rdev));
984263bc
MD
1938 break;
1939 case VFIFO:
6ddb7618 1940 vp->v_ops = &mntp->mnt_vn_fifo_ops;
984263bc 1941 break;
3e72e117 1942 case VDIR:
1c843a13 1943 case VREG:
b0d18f7d
MD
1944 vinitvmio(vp, ip->i_size,
1945 blkoffsize(ip->i_fs, ip, ip->i_size),
1946 blkoff(ip->i_fs, ip->i_size));
1c843a13
MD
1947 break;
1948 case VLNK:
b0d18f7d
MD
1949 if (ip->i_size >= vp->v_mount->mnt_maxsymlinklen) {
1950 vinitvmio(vp, ip->i_size,
1951 blkoffsize(ip->i_fs, ip, ip->i_size),
1952 blkoff(ip->i_fs, ip->i_size));
1953 }
3e72e117 1954 break;
984263bc
MD
1955 default:
1956 break;
1957
1958 }
57f7b636 1959
c309c6d4 1960 if (ip->i_number == UFS_ROOTINO)
2247fe02 1961 vsetflags(vp, VROOT);
984263bc
MD
1962 /*
1963 * Initialize modrev times
1964 */
9d6d26c9 1965 ip->i_modrev = init_va_filerev();
984263bc
MD
1966 *vpp = vp;
1967 return (0);
1968}
1969
1970/*
1971 * Allocate a new inode.
1972 */
0961aa92 1973static
984263bc 1974int
0973c589
CP
1975ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
1976 struct componentname *cnp)
984263bc 1977{
3ff2135f 1978 struct inode *ip, *pdir;
984263bc
MD
1979 struct direct newdir;
1980 struct vnode *tvp;
1981 int error;
1982
1983 pdir = VTOI(dvp);
984263bc
MD
1984 *vpp = NULL;
1985 if ((mode & IFMT) == 0)
1986 mode |= IFREG;
1987
ac690a1d 1988 error = ffs_valloc(dvp, mode, cnp->cn_cred, &tvp);
984263bc
MD
1989 if (error)
1990 return (error);
1991 ip = VTOI(tvp);
33036abf 1992 ip->i_flags = pdir->i_flags & (SF_NOHISTORY|UF_NOHISTORY|UF_NODUMP);
984263bc
MD
1993 ip->i_gid = pdir->i_gid;
1994#ifdef SUIDDIR
1995 {
1996#ifdef QUOTA
1997 struct ucred ucred, *ucp;
1998 ucp = cnp->cn_cred;
1999#endif
2000 /*
2001 * If we are not the owner of the directory,
2002 * and we are hacking owners here, (only do this where told to)
2003 * and we are not giving it TO root, (would subvert quotas)
2004 * then go ahead and give it to the other user.
2005 * Note that this drops off the execute bits for security.
2006 */
2007 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
2008 (pdir->i_mode & ISUID) &&
2009 (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
2010 ip->i_uid = pdir->i_uid;
2011 mode &= ~07111;
2012#ifdef QUOTA
2013 /*
2014 * Make sure the correct user gets charged
2015 * for the space.
2016 * Quickly knock up a dummy credential for the victim.
2017 * XXX This seems to never be accessed out of our
2018 * context so a stack variable is ok.
2019 */
2020 ucred.cr_ref = 1;
2021 ucred.cr_uid = ip->i_uid;
2022 ucred.cr_ngroups = 1;
2023 ucred.cr_groups[0] = pdir->i_gid;
2024 ucp = &ucred;
2025#endif
2026 } else
2027 ip->i_uid = cnp->cn_cred->cr_uid;
2028
2029#ifdef QUOTA
50e58362
MD
2030 if ((error = ufs_getinoquota(ip)) ||
2031 (error = ufs_chkiq(ip, 1, ucp, 0))) {
ac690a1d 2032 ffs_vfree(tvp, ip->i_number, mode);
984263bc
MD
2033 vput(tvp);
2034 return (error);
2035 }
2036#endif
2037 }
2038#else /* !SUIDDIR */
2039 ip->i_uid = cnp->cn_cred->cr_uid;
2040#ifdef QUOTA
50e58362
MD
2041 if ((error = ufs_getinoquota(ip)) ||
2042 (error = ufs_chkiq(ip, 1, cnp->cn_cred, 0))) {
ac690a1d 2043 ffs_vfree(tvp, ip->i_number, mode);
984263bc
MD
2044 vput(tvp);
2045 return (error);
2046 }
2047#endif
2048#endif /* !SUIDDIR */
712774a1 2049 ip->i_din.di_spare7E = 0;
984263bc
MD
2050 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2051 ip->i_mode = mode;
2052 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
2053 ip->i_effnlink = 1;
2054 ip->i_nlink = 1;
2055 if (DOINGSOFTDEP(tvp))
2056 softdep_change_linkcnt(ip);
2057 if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
61b7a688 2058 priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID, 0)) {
984263bc 2059 ip->i_mode &= ~ISGID;
41c20dac 2060 }
984263bc 2061
2b69e610 2062 if (cnp->cn_flags & CNP_ISWHITEOUT)
984263bc
MD
2063 ip->i_flags |= UF_OPAQUE;
2064
1c843a13
MD
2065 /*
2066 * Regular files and directories need VM objects. Softlinks do
2067 * not (not immediately anyway).
2068 */
2069 if (tvp->v_type == VREG || tvp->v_type == VDIR)
b0d18f7d 2070 vinitvmio(tvp, 0, PAGE_SIZE, -1);
1c843a13 2071
984263bc
MD
2072 /*
2073 * Make sure inode goes to disk before directory entry.
2074 */
ac690a1d 2075 error = ffs_update(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp)));
984263bc
MD
2076 if (error)
2077 goto bad;
2078 ufs_makedirentry(ip, cnp, &newdir);
2079 error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL);
2080 if (error)
2081 goto bad;
2082 *vpp = tvp;
2083 return (0);
2084
2085bad:
2086 /*
2087 * Write error occurred trying to update the inode
2088 * or the directory so must deallocate the inode.
2089 */
2090 ip->i_effnlink = 0;
2091 ip->i_nlink = 0;
2092 ip->i_flag |= IN_CHANGE;
2093 if (DOINGSOFTDEP(tvp))
2094 softdep_change_linkcnt(ip);
2095 vput(tvp);
2096 return (error);
2097}
2098
2099static int
0973c589 2100ufs_missingop(struct vop_generic_args *ap)
984263bc 2101{
31bd717a 2102 panic("no vop function for %s in ufs child", ap->a_desc->sd_name);
984263bc
MD
2103 return (EOPNOTSUPP);
2104}
2105
2106static struct filterops ufsread_filtops =
4c91dbc9 2107 { FILTEROP_ISFD, NULL, filt_ufsdetach, filt_ufsread };
984263bc 2108static struct filterops ufswrite_filtops =
4c91dbc9 2109 { FILTEROP_ISFD, NULL, filt_ufsdetach, filt_ufswrite };
984263bc 2110static struct filterops ufsvnode_filtops =
4c91dbc9 2111 { FILTEROP_ISFD, NULL, filt_ufsdetach, filt_ufsvnode };
984263bc 2112
0973c589
CP
2113/*
2114 * ufs_kqfilter(struct vnode *a_vp, struct knote *a_kn)
2115 */
984263bc 2116static int
0973c589 2117ufs_kqfilter(struct vop_kqfilter_args *ap)
984263bc
MD
2118{
2119 struct vnode *vp = ap->a_vp;
2120 struct knote *kn = ap->a_kn;
2121
2122 switch (kn->kn_filter) {
2123 case EVFILT_READ:
2124 kn->kn_fop = &ufsread_filtops;
2125 break;
2126 case EVFILT_WRITE:
2127 kn->kn_fop = &ufswrite_filtops;
2128 break;
2129 case EVFILT_VNODE:
2130 kn->kn_fop = &ufsvnode_filtops;
2131 break;
2132 default:
b287d649 2133 return (EOPNOTSUPP);
984263bc
MD
2134 }
2135
2136 kn->kn_hook = (caddr_t)vp;
2137
5b22f1a7 2138 /* XXX: kq token actually protects the list */
3b998fa9 2139 lwkt_gettoken(&vp->v_token);
5b22f1a7 2140 knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
3b998fa9 2141 lwkt_reltoken(&vp->v_token);
984263bc
MD
2142
2143 return (0);
2144}
2145
2146static void
2147filt_ufsdetach(struct knote *kn)
2148{
2149 struct vnode *vp = (struct vnode *)kn->kn_hook;
2150
3b998fa9 2151 lwkt_gettoken(&vp->v_token);
5b22f1a7 2152 knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
3b998fa9 2153 lwkt_reltoken(&vp->v_token);
984263bc
MD
2154}
2155
2156/*ARGSUSED*/
2157static int
2158filt_ufsread(struct knote *kn, long hint)
2159{
2160 struct vnode *vp = (struct vnode *)kn->kn_hook;
2161 struct inode *ip = VTOI(vp);
57b24f4e 2162 off_t off;
984263bc
MD
2163
2164 /*
2165 * filesystem is gone, so set the EOF flag and schedule
2166 * the knote for deletion.
2167 */
2168 if (hint == NOTE_REVOKE) {
3bcb6e5e 2169 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
984263bc
MD
2170 return (1);
2171 }
2172
57b24f4e
MD
2173 off = ip->i_size - kn->kn_fp->f_offset;
2174 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
2175 if (kn->kn_sfflags & NOTE_OLDAPI)
2176 return(1);
984263bc
MD
2177 return (kn->kn_data != 0);
2178}
2179
2180/*ARGSUSED*/
2181static int
2182filt_ufswrite(struct knote *kn, long hint)
2183{
984263bc
MD
2184 /*
2185 * filesystem is gone, so set the EOF flag and schedule
2186 * the knote for deletion.
2187 */
2188 if (hint == NOTE_REVOKE)
3bcb6e5e 2189 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
984263bc
MD
2190
2191 kn->kn_data = 0;
2192 return (1);
2193}
2194
2195static int
2196filt_ufsvnode(struct knote *kn, long hint)
2197{
984263bc
MD
2198 if (kn->kn_sfflags & hint)
2199 kn->kn_fflags |= hint;
2200 if (hint == NOTE_REVOKE) {
3bcb6e5e 2201 kn->kn_flags |= (EV_EOF | EV_NODATA);
984263bc
MD
2202 return (1);
2203 }
2204 return (kn->kn_fflags != 0);
2205}
2206
2207/* Global vfs data structures for ufs. */
66a1ddf5
MD
2208static struct vop_ops ufs_vnode_vops = {
2209 .vop_default = vop_defaultop,
2210 .vop_fsync = (void *)ufs_missingop,
2211 .vop_read = (void *)ufs_missingop,
2212 .vop_reallocblks = (void *)ufs_missingop,
2213 .vop_write = (void *)ufs_missingop,
2214 .vop_access = ufs_access,
2215 .vop_advlock = ufs_advlock,
2216 .vop_bmap = ufs_bmap,
2217 .vop_old_lookup = ufs_lookup,
2218 .vop_close = ufs_close,
2219 .vop_old_create = ufs_create,
2220 .vop_getattr = ufs_getattr,
2221 .vop_inactive = ufs_inactive,
66a1ddf5 2222 .vop_old_link = ufs_link,
64950f31
MD
2223 .vop_old_mkdir = ufs_mkdir,
2224 .vop_old_mknod = ufs_mknod,
3a907475 2225 .vop_open = vop_stdopen,
64950f31 2226 .vop_pathconf = vop_stdpathconf,
66a1ddf5
MD
2227 .vop_kqfilter = ufs_kqfilter,
2228 .vop_print = ufs_print,
2229 .vop_readdir = ufs_readdir,
2230 .vop_readlink = ufs_readlink,
2231 .vop_reclaim = ufs_reclaim,
2232 .vop_old_remove = ufs_remove,
2233 .vop_old_rename = ufs_rename,
2234 .vop_old_rmdir = ufs_rmdir,
2235 .vop_setattr = ufs_setattr,
349433c9 2236 .vop_markatime = ufs_markatime,
66a1ddf5
MD
2237 .vop_strategy = ufs_strategy,
2238 .vop_old_symlink = ufs_symlink,
66a1ddf5 2239 .vop_old_whiteout = ufs_whiteout
984263bc 2240};
66a1ddf5
MD
2241
2242static struct vop_ops ufs_spec_vops = {
8be7edad 2243 .vop_default = vop_defaultop,
66a1ddf5
MD
2244 .vop_fsync = (void *)ufs_missingop,
2245 .vop_access = ufs_access,
8be7edad
MD
2246 .vop_close = ufs_close,
2247 .vop_getattr = ufs_getattr,
66a1ddf5 2248 .vop_inactive = ufs_inactive,
66a1ddf5 2249 .vop_print = ufs_print,
8be7edad 2250 .vop_read = vop_stdnoread,
66a1ddf5
MD
2251 .vop_reclaim = ufs_reclaim,
2252 .vop_setattr = ufs_setattr,
349433c9 2253 .vop_markatime = ufs_markatime,
8be7edad 2254 .vop_write = vop_stdnowrite
984263bc 2255};
66a1ddf5
MD
2256
2257static struct vop_ops ufs_fifo_vops = {
2258 .vop_default = fifo_vnoperate,
2259 .vop_fsync = (void *)ufs_missingop,
2260 .vop_access = ufs_access,
2261 .vop_close = ufsfifo_close,
2262 .vop_getattr = ufs_getattr,
2263 .vop_inactive = ufs_inactive,
66a1ddf5 2264 .vop_kqfilter = ufsfifo_kqfilter,
66a1ddf5
MD
2265 .vop_print = ufs_print,
2266 .vop_read = ufsfifo_read,
2267 .vop_reclaim = ufs_reclaim,
2268 .vop_setattr = ufs_setattr,
349433c9 2269 .vop_markatime = ufs_markatime,
66a1ddf5 2270 .vop_write = ufsfifo_write
984263bc 2271};
984263bc 2272
66a1ddf5
MD
2273VNODEOP_SET(ufs_vnode_vops);
2274VNODEOP_SET(ufs_spec_vops);
2275VNODEOP_SET(ufs_fifo_vops);
984263bc 2276
0973c589 2277/*
31bd717a 2278 * ufs_vnoperate()
0973c589 2279 */
984263bc 2280int
0973c589 2281ufs_vnoperate(struct vop_generic_args *ap)
984263bc 2282{
66a1ddf5 2283 return (VOCALL(&ufs_vnode_vops, ap));
984263bc
MD
2284}
2285
0973c589 2286/*
31bd717a 2287 * ufs_vnoperatefifo()
0973c589 2288 */
984263bc 2289int
0973c589 2290ufs_vnoperatefifo(struct vop_generic_args *ap)
984263bc 2291{
66a1ddf5 2292 return (VOCALL(&ufs_fifo_vops, ap));
984263bc
MD
2293}
2294
0973c589 2295/*
31bd717a 2296 * ufs_vnoperatespec()
0973c589 2297 */
984263bc 2298int
0973c589 2299ufs_vnoperatespec(struct vop_generic_args *ap)
984263bc 2300{
66a1ddf5 2301 return (VOCALL(&ufs_spec_vops, ap));
984263bc 2302}