1 /* $NetBSD: ufs_vnops.c,v 1.113.2.2 2004/07/28 11:30:07 tron Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)ufs_vnops.c 8.28 (Berkeley) 7/31/95
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.113.2.2 2004/07/28 11:30:07 tron Exp $");
41
42 #ifndef _LKM
43 #include "opt_quota.h"
44 #include "fs_lfs.h"
45 #endif /* _LKM */
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/namei.h>
50 #include <sys/resourcevar.h>
51 #include <sys/kernel.h>
52 #include <sys/file.h>
53 #include <sys/stat.h>
54 #include <sys/buf.h>
55 #include <sys/proc.h>
56 #include <sys/mount.h>
57 #include <sys/vnode.h>
58 #include <sys/malloc.h>
59 #include <sys/dirent.h>
60 #include <sys/lockf.h>
61
62 #include <miscfs/specfs/specdev.h>
63 #include <miscfs/fifofs/fifo.h>
64
65 #include <ufs/ufs/quota.h>
66 #include <ufs/ufs/inode.h>
67 #include <ufs/ufs/dir.h>
68 #include <ufs/ufs/ufsmount.h>
69 #include <ufs/ufs/ufs_bswap.h>
70 #include <ufs/ufs/ufs_extern.h>
71 #include <ufs/ext2fs/ext2fs_extern.h>
72 #include <ufs/lfs/lfs_extern.h>
73
74 #include <uvm/uvm.h>
75
76 static int ufs_chmod(struct vnode *, int, struct ucred *, struct proc *);
77 static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
78 struct proc *);
79
80 /*
81 * A virgin directory (no blushing please).
82 */
83 static const struct dirtemplate mastertemplate = {
84 0, 12, DT_DIR, 1, ".",
85 0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
86 };
87
88 /*
89 * Create a regular file
90 */
91 int
92 ufs_create(void *v)
93 {
94 struct vop_create_args /* {
95 struct vnode *a_dvp;
96 struct vnode **a_vpp;
97 struct componentname *a_cnp;
98 struct vattr *a_vap;
99 } */ *ap = v;
100 int error;
101
102 error =
103 ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
104 ap->a_dvp, ap->a_vpp, ap->a_cnp);
105 if (error)
106 return (error);
107 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
108 return (0);
109 }
110
111 /*
112 * Mknod vnode call
113 */
114 /* ARGSUSED */
115 int
116 ufs_mknod(void *v)
117 {
118 struct vop_mknod_args /* {
119 struct vnode *a_dvp;
120 struct vnode **a_vpp;
121 struct componentname *a_cnp;
122 struct vattr *a_vap;
123 } */ *ap = v;
124 struct vattr *vap;
125 struct vnode **vpp;
126 struct inode *ip;
127 int error;
128 struct mount *mp;
129 ino_t ino;
130
131 vap = ap->a_vap;
132 vpp = ap->a_vpp;
133 if ((error =
134 ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
135 ap->a_dvp, vpp, ap->a_cnp)) != 0)
136 return (error);
137 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
138 ip = VTOI(*vpp);
139 mp = (*vpp)->v_mount;
140 ino = ip->i_number;
141 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
142 if (vap->va_rdev != VNOVAL) {
143 /*
144 * Want to be able to use this to make badblock
145 * inodes, so don't truncate the dev number.
146 */
147 if (ip->i_ump->um_fstype == UFS1)
148 ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev,
149 UFS_MPNEEDSWAP(mp));
150 else
151 ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev,
152 UFS_MPNEEDSWAP(mp));
153 }
154 /*
155 * Remove inode so that it will be reloaded by VFS_VGET and
156 * checked to see if it is an alias of an existing entry in
157 * the inode cache.
158 */
159 vput(*vpp);
160 (*vpp)->v_type = VNON;
161 vgone(*vpp);
162 error = VFS_VGET(mp, ino, vpp);
163 if (error != 0) {
164 *vpp = NULL;
165 return (error);
166 }
167 return (0);
168 }
169
170 /*
171 * Open called.
172 *
173 * Nothing to do.
174 */
175 /* ARGSUSED */
176 int
177 ufs_open(void *v)
178 {
179 struct vop_open_args /* {
180 struct vnode *a_vp;
181 int a_mode;
182 struct ucred *a_cred;
183 struct proc *a_p;
184 } */ *ap = v;
185
186 /*
187 * Files marked append-only must be opened for appending.
188 */
189 if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
190 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
191 return (EPERM);
192 return (0);
193 }
194
195 /*
196 * Close called.
197 *
198 * Update the times on the inode.
199 */
200 /* ARGSUSED */
201 int
202 ufs_close(void *v)
203 {
204 struct vop_close_args /* {
205 struct vnode *a_vp;
206 int a_fflag;
207 struct ucred *a_cred;
208 struct proc *a_p;
209 } */ *ap = v;
210 struct vnode *vp;
211 struct inode *ip;
212 struct timespec ts;
213
214 vp = ap->a_vp;
215 ip = VTOI(vp);
216 simple_lock(&vp->v_interlock);
217 if (vp->v_usecount > 1) {
218 TIMEVAL_TO_TIMESPEC(&time, &ts);
219 ITIMES(ip, &ts, &ts, &ts);
220 }
221 simple_unlock(&vp->v_interlock);
222 return (0);
223 }
224
225 int
226 ufs_access(void *v)
227 {
228 struct vop_access_args /* {
229 struct vnode *a_vp;
230 int a_mode;
231 struct ucred *a_cred;
232 struct proc *a_p;
233 } */ *ap = v;
234 struct vnode *vp;
235 struct inode *ip;
236 mode_t mode;
237 #ifdef QUOTA
238 int error;
239 #endif
240
241 vp = ap->a_vp;
242 ip = VTOI(vp);
243 mode = ap->a_mode;
244 /*
245 * Disallow write attempts on read-only file systems;
246 * unless the file is a socket, fifo, or a block or
247 * character device resident on the file system.
248 */
249 if (mode & VWRITE) {
250 switch (vp->v_type) {
251 case VDIR:
252 case VLNK:
253 case VREG:
254 if (vp->v_mount->mnt_flag & MNT_RDONLY)
255 return (EROFS);
256 #ifdef QUOTA
257 if ((error = getinoquota(ip)) != 0)
258 return (error);
259 #endif
260 break;
261 case VBAD:
262 case VBLK:
263 case VCHR:
264 case VSOCK:
265 case VFIFO:
266 case VNON:
267 default:
268 break;
269 }
270 }
271
272 /* If immutable bit set, nobody gets to write it. */
273 if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
274 return (EPERM);
275
276 return (vaccess(vp->v_type, ip->i_mode & ALLPERMS,
277 ip->i_uid, ip->i_gid, mode, ap->a_cred));
278 }
279
280 /* ARGSUSED */
281 int
282 ufs_getattr(void *v)
283 {
284 struct vop_getattr_args /* {
285 struct vnode *a_vp;
286 struct vattr *a_vap;
287 struct ucred *a_cred;
288 struct proc *a_p;
289 } */ *ap = v;
290 struct vnode *vp;
291 struct inode *ip;
292 struct vattr *vap;
293 struct timespec ts;
294
295 vp = ap->a_vp;
296 ip = VTOI(vp);
297 vap = ap->a_vap;
298 TIMEVAL_TO_TIMESPEC(&time, &ts);
299 ITIMES(ip, &ts, &ts, &ts);
300
301 /*
302 * Copy from inode table
303 */
304 vap->va_fsid = ip->i_dev;
305 vap->va_fileid = ip->i_number;
306 vap->va_mode = ip->i_mode & ALLPERMS;
307 vap->va_nlink = ip->i_ffs_effnlink;
308 vap->va_uid = ip->i_uid;
309 vap->va_gid = ip->i_gid;
310 vap->va_size = vp->v_size;
311 if (ip->i_ump->um_fstype == UFS1) {
312 vap->va_rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
313 UFS_MPNEEDSWAP(vp->v_mount));
314 vap->va_atime.tv_sec = ip->i_ffs1_atime;
315 vap->va_atime.tv_nsec = ip->i_ffs1_atimensec;
316 vap->va_mtime.tv_sec = ip->i_ffs1_mtime;
317 vap->va_mtime.tv_nsec = ip->i_ffs1_mtimensec;
318 vap->va_ctime.tv_sec = ip->i_ffs1_ctime;
319 vap->va_ctime.tv_nsec = ip->i_ffs1_ctimensec;
320 vap->va_birthtime.tv_sec = 0;
321 vap->va_birthtime.tv_nsec = 0;
322 vap->va_bytes = dbtob((u_quad_t)ip->i_ffs1_blocks);
323 } else {
324 vap->va_rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
325 UFS_MPNEEDSWAP(vp->v_mount));
326 vap->va_atime.tv_sec = ip->i_ffs2_atime;
327 vap->va_atime.tv_nsec = ip->i_ffs2_atimensec;
328 vap->va_mtime.tv_sec = ip->i_ffs2_mtime;
329 vap->va_mtime.tv_nsec = ip->i_ffs2_mtimensec;
330 vap->va_ctime.tv_sec = ip->i_ffs2_ctime;
331 vap->va_ctime.tv_nsec = ip->i_ffs2_ctimensec;
332 vap->va_birthtime.tv_sec = ip->i_ffs2_birthtime;
333 vap->va_birthtime.tv_nsec = ip->i_ffs2_birthnsec;
334 vap->va_bytes = dbtob(ip->i_ffs2_blocks);
335 }
336 vap->va_gen = ip->i_gen;
337 vap->va_flags = ip->i_flags;
338
339 /* this doesn't belong here */
340 if (vp->v_type == VBLK)
341 vap->va_blocksize = BLKDEV_IOSIZE;
342 else if (vp->v_type == VCHR)
343 vap->va_blocksize = MAXBSIZE;
344 else
345 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
346 vap->va_type = vp->v_type;
347 vap->va_filerev = ip->i_modrev;
348 return (0);
349 }
350
351 /*
352 * Set attribute vnode op. called from several syscalls
353 */
354 int
355 ufs_setattr(void *v)
356 {
357 struct vop_setattr_args /* {
358 struct vnode *a_vp;
359 struct vattr *a_vap;
360 struct ucred *a_cred;
361 struct proc *a_p;
362 } */ *ap = v;
363 struct vattr *vap;
364 struct vnode *vp;
365 struct inode *ip;
366 struct ucred *cred;
367 struct proc *p;
368 int error;
369
370 vap = ap->a_vap;
371 vp = ap->a_vp;
372 ip = VTOI(vp);
373 cred = ap->a_cred;
374 p = ap->a_p;
375
376 /*
377 * Check for unsettable attributes.
378 */
379 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
380 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
381 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
382 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
383 return (EINVAL);
384 }
385 if (vap->va_flags != VNOVAL) {
386 if (vp->v_mount->mnt_flag & MNT_RDONLY)
387 return (EROFS);
388 if (cred->cr_uid != ip->i_uid &&
389 (error = suser(cred, &p->p_acflag)))
390 return (error);
391 if (cred->cr_uid == 0) {
392 if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) &&
393 securelevel > 0)
394 return (EPERM);
395 ip->i_flags = vap->va_flags;
396 DIP_ASSIGN(ip, flags, ip->i_flags);
397 } else {
398 if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) ||
399 (vap->va_flags & UF_SETTABLE) != vap->va_flags)
400 return (EPERM);
401 if ((ip->i_flags & SF_SETTABLE) !=
402 (vap->va_flags & SF_SETTABLE))
403 return (EPERM);
404 ip->i_flags &= SF_SETTABLE;
405 ip->i_flags |= (vap->va_flags & UF_SETTABLE);
406 DIP_ASSIGN(ip, flags, ip->i_flags);
407 }
408 ip->i_flag |= IN_CHANGE;
409 if (vap->va_flags & (IMMUTABLE | APPEND))
410 return (0);
411 }
412 if (ip->i_flags & (IMMUTABLE | APPEND))
413 return (EPERM);
414 /*
415 * Go through the fields and update iff not VNOVAL.
416 */
417 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
418 if (vp->v_mount->mnt_flag & MNT_RDONLY)
419 return (EROFS);
420 error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
421 if (error)
422 return (error);
423 }
424 if (vap->va_size != VNOVAL) {
425 /*
426 * Disallow write attempts on read-only file systems;
427 * unless the file is a socket, fifo, or a block or
428 * character device resident on the file system.
429 */
430 switch (vp->v_type) {
431 case VDIR:
432 return (EISDIR);
433 case VLNK:
434 case VREG:
435 if (vp->v_mount->mnt_flag & MNT_RDONLY)
436 return (EROFS);
437 break;
438 default:
439 break;
440 }
441 error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p);
442 if (error)
443 return (error);
444 }
445 ip = VTOI(vp);
446 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
447 vap->va_birthtime.tv_sec != VNOVAL) {
448 if (vp->v_mount->mnt_flag & MNT_RDONLY)
449 return (EROFS);
450 if (cred->cr_uid != ip->i_uid &&
451 (error = suser(cred, &p->p_acflag)) &&
452 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
453 (error = VOP_ACCESS(vp, VWRITE, cred, p))))
454 return (error);
455 if (vap->va_atime.tv_sec != VNOVAL)
456 if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
457 ip->i_flag |= IN_ACCESS;
458 if (vap->va_mtime.tv_sec != VNOVAL)
459 ip->i_flag |= IN_CHANGE | IN_UPDATE;
460 if (vap->va_birthtime.tv_sec != VNOVAL &&
461 ip->i_ump->um_fstype == UFS2) {
462 ip->i_ffs2_birthtime = vap->va_birthtime.tv_sec;
463 ip->i_ffs2_birthnsec = vap->va_birthtime.tv_nsec;
464 }
465 error = VOP_UPDATE(vp, &vap->va_atime, &vap->va_mtime, 0);
466 if (error)
467 return (error);
468 }
469 error = 0;
470 if (vap->va_mode != (mode_t)VNOVAL) {
471 if (vp->v_mount->mnt_flag & MNT_RDONLY)
472 return (EROFS);
473 error = ufs_chmod(vp, (int)vap->va_mode, cred, p);
474 }
475 VN_KNOTE(vp, NOTE_ATTRIB);
476 return (error);
477 }
478
479 /*
480 * Change the mode on a file.
481 * Inode must be locked before calling.
482 */
483 static int
484 ufs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct proc *p)
485 {
486 struct inode *ip;
487 int error;
488
489 ip = VTOI(vp);
490 if (cred->cr_uid != ip->i_uid &&
491 (error = suser(cred, &p->p_acflag)))
492 return (error);
493 if (cred->cr_uid) {
494 if (vp->v_type != VDIR && (mode & S_ISTXT))
495 return (EFTYPE);
496 if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
497 return (EPERM);
498 }
499 ip->i_mode &= ~ALLPERMS;
500 ip->i_mode |= (mode & ALLPERMS);
501 ip->i_flag |= IN_CHANGE;
502 DIP_ASSIGN(ip, mode, ip->i_mode);
503 return (0);
504 }
505
506 /*
507 * Perform chown operation on inode ip;
508 * inode must be locked prior to call.
509 */
510 static int
511 ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
512 struct proc *p)
513 {
514 struct inode *ip;
515 int error;
516 #ifdef QUOTA
517 uid_t ouid;
518 gid_t ogid;
519 int i;
520 int64_t change;
521 #endif
522 ip = VTOI(vp);
523 error = 0;
524
525 if (uid == (uid_t)VNOVAL)
526 uid = ip->i_uid;
527 if (gid == (gid_t)VNOVAL)
528 gid = ip->i_gid;
529 /*
530 * If we don't own the file, are trying to change the owner
531 * of the file, or are not a member of the target group,
532 * the caller's credentials must imply super-user privilege
533 * or the call fails.
534 */
535 if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
536 (gid != ip->i_gid &&
537 !(cred->cr_gid == gid || groupmember((gid_t)gid, cred)))) &&
538 ((error = suser(cred, &p->p_acflag)) != 0))
539 return (error);
540
541 #ifdef QUOTA
542 ogid = ip->i_gid;
543 ouid = ip->i_uid;
544 if ((error = getinoquota(ip)) != 0)
545 return (error);
546 if (ouid == uid) {
547 dqrele(vp, ip->i_dquot[USRQUOTA]);
548 ip->i_dquot[USRQUOTA] = NODQUOT;
549 }
550 if (ogid == gid) {
551 dqrele(vp, ip->i_dquot[GRPQUOTA]);
552 ip->i_dquot[GRPQUOTA] = NODQUOT;
553 }
554 change = DIP(ip, blocks);
555 (void) chkdq(ip, -change, cred, CHOWN);
556 (void) chkiq(ip, -1, cred, CHOWN);
557 for (i = 0; i < MAXQUOTAS; i++) {
558 dqrele(vp, ip->i_dquot[i]);
559 ip->i_dquot[i] = NODQUOT;
560 }
561 #endif
562 ip->i_gid = gid;
563 DIP_ASSIGN(ip, gid, gid);
564 ip->i_uid = uid;
565 DIP_ASSIGN(ip, uid, uid);
566 #ifdef QUOTA
567 if ((error = getinoquota(ip)) == 0) {
568 if (ouid == uid) {
569 dqrele(vp, ip->i_dquot[USRQUOTA]);
570 ip->i_dquot[USRQUOTA] = NODQUOT;
571 }
572 if (ogid == gid) {
573 dqrele(vp, ip->i_dquot[GRPQUOTA]);
574 ip->i_dquot[GRPQUOTA] = NODQUOT;
575 }
576 if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
577 if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
578 goto good;
579 else
580 (void) chkdq(ip, -change, cred, CHOWN|FORCE);
581 }
582 for (i = 0; i < MAXQUOTAS; i++) {
583 dqrele(vp, ip->i_dquot[i]);
584 ip->i_dquot[i] = NODQUOT;
585 }
586 }
587 ip->i_gid = ogid;
588 DIP_ASSIGN(ip, gid, ogid);
589 ip->i_uid = ouid;
590 DIP_ASSIGN(ip, uid, ouid);
591 if (getinoquota(ip) == 0) {
592 if (ouid == uid) {
593 dqrele(vp, ip->i_dquot[USRQUOTA]);
594 ip->i_dquot[USRQUOTA] = NODQUOT;
595 }
596 if (ogid == gid) {
597 dqrele(vp, ip->i_dquot[GRPQUOTA]);
598 ip->i_dquot[GRPQUOTA] = NODQUOT;
599 }
600 (void) chkdq(ip, change, cred, FORCE|CHOWN);
601 (void) chkiq(ip, 1, cred, FORCE|CHOWN);
602 (void) getinoquota(ip);
603 }
604 return (error);
605 good:
606 if (getinoquota(ip))
607 panic("chown: lost quota");
608 #endif /* QUOTA */
609 ip->i_flag |= IN_CHANGE;
610 return (0);
611 }
612
613 int
614 ufs_remove(void *v)
615 {
616 struct vop_remove_args /* {
617 struct vnode *a_dvp;
618 struct vnode *a_vp;
619 struct componentname *a_cnp;
620 } */ *ap = v;
621 struct vnode *vp, *dvp;
622 struct inode *ip;
623 int error;
624
625 vp = ap->a_vp;
626 dvp = ap->a_dvp;
627 ip = VTOI(vp);
628 if (vp->v_type == VDIR || (ip->i_flags & (IMMUTABLE | APPEND)) ||
629 (VTOI(dvp)->i_flags & APPEND))
630 error = EPERM;
631 else
632 error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
633 VN_KNOTE(vp, NOTE_DELETE);
634 VN_KNOTE(dvp, NOTE_WRITE);
635 if (dvp == vp)
636 vrele(vp);
637 else
638 vput(vp);
639 vput(dvp);
640 return (error);
641 }
642
643 /*
644 * link vnode call
645 */
646 int
647 ufs_link(void *v)
648 {
649 struct vop_link_args /* {
650 struct vnode *a_dvp;
651 struct vnode *a_vp;
652 struct componentname *a_cnp;
653 } */ *ap = v;
654 struct vnode *vp, *dvp;
655 struct componentname *cnp;
656 struct inode *ip;
657 struct direct newdir;
658 int error;
659
660 dvp = ap->a_dvp;
661 vp = ap->a_vp;
662 cnp = ap->a_cnp;
663 #ifdef DIAGNOSTIC
664 if ((cnp->cn_flags & HASBUF) == 0)
665 panic("ufs_link: no name");
666 #endif
667 if (vp->v_type == VDIR) {
668 VOP_ABORTOP(dvp, cnp);
669 error = EPERM;
670 goto out2;
671 }
672 if (dvp->v_mount != vp->v_mount) {
673 VOP_ABORTOP(dvp, cnp);
674 error = EXDEV;
675 goto out2;
676 }
677 if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) {
678 VOP_ABORTOP(dvp, cnp);
679 goto out2;
680 }
681 ip = VTOI(vp);
682 if ((nlink_t)ip->i_nlink >= LINK_MAX) {
683 VOP_ABORTOP(dvp, cnp);
684 error = EMLINK;
685 goto out1;
686 }
687 if (ip->i_flags & (IMMUTABLE | APPEND)) {
688 VOP_ABORTOP(dvp, cnp);
689 error = EPERM;
690 goto out1;
691 }
692 ip->i_ffs_effnlink++;
693 ip->i_nlink++;
694 DIP_ASSIGN(ip, nlink, ip->i_nlink);
695 ip->i_flag |= IN_CHANGE;
696 if (DOINGSOFTDEP(vp))
697 softdep_change_linkcnt(ip);
698 error = VOP_UPDATE(vp, NULL, NULL, UPDATE_DIROP);
699 if (!error) {
700 ufs_makedirentry(ip, cnp, &newdir);
701 error = ufs_direnter(dvp, vp, &newdir, cnp, NULL);
702 }
703 if (error) {
704 ip->i_ffs_effnlink--;
705 ip->i_nlink--;
706 DIP_ASSIGN(ip, nlink, ip->i_nlink);
707 ip->i_flag |= IN_CHANGE;
708 if (DOINGSOFTDEP(vp))
709 softdep_change_linkcnt(ip);
710 }
711 PNBUF_PUT(cnp->cn_pnbuf);
712 out1:
713 if (dvp != vp)
714 VOP_UNLOCK(vp, 0);
715 out2:
716 VN_KNOTE(vp, NOTE_LINK);
717 VN_KNOTE(dvp, NOTE_WRITE);
718 vput(dvp);
719 return (error);
720 }
721
722 /*
723 * whiteout vnode call
724 */
725 int
726 ufs_whiteout(void *v)
727 {
728 struct vop_whiteout_args /* {
729 struct vnode *a_dvp;
730 struct componentname *a_cnp;
731 int a_flags;
732 } */ *ap = v;
733 struct vnode *dvp;
734 struct componentname *cnp;
735 struct direct newdir;
736 int error;
737
738 dvp = ap->a_dvp;
739 cnp = ap->a_cnp;
740 error = 0;
741 switch (ap->a_flags) {
742 case LOOKUP:
743 /* 4.4 format directories support whiteout operations */
744 if (dvp->v_mount->mnt_maxsymlinklen > 0)
745 return (0);
746 return (EOPNOTSUPP);
747
748 case CREATE:
749 /* create a new directory whiteout */
750 #ifdef DIAGNOSTIC
751 if ((cnp->cn_flags & SAVENAME) == 0)
752 panic("ufs_whiteout: missing name");
753 if (dvp->v_mount->mnt_maxsymlinklen <= 0)
754 panic("ufs_whiteout: old format filesystem");
755 #endif
756
757 newdir.d_ino = WINO;
758 newdir.d_namlen = cnp->cn_namelen;
759 memcpy(newdir.d_name, cnp->cn_nameptr,
760 (size_t)cnp->cn_namelen);
761 newdir.d_name[cnp->cn_namelen] = '\0';
762 newdir.d_type = DT_WHT;
763 error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL);
764 break;
765
766 case DELETE:
767 /* remove an existing directory whiteout */
768 #ifdef DIAGNOSTIC
769 if (dvp->v_mount->mnt_maxsymlinklen <= 0)
770 panic("ufs_whiteout: old format filesystem");
771 #endif
772
773 cnp->cn_flags &= ~DOWHITEOUT;
774 error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
775 break;
776 default:
777 panic("ufs_whiteout: unknown op");
778 /* NOTREACHED */
779 }
780 if (cnp->cn_flags & HASBUF) {
781 PNBUF_PUT(cnp->cn_pnbuf);
782 cnp->cn_flags &= ~HASBUF;
783 }
784 return (error);
785 }
786
787
788 /*
789 * Rename system call.
790 * rename("foo", "bar");
791 * is essentially
792 * unlink("bar");
793 * link("foo", "bar");
794 * unlink("foo");
795 * but ``atomically''. Can't do full commit without saving state in the
796 * inode on disk which isn't feasible at this time. Best we can do is
797 * always guarantee the target exists.
798 *
799 * Basic algorithm is:
800 *
801 * 1) Bump link count on source while we're linking it to the
802 * target. This also ensure the inode won't be deleted out
803 * from underneath us while we work (it may be truncated by
804 * a concurrent `trunc' or `open' for creation).
805 * 2) Link source to destination. If destination already exists,
806 * delete it first.
807 * 3) Unlink source reference to inode if still around. If a
808 * directory was moved and the parent of the destination
809 * is different from the source, patch the ".." entry in the
810 * directory.
811 */
812 int
813 ufs_rename(void *v)
814 {
815 struct vop_rename_args /* {
816 struct vnode *a_fdvp;
817 struct vnode *a_fvp;
818 struct componentname *a_fcnp;
819 struct vnode *a_tdvp;
820 struct vnode *a_tvp;
821 struct componentname *a_tcnp;
822 } */ *ap = v;
823 struct vnode *tvp, *tdvp, *fvp, *fdvp;
824 struct componentname *tcnp, *fcnp;
825 struct inode *ip, *xp, *dp;
826 struct direct newdir;
827 int doingdirectory, oldparent, newparent, error;
828
829 tvp = ap->a_tvp;
830 tdvp = ap->a_tdvp;
831 fvp = ap->a_fvp;
832 fdvp = ap->a_fdvp;
833 tcnp = ap->a_tcnp;
834 fcnp = ap->a_fcnp;
835 doingdirectory = oldparent = newparent = error = 0;
836
837 #ifdef DIAGNOSTIC
838 if ((tcnp->cn_flags & HASBUF) == 0 ||
839 (fcnp->cn_flags & HASBUF) == 0)
840 panic("ufs_rename: no name");
841 #endif
842 /*
843 * Check for cross-device rename.
844 */
845 if ((fvp->v_mount != tdvp->v_mount) ||
846 (tvp && (fvp->v_mount != tvp->v_mount))) {
847 error = EXDEV;
848 abortit:
849 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
850 if (tdvp == tvp)
851 vrele(tdvp);
852 else
853 vput(tdvp);
854 if (tvp)
855 vput(tvp);
856 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
857 vrele(fdvp);
858 vrele(fvp);
859 return (error);
860 }
861
862 /*
863 * Check if just deleting a link name.
864 */
865 if (tvp && ((VTOI(tvp)->i_flags & (IMMUTABLE | APPEND)) ||
866 (VTOI(tdvp)->i_flags & APPEND))) {
867 error = EPERM;
868 goto abortit;
869 }
870 if (fvp == tvp) {
871 if (fvp->v_type == VDIR) {
872 error = EINVAL;
873 goto abortit;
874 }
875
876 /* Release destination completely. */
877 VOP_ABORTOP(tdvp, tcnp);
878 vput(tdvp);
879 vput(tvp);
880
881 /* Delete source. */
882 vrele(fvp);
883 fcnp->cn_flags &= ~(MODMASK | SAVESTART);
884 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
885 fcnp->cn_nameiop = DELETE;
886 if ((error = relookup(fdvp, &fvp, fcnp))){
887 /* relookup blew away fdvp */
888 return (error);
889 }
890 return (VOP_REMOVE(fdvp, fvp, fcnp));
891 }
892 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
893 goto abortit;
894 dp = VTOI(fdvp);
895 ip = VTOI(fvp);
896 if ((nlink_t) ip->i_nlink >= LINK_MAX) {
897 VOP_UNLOCK(fvp, 0);
898 error = EMLINK;
899 goto abortit;
900 }
901 if ((ip->i_flags & (IMMUTABLE | APPEND)) ||
902 (dp->i_flags & APPEND)) {
903 VOP_UNLOCK(fvp, 0);
904 error = EPERM;
905 goto abortit;
906 }
907 if ((ip->i_mode & IFMT) == IFDIR) {
908 /*
909 * Avoid ".", "..", and aliases of "." for obvious reasons.
910 */
911 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
912 dp == ip ||
913 (fcnp->cn_flags & ISDOTDOT) ||
914 (tcnp->cn_flags & ISDOTDOT) ||
915 (ip->i_flag & IN_RENAME)) {
916 VOP_UNLOCK(fvp, 0);
917 error = EINVAL;
918 goto abortit;
919 }
920 ip->i_flag |= IN_RENAME;
921 oldparent = dp->i_number;
922 doingdirectory = 1;
923 }
924 VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */
925 /* vrele(fdvp); */
926
927 /*
928 * When the target exists, both the directory
929 * and target vnodes are returned locked.
930 */
931 dp = VTOI(tdvp);
932 xp = NULL;
933 if (tvp)
934 xp = VTOI(tvp);
935
936 /*
937 * 1) Bump link count while we're moving stuff
938 * around. If we crash somewhere before
939 * completing our work, the link count
940 * may be wrong, but correctable.
941 */
942 ip->i_ffs_effnlink++;
943 ip->i_nlink++;
944 DIP_ASSIGN(ip, nlink, ip->i_nlink);
945 ip->i_flag |= IN_CHANGE;
946 if (DOINGSOFTDEP(fvp))
947 softdep_change_linkcnt(ip);
948 if ((error = VOP_UPDATE(fvp, NULL, NULL, UPDATE_DIROP)) != 0) {
949 VOP_UNLOCK(fvp, 0);
950 goto bad;
951 }
952
953 /*
954 * If ".." must be changed (ie the directory gets a new
955 * parent) then the source directory must not be in the
956 * directory hierarchy above the target, as this would
957 * orphan everything below the source directory. Also
958 * the user must have write permission in the source so
959 * as to be able to change "..". We must repeat the call
960 * to namei, as the parent directory is unlocked by the
961 * call to checkpath().
962 */
963 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
964 VOP_UNLOCK(fvp, 0);
965 if (oldparent != dp->i_number)
966 newparent = dp->i_number;
967 if (doingdirectory && newparent) {
968 if (error) /* write access check above */
969 goto bad;
970 if (xp != NULL)
971 vput(tvp);
972 vref(tdvp); /* compensate for the ref checkpath looses */
973 if ((error = ufs_checkpath(ip, dp, tcnp->cn_cred)) != 0) {
974 vrele(tdvp);
975 goto out;
976 }
977 tcnp->cn_flags &= ~SAVESTART;
978 if ((error = relookup(tdvp, &tvp, tcnp)) != 0)
979 goto out;
980 dp = VTOI(tdvp);
981 xp = NULL;
982 if (tvp)
983 xp = VTOI(tvp);
984 }
985 /*
986 * 2) If target doesn't exist, link the target
987 * to the source and unlink the source.
988 * Otherwise, rewrite the target directory
989 * entry to reference the source inode and
990 * expunge the original entry's existence.
991 */
992 if (xp == NULL) {
993 if (dp->i_dev != ip->i_dev)
994 panic("rename: EXDEV");
995 /*
996 * Account for ".." in new directory.
997 * When source and destination have the same
998 * parent we don't fool with the link count.
999 */
1000 if (doingdirectory && newparent) {
1001 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1002 error = EMLINK;
1003 goto bad;
1004 }
1005 dp->i_ffs_effnlink++;
1006 dp->i_nlink++;
1007 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1008 dp->i_flag |= IN_CHANGE;
1009 if (DOINGSOFTDEP(tdvp))
1010 softdep_change_linkcnt(dp);
1011 if ((error = VOP_UPDATE(tdvp, NULL, NULL,
1012 UPDATE_DIROP)) != 0) {
1013 dp->i_ffs_effnlink--;
1014 dp->i_nlink--;
1015 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1016 dp->i_flag |= IN_CHANGE;
1017 if (DOINGSOFTDEP(tdvp))
1018 softdep_change_linkcnt(dp);
1019 goto bad;
1020 }
1021 }
1022 ufs_makedirentry(ip, tcnp, &newdir);
1023 error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL);
1024 if (error != 0) {
1025 if (doingdirectory && newparent) {
1026 dp->i_ffs_effnlink--;
1027 dp->i_nlink--;
1028 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1029 dp->i_flag |= IN_CHANGE;
1030 if (DOINGSOFTDEP(tdvp))
1031 softdep_change_linkcnt(dp);
1032 (void)VOP_UPDATE(tdvp, NULL, NULL,
1033 UPDATE_WAIT|UPDATE_DIROP);
1034 }
1035 goto bad;
1036 }
1037 VN_KNOTE(tdvp, NOTE_WRITE);
1038 vput(tdvp);
1039 } else {
1040 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1041 panic("rename: EXDEV");
1042 /*
1043 * Short circuit rename(foo, foo).
1044 */
1045 if (xp->i_number == ip->i_number)
1046 panic("rename: same file");
1047 /*
1048 * If the parent directory is "sticky", then the user must
1049 * own the parent directory, or the destination of the rename,
1050 * otherwise the destination may not be changed (except by
1051 * root). This implements append-only directories.
1052 */
1053 if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
1054 tcnp->cn_cred->cr_uid != dp->i_uid &&
1055 xp->i_uid != tcnp->cn_cred->cr_uid) {
1056 error = EPERM;
1057 goto bad;
1058 }
1059 /*
1060 * Target must be empty if a directory and have no links
1061 * to it. Also, ensure source and target are compatible
1062 * (both directories, or both not directories).
1063 */
1064 if ((xp->i_mode & IFMT) == IFDIR) {
1065 if (xp->i_ffs_effnlink > 2 ||
1066 !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
1067 error = ENOTEMPTY;
1068 goto bad;
1069 }
1070 if (!doingdirectory) {
1071 error = ENOTDIR;
1072 goto bad;
1073 }
1074 cache_purge(tdvp);
1075 } else if (doingdirectory) {
1076 error = EISDIR;
1077 goto bad;
1078 }
1079 if ((error = ufs_dirrewrite(dp, xp, ip->i_number,
1080 IFTODT(ip->i_mode), doingdirectory && newparent ?
1081 newparent : doingdirectory, IN_CHANGE|IN_UPDATE)) != 0)
1082 goto bad;
1083 if (doingdirectory) {
1084 if (!newparent) {
1085 dp->i_ffs_effnlink--;
1086 if (DOINGSOFTDEP(tdvp))
1087 softdep_change_linkcnt(dp);
1088 }
1089 xp->i_ffs_effnlink--;
1090 if (DOINGSOFTDEP(tvp))
1091 softdep_change_linkcnt(xp);
1092 }
1093 if (doingdirectory && !DOINGSOFTDEP(tvp)) {
1094 /*
1095 * Truncate inode. The only stuff left in the directory
1096 * is "." and "..". The "." reference is inconsequential
1097 * since we are quashing it. We have removed the "."
1098 * reference and the reference in the parent directory,
1099 * but there may be other hard links. The soft
1100 * dependency code will arrange to do these operations
1101 * after the parent directory entry has been deleted on
1102 * disk, so when running with that code we avoid doing
1103 * them now.
1104 */
1105 if (!newparent) {
1106 dp->i_nlink--;
1107 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1108 dp->i_flag |= IN_CHANGE;
1109 }
1110 xp->i_nlink--;
1111 DIP_ASSIGN(xp, nlink, xp->i_nlink);
1112 xp->i_flag |= IN_CHANGE;
1113 if ((error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
1114 tcnp->cn_cred, tcnp->cn_proc)))
1115 goto bad;
1116 }
1117 VN_KNOTE(tdvp, NOTE_WRITE);
1118 vput(tdvp);
1119 VN_KNOTE(tvp, NOTE_DELETE);
1120 vput(tvp);
1121 xp = NULL;
1122 }
1123
1124 /*
1125 * 3) Unlink the source.
1126 */
1127 fcnp->cn_flags &= ~(MODMASK | SAVESTART);
1128 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1129 if ((error = relookup(fdvp, &fvp, fcnp))) {
1130 vrele(ap->a_fvp);
1131 return (error);
1132 }
1133 if (fvp != NULL) {
1134 xp = VTOI(fvp);
1135 dp = VTOI(fdvp);
1136 } else {
1137 /*
1138 * From name has disappeared.
1139 */
1140 if (doingdirectory)
1141 panic("rename: lost dir entry");
1142 vrele(ap->a_fvp);
1143 return (0);
1144 }
1145 /*
1146 * Ensure that the directory entry still exists and has not
1147 * changed while the new name has been entered. If the source is
1148 * a file then the entry may have been unlinked or renamed. In
1149 * either case there is no further work to be done. If the source
1150 * is a directory then it cannot have been rmdir'ed; The IRENAME
1151 * flag ensures that it cannot be moved by another rename or removed
1152 * by a rmdir.
1153 */
1154 if (xp != ip) {
1155 if (doingdirectory)
1156 panic("rename: lost dir entry");
1157 } else {
1158 /*
1159 * If the source is a directory with a
1160 * new parent, the link count of the old
1161 * parent directory must be decremented
1162 * and ".." set to point to the new parent.
1163 */
1164 if (doingdirectory && newparent) {
1165 xp->i_offset = mastertemplate.dot_reclen;
1166 ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0, IN_CHANGE);
1167 cache_purge(fdvp);
1168 }
1169 error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
1170 xp->i_flag &= ~IN_RENAME;
1171 }
1172 VN_KNOTE(fvp, NOTE_RENAME);
1173 if (dp)
1174 vput(fdvp);
1175 if (xp)
1176 vput(fvp);
1177 vrele(ap->a_fvp);
1178 return (error);
1179
1180 /* exit routines from steps 1 & 2 */
1181 bad:
1182 if (xp)
1183 vput(ITOV(xp));
1184 vput(ITOV(dp));
1185 out:
1186 if (doingdirectory)
1187 ip->i_flag &= ~IN_RENAME;
1188 if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
1189 ip->i_ffs_effnlink--;
1190 ip->i_nlink--;
1191 DIP_ASSIGN(ip, nlink, ip->i_nlink);
1192 ip->i_flag |= IN_CHANGE;
1193 ip->i_flag &= ~IN_RENAME;
1194 if (DOINGSOFTDEP(fvp))
1195 softdep_change_linkcnt(ip);
1196 vput(fvp);
1197 } else
1198 vrele(fvp);
1199 vrele(fdvp);
1200 return (error);
1201 }
1202
1203 /*
1204 * Mkdir system call
1205 */
1206 int
1207 ufs_mkdir(void *v)
1208 {
1209 struct vop_mkdir_args /* {
1210 struct vnode *a_dvp;
1211 struct vnode **a_vpp;
1212 struct componentname *a_cnp;
1213 struct vattr *a_vap;
1214 } */ *ap = v;
1215 struct vnode *dvp, *tvp;
1216 struct vattr *vap;
1217 struct componentname *cnp;
1218 struct inode *ip, *dp;
1219 struct buf *bp;
1220 struct dirtemplate dirtemplate;
1221 struct direct newdir;
1222 int error, dmode, blkoff;
1223 int dirblksiz = DIRBLKSIZ;
1224 if (UFS_MPISAPPLEUFS(ap->a_dvp->v_mount)) {
1225 dirblksiz = APPLEUFS_DIRBLKSIZ;
1226 }
1227
1228 dvp = ap->a_dvp;
1229 vap = ap->a_vap;
1230 cnp = ap->a_cnp;
1231 #ifdef DIAGNOSTIC
1232 if ((cnp->cn_flags & HASBUF) == 0)
1233 panic("ufs_mkdir: no name");
1234 #endif
1235 dp = VTOI(dvp);
1236 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1237 error = EMLINK;
1238 goto out;
1239 }
1240 dmode = vap->va_mode & ACCESSPERMS;
1241 dmode |= IFDIR;
1242 /*
1243 * Must simulate part of ufs_makeinode here to acquire the inode,
1244 * but not have it entered in the parent directory. The entry is
1245 * made later after writing "." and ".." entries.
1246 */
1247 if ((error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp)) != 0)
1248 goto out;
1249 ip = VTOI(tvp);
1250 ip->i_uid = cnp->cn_cred->cr_uid;
1251 DIP_ASSIGN(ip, uid, ip->i_uid);
1252 ip->i_gid = dp->i_gid;
1253 DIP_ASSIGN(ip, gid, ip->i_gid);
1254 #ifdef QUOTA
1255 if ((error = getinoquota(ip)) ||
1256 (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
1257 PNBUF_PUT(cnp->cn_pnbuf);
1258 VOP_VFREE(tvp, ip->i_number, dmode);
1259 vput(tvp);
1260 vput(dvp);
1261 return (error);
1262 }
1263 #endif
1264 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1265 ip->i_mode = dmode;
1266 DIP_ASSIGN(ip, mode, dmode);
1267 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
1268 ip->i_ffs_effnlink = 2;
1269 ip->i_nlink = 2;
1270 DIP_ASSIGN(ip, nlink, 2);
1271 if (DOINGSOFTDEP(tvp))
1272 softdep_change_linkcnt(ip);
1273 if (cnp->cn_flags & ISWHITEOUT) {
1274 ip->i_flags |= UF_OPAQUE;
1275 DIP_ASSIGN(ip, flags, ip->i_flags);
1276 }
1277
1278 /*
1279 * Bump link count in parent directory to reflect work done below.
1280 * Should be done before reference is created so cleanup is
1281 * possible if we crash.
1282 */
1283 dp->i_ffs_effnlink++;
1284 dp->i_nlink++;
1285 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1286 dp->i_flag |= IN_CHANGE;
1287 if (DOINGSOFTDEP(dvp))
1288 softdep_change_linkcnt(dp);
1289 if ((error = VOP_UPDATE(dvp, NULL, NULL, UPDATE_DIROP)) != 0)
1290 goto bad;
1291
1292 /*
1293 * Initialize directory with "." and ".." from static template.
1294 */
1295 dirtemplate = mastertemplate;
1296 dirtemplate.dotdot_reclen = dirblksiz - dirtemplate.dot_reclen;
1297 dirtemplate.dot_ino = ufs_rw32(ip->i_number,
1298 UFS_MPNEEDSWAP(dvp->v_mount));
1299 dirtemplate.dotdot_ino = ufs_rw32(dp->i_number,
1300 UFS_MPNEEDSWAP(dvp->v_mount));
1301 dirtemplate.dot_reclen = ufs_rw16(dirtemplate.dot_reclen,
1302 UFS_MPNEEDSWAP(dvp->v_mount));
1303 dirtemplate.dotdot_reclen = ufs_rw16(dirtemplate.dotdot_reclen,
1304 UFS_MPNEEDSWAP(dvp->v_mount));
1305 if (dvp->v_mount->mnt_maxsymlinklen <= 0) {
1306 #if BYTE_ORDER == LITTLE_ENDIAN
1307 if (UFS_MPNEEDSWAP(dvp->v_mount) == 0)
1308 #else
1309 if (UFS_MPNEEDSWAP(dvp->v_mount) != 0)
1310 #endif
1311 {
1312 dirtemplate.dot_type = dirtemplate.dot_namlen;
1313 dirtemplate.dotdot_type = dirtemplate.dotdot_namlen;
1314 dirtemplate.dot_namlen = dirtemplate.dotdot_namlen = 0;
1315 } else
1316 dirtemplate.dot_type = dirtemplate.dotdot_type = 0;
1317 }
1318 if ((error = VOP_BALLOC(tvp, (off_t)0, dirblksiz, cnp->cn_cred,
1319 B_CLRBUF, &bp)) != 0)
1320 goto bad;
1321 ip->i_size = dirblksiz;
1322 DIP_ASSIGN(ip, size, dirblksiz);
1323 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1324 uvm_vnp_setsize(tvp, ip->i_size);
1325 memcpy((caddr_t)bp->b_data, (caddr_t)&dirtemplate, sizeof dirtemplate);
1326 if (DOINGSOFTDEP(tvp)) {
1327 /*
1328 * Ensure that the entire newly allocated block is a
1329 * valid directory so that future growth within the
1330 * block does not have to ensure that the block is
1331 * written before the inode.
1332 */
1333 blkoff = dirblksiz;
1334 while (blkoff < bp->b_bcount) {
1335 ((struct direct *)
1336 (bp->b_data + blkoff))->d_reclen = dirblksiz;
1337 blkoff += dirblksiz;
1338 }
1339 }
1340 /*
1341 * Directory set up, now install it's entry in the parent directory.
1342 *
1343 * If we are not doing soft dependencies, then we must write out the
1344 * buffer containing the new directory body before entering the new
1345 * name in the parent. If we are doing soft dependencies, then the
1346 * buffer containing the new directory body will be passed to and
1347 * released in the soft dependency code after the code has attached
1348 * an appropriate ordering dependency to the buffer which ensures that
1349 * the buffer is written before the new name is written in the parent.
1350 */
1351 if (!DOINGSOFTDEP(tvp) && ((error = VOP_BWRITE(bp)) != 0))
1352 goto bad;
1353 if ((error = VOP_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0) {
1354 if (DOINGSOFTDEP(tvp))
1355 (void)VOP_BWRITE(bp);
1356 goto bad;
1357 }
1358 ufs_makedirentry(ip, cnp, &newdir);
1359 error = ufs_direnter(dvp, tvp, &newdir, cnp, bp);
1360 bad:
1361 if (error == 0) {
1362 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1363 *ap->a_vpp = tvp;
1364 } else {
1365 dp->i_ffs_effnlink--;
1366 dp->i_nlink--;
1367 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1368 dp->i_flag |= IN_CHANGE;
1369 if (DOINGSOFTDEP(dvp))
1370 softdep_change_linkcnt(dp);
1371 /*
1372 * No need to do an explicit VOP_TRUNCATE here, vrele will
1373 * do this for us because we set the link count to 0.
1374 */
1375 ip->i_ffs_effnlink = 0;
1376 ip->i_nlink = 0;
1377 DIP_ASSIGN(ip, nlink, 0);
1378 ip->i_flag |= IN_CHANGE;
1379 #ifdef LFS
1380 /* If IN_ADIROP, account for it */
1381 lfs_unmark_vnode(tvp);
1382 #endif
1383 if (DOINGSOFTDEP(tvp))
1384 softdep_change_linkcnt(ip);
1385 vput(tvp);
1386 }
1387 out:
1388 PNBUF_PUT(cnp->cn_pnbuf);
1389 vput(dvp);
1390 return (error);
1391 }
1392
1393 /*
1394 * Rmdir system call.
1395 */
1396 int
1397 ufs_rmdir(void *v)
1398 {
1399 struct vop_rmdir_args /* {
1400 struct vnode *a_dvp;
1401 struct vnode *a_vp;
1402 struct componentname *a_cnp;
1403 } */ *ap = v;
1404 struct vnode *vp, *dvp;
1405 struct componentname *cnp;
1406 struct inode *ip, *dp;
1407 int error;
1408
1409 vp = ap->a_vp;
1410 dvp = ap->a_dvp;
1411 cnp = ap->a_cnp;
1412 ip = VTOI(vp);
1413 dp = VTOI(dvp);
1414 /*
1415 * No rmdir "." or of mounted directories please.
1416 */
1417 if (dp == ip || vp->v_mountedhere != NULL) {
1418 vrele(dvp);
1419 if (vp->v_mountedhere != NULL)
1420 VOP_UNLOCK(dvp, 0);
1421 vput(vp);
1422 return (EINVAL);
1423 }
1424 /*
1425 * Do not remove a directory that is in the process of being renamed.
1426 * Verify that the directory is empty (and valid). (Rmdir ".." won't
1427 * be valid since ".." will contain a reference to the current
1428 * directory and thus be non-empty.)
1429 */
1430 error = 0;
1431 if (ip->i_flag & IN_RENAME) {
1432 error = EINVAL;
1433 goto out;
1434 }
1435 if (ip->i_ffs_effnlink != 2 ||
1436 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1437 error = ENOTEMPTY;
1438 goto out;
1439 }
1440 if ((dp->i_flags & APPEND) ||
1441 (ip->i_flags & (IMMUTABLE | APPEND))) {
1442 error = EPERM;
1443 goto out;
1444 }
1445 /*
1446 * Delete reference to directory before purging
1447 * inode. If we crash in between, the directory
1448 * will be reattached to lost+found,
1449 */
1450 if (DOINGSOFTDEP(vp)) {
1451 dp->i_ffs_effnlink--;
1452 ip->i_ffs_effnlink--;
1453 softdep_change_linkcnt(dp);
1454 softdep_change_linkcnt(ip);
1455 }
1456 error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
1457 if (error) {
1458 if (DOINGSOFTDEP(vp)) {
1459 dp->i_ffs_effnlink++;
1460 ip->i_ffs_effnlink++;
1461 softdep_change_linkcnt(dp);
1462 softdep_change_linkcnt(ip);
1463 }
1464 goto out;
1465 }
1466 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1467 cache_purge(dvp);
1468 /*
1469 * Truncate inode. The only stuff left in the directory is "." and
1470 * "..". The "." reference is inconsequential since we're quashing
1471 * it. The soft dependency code will arrange to do these operations
1472 * after the parent directory entry has been deleted on disk, so
1473 * when running with that code we avoid doing them now.
1474 */
1475 if (!DOINGSOFTDEP(vp)) {
1476 dp->i_nlink--;
1477 dp->i_ffs_effnlink--;
1478 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1479 dp->i_flag |= IN_CHANGE;
1480 ip->i_nlink--;
1481 ip->i_ffs_effnlink--;
1482 DIP_ASSIGN(ip, nlink, ip->i_nlink);
1483 ip->i_flag |= IN_CHANGE;
1484 error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
1485 cnp->cn_proc);
1486 }
1487 cache_purge(vp);
1488 out:
1489 VN_KNOTE(vp, NOTE_DELETE);
1490 vput(dvp);
1491 vput(vp);
1492 return (error);
1493 }
1494
1495 /*
1496 * symlink -- make a symbolic link
1497 */
1498 int
1499 ufs_symlink(void *v)
1500 {
1501 struct vop_symlink_args /* {
1502 struct vnode *a_dvp;
1503 struct vnode **a_vpp;
1504 struct componentname *a_cnp;
1505 struct vattr *a_vap;
1506 char *a_target;
1507 } */ *ap = v;
1508 struct vnode *vp, **vpp;
1509 struct inode *ip;
1510 int len, error;
1511
1512 vpp = ap->a_vpp;
1513 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
1514 vpp, ap->a_cnp);
1515 if (error)
1516 return (error);
1517 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1518 vp = *vpp;
1519 len = strlen(ap->a_target);
1520 if (len < vp->v_mount->mnt_maxsymlinklen) {
1521 ip = VTOI(vp);
1522 memcpy((char *)SHORTLINK(ip), ap->a_target, len);
1523 ip->i_size = len;
1524 DIP_ASSIGN(ip, size, len);
1525 uvm_vnp_setsize(vp, ip->i_size);
1526 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1527 } else
1528 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1529 UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, NULL,
1530 (struct proc *)0);
1531 if (error)
1532 vput(vp);
1533 return (error);
1534 }
1535
1536 /*
1537 * Vnode op for reading directories.
1538 *
1539 * The routine below assumes that the on-disk format of a directory
1540 * is the same as that defined by <sys/dirent.h>. If the on-disk
1541 * format changes, then it will be necessary to do a conversion
1542 * from the on-disk format that read returns to the format defined
1543 * by <sys/dirent.h>.
1544 */
1545 int
1546 ufs_readdir(void *v)
1547 {
1548 struct vop_readdir_args /* {
1549 struct vnode *a_vp;
1550 struct uio *a_uio;
1551 struct ucred *a_cred;
1552 int *a_eofflag;
1553 off_t **a_cookies;
1554 int *ncookies;
1555 } */ *ap = v;
1556 struct uio *uio;
1557 int error;
1558 size_t count, lost;
1559 off_t off;
1560 int dirblksiz = DIRBLKSIZ;
1561 if (UFS_MPISAPPLEUFS(ap->a_vp->v_mount)) {
1562 dirblksiz = APPLEUFS_DIRBLKSIZ;
1563 }
1564
1565 uio = ap->a_uio;
1566 off = uio->uio_offset;
1567 count = uio->uio_resid;
1568 /* Make sure we don't return partial entries. */
1569 count -= (uio->uio_offset + count) & (dirblksiz -1);
1570 if (count <= 0)
1571 return (EINVAL);
1572 lost = uio->uio_resid - count;
1573 uio->uio_resid = count;
1574 uio->uio_iov->iov_len = count;
1575 #if BYTE_ORDER == LITTLE_ENDIAN
1576 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0 &&
1577 UFS_MPNEEDSWAP(ap->a_vp->v_mount) == 0)
1578 #else
1579 if (UFS_MPNEEDSWAP(ap->a_vp->v_mount) == 0)
1580 #endif
1581 {
1582 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1583 } else {
1584 struct dirent *dp, *edp;
1585 struct uio auio;
1586 struct iovec aiov;
1587 caddr_t dirbuf;
1588 int readcnt;
1589 u_char tmp;
1590
1591 auio = *uio;
1592 auio.uio_iov = &aiov;
1593 auio.uio_iovcnt = 1;
1594 auio.uio_segflg = UIO_SYSSPACE;
1595 aiov.iov_len = count;
1596 MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK);
1597 aiov.iov_base = dirbuf;
1598 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
1599 if (error == 0) {
1600 readcnt = count - auio.uio_resid;
1601 edp = (struct dirent *)&dirbuf[readcnt];
1602 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1603 #if BYTE_ORDER == LITTLE_ENDIAN
1604 if (ap->a_vp->v_mount->mnt_maxsymlinklen <= 0 &&
1605 UFS_MPNEEDSWAP(ap->a_vp->v_mount) == 0)
1606 #else
1607 if (ap->a_vp->v_mount->mnt_maxsymlinklen <= 0 &&
1608 UFS_MPNEEDSWAP(ap->a_vp->v_mount) != 0)
1609 #endif
1610 {
1611 tmp = dp->d_namlen;
1612 dp->d_namlen = dp->d_type;
1613 dp->d_type = tmp;
1614 }
1615 dp->d_fileno = ufs_rw32(dp->d_fileno,
1616 UFS_MPNEEDSWAP(ap->a_vp->v_mount));
1617 dp->d_reclen = ufs_rw16(dp->d_reclen,
1618 UFS_MPNEEDSWAP(ap->a_vp->v_mount));
1619 if (dp->d_reclen > 0) {
1620 dp = (struct dirent *)
1621 ((char *)dp + dp->d_reclen);
1622 } else {
1623 error = EIO;
1624 break;
1625 }
1626 }
1627 if (dp >= edp)
1628 error = uiomove(dirbuf, readcnt, uio);
1629 }
1630 FREE(dirbuf, M_TEMP);
1631 }
1632 if (!error && ap->a_ncookies) {
1633 struct dirent *dp, *dpstart;
1634 off_t *cookies, offstart;
1635 int ncookies;
1636
1637 /*
1638 * Only the NFS server and emulations use cookies, and they
1639 * load the directory block into system space, so we can
1640 * just look at it directly.
1641 */
1642 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1643 panic("ufs_readdir: lost in space");
1644 dpstart = (struct dirent *)
1645 ((caddr_t)uio->uio_iov->iov_base - (uio->uio_offset - off));
1646 offstart = off;
1647 for (dp = dpstart, ncookies = 0; off < uio->uio_offset; ) {
1648 if (dp->d_reclen == 0)
1649 break;
1650 off += dp->d_reclen;
1651 ncookies++;
1652 dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
1653 }
1654 lost += uio->uio_offset - off;
1655 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
1656 uio->uio_offset = off;
1657 *ap->a_ncookies = ncookies;
1658 *ap->a_cookies = cookies;
1659 for (off = offstart, dp = dpstart; off < uio->uio_offset; ) {
1660 off += dp->d_reclen;
1661 *(cookies++) = off;
1662 dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
1663 }
1664 }
1665 uio->uio_resid += lost;
1666 *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
1667 return (error);
1668 }
1669
1670 /*
1671 * Return target name of a symbolic link
1672 */
1673 int
1674 ufs_readlink(void *v)
1675 {
1676 struct vop_readlink_args /* {
1677 struct vnode *a_vp;
1678 struct uio *a_uio;
1679 struct ucred *a_cred;
1680 } */ *ap = v;
1681 struct vnode *vp;
1682 struct inode *ip;
1683 int isize;
1684
1685 vp = ap->a_vp;
1686 ip = VTOI(vp);
1687 isize = ip->i_size;
1688 if (isize < vp->v_mount->mnt_maxsymlinklen ||
1689 (vp->v_mount->mnt_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) {
1690 uiomove((char *)SHORTLINK(ip), isize, ap->a_uio);
1691 return (0);
1692 }
1693 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1694 }
1695
1696 /*
1697 * Calculate the logical to physical mapping if not done already,
1698 * then call the device strategy routine.
1699 */
1700 int
1701 ufs_strategy(void *v)
1702 {
1703 struct vop_strategy_args /* {
1704 struct vnode *a_vp;
1705 struct buf *a_bp;
1706 } */ *ap = v;
1707 struct buf *bp;
1708 struct vnode *vp;
1709 struct inode *ip;
1710 int error;
1711
1712 bp = ap->a_bp;
1713 vp = ap->a_vp;
1714 ip = VTOI(vp);
1715 if (vp->v_type == VBLK || vp->v_type == VCHR)
1716 panic("ufs_strategy: spec");
1717 KASSERT(bp->b_bcount != 0);
1718 if (bp->b_blkno == bp->b_lblkno) {
1719 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno,
1720 NULL);
1721 if (error) {
1722 bp->b_error = error;
1723 bp->b_flags |= B_ERROR;
1724 biodone(bp);
1725 return (error);
1726 }
1727 if (bp->b_blkno == -1) /* no valid data */
1728 clrbuf(bp);
1729 }
1730 if (bp->b_blkno < 0) { /* block is not on disk */
1731 biodone(bp);
1732 return (0);
1733 }
1734 vp = ip->i_devvp;
1735 return (VOP_STRATEGY(vp, bp));
1736 }
1737
1738 /*
1739 * Print out the contents of an inode.
1740 */
1741 int
1742 ufs_print(void *v)
1743 {
1744 struct vop_print_args /* {
1745 struct vnode *a_vp;
1746 } */ *ap = v;
1747 struct vnode *vp;
1748 struct inode *ip;
1749
1750 vp = ap->a_vp;
1751 ip = VTOI(vp);
1752 printf("tag VT_UFS, ino %d, on dev %d, %d", ip->i_number,
1753 major(ip->i_dev), minor(ip->i_dev));
1754 printf(" flags 0x%x, effnlink %d, nlink %d\n",
1755 ip->i_flag, ip->i_ffs_effnlink, ip->i_nlink);
1756 printf("\tmode 0%o, owner %d, group %d, size %qd",
1757 ip->i_mode, ip->i_uid, ip->i_gid,
1758 (long long)ip->i_size);
1759 if (vp->v_type == VFIFO)
1760 fifo_printinfo(vp);
1761 lockmgr_printinfo(&vp->v_lock);
1762 printf("\n");
1763 return (0);
1764 }
1765
1766 /*
1767 * Read wrapper for special devices.
1768 */
1769 int
1770 ufsspec_read(void *v)
1771 {
1772 struct vop_read_args /* {
1773 struct vnode *a_vp;
1774 struct uio *a_uio;
1775 int a_ioflag;
1776 struct ucred *a_cred;
1777 } */ *ap = v;
1778
1779 /*
1780 * Set access flag.
1781 */
1782 if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
1783 VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1784 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
1785 }
1786
1787 /*
1788 * Write wrapper for special devices.
1789 */
1790 int
1791 ufsspec_write(void *v)
1792 {
1793 struct vop_write_args /* {
1794 struct vnode *a_vp;
1795 struct uio *a_uio;
1796 int a_ioflag;
1797 struct ucred *a_cred;
1798 } */ *ap = v;
1799
1800 /*
1801 * Set update and change flags.
1802 */
1803 if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
1804 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
1805 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
1806 }
1807
1808 /*
1809 * Close wrapper for special devices.
1810 *
1811 * Update the times on the inode then do device close.
1812 */
1813 int
1814 ufsspec_close(void *v)
1815 {
1816 struct vop_close_args /* {
1817 struct vnode *a_vp;
1818 int a_fflag;
1819 struct ucred *a_cred;
1820 struct proc *a_p;
1821 } */ *ap = v;
1822 struct vnode *vp;
1823 struct inode *ip;
1824 struct timespec ts;
1825
1826 vp = ap->a_vp;
1827 ip = VTOI(vp);
1828 simple_lock(&vp->v_interlock);
1829 if (vp->v_usecount > 1) {
1830 TIMEVAL_TO_TIMESPEC(&time, &ts);
1831 ITIMES(ip, &ts, &ts, &ts);
1832 }
1833 simple_unlock(&vp->v_interlock);
1834 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
1835 }
1836
1837 /*
1838 * Read wrapper for fifo's
1839 */
1840 int
1841 ufsfifo_read(void *v)
1842 {
1843 struct vop_read_args /* {
1844 struct vnode *a_vp;
1845 struct uio *a_uio;
1846 int a_ioflag;
1847 struct ucred *a_cred;
1848 } */ *ap = v;
1849
1850 /*
1851 * Set access flag.
1852 */
1853 VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1854 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
1855 }
1856
1857 /*
1858 * Write wrapper for fifo's.
1859 */
1860 int
1861 ufsfifo_write(void *v)
1862 {
1863 struct vop_write_args /* {
1864 struct vnode *a_vp;
1865 struct uio *a_uio;
1866 int a_ioflag;
1867 struct ucred *a_cred;
1868 } */ *ap = v;
1869
1870 /*
1871 * Set update and change flags.
1872 */
1873 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
1874 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
1875 }
1876
1877 /*
1878 * Close wrapper for fifo's.
1879 *
1880 * Update the times on the inode then do device close.
1881 */
1882 int
1883 ufsfifo_close(void *v)
1884 {
1885 struct vop_close_args /* {
1886 struct vnode *a_vp;
1887 int a_fflag;
1888 struct ucred *a_cred;
1889 struct proc *a_p;
1890 } */ *ap = v;
1891 struct vnode *vp;
1892 struct inode *ip;
1893 struct timespec ts;
1894
1895 vp = ap->a_vp;
1896 ip = VTOI(vp);
1897 simple_lock(&vp->v_interlock);
1898 if (ap->a_vp->v_usecount > 1) {
1899 TIMEVAL_TO_TIMESPEC(&time, &ts);
1900 ITIMES(ip, &ts, &ts, &ts);
1901 }
1902 simple_unlock(&vp->v_interlock);
1903 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
1904 }
1905
1906 /*
1907 * Return POSIX pathconf information applicable to ufs filesystems.
1908 */
1909 int
1910 ufs_pathconf(void *v)
1911 {
1912 struct vop_pathconf_args /* {
1913 struct vnode *a_vp;
1914 int a_name;
1915 register_t *a_retval;
1916 } */ *ap = v;
1917
1918 switch (ap->a_name) {
1919 case _PC_LINK_MAX:
1920 *ap->a_retval = LINK_MAX;
1921 return (0);
1922 case _PC_NAME_MAX:
1923 *ap->a_retval = NAME_MAX;
1924 return (0);
1925 case _PC_PATH_MAX:
1926 *ap->a_retval = PATH_MAX;
1927 return (0);
1928 case _PC_PIPE_BUF:
1929 *ap->a_retval = PIPE_BUF;
1930 return (0);
1931 case _PC_CHOWN_RESTRICTED:
1932 *ap->a_retval = 1;
1933 return (0);
1934 case _PC_NO_TRUNC:
1935 *ap->a_retval = 1;
1936 return (0);
1937 case _PC_SYNC_IO:
1938 *ap->a_retval = 1;
1939 return (0);
1940 case _PC_FILESIZEBITS:
1941 *ap->a_retval = 42;
1942 return (0);
1943 default:
1944 return (EINVAL);
1945 }
1946 /* NOTREACHED */
1947 }
1948
1949 /*
1950 * Advisory record locking support
1951 */
1952 int
1953 ufs_advlock(void *v)
1954 {
1955 struct vop_advlock_args /* {
1956 struct vnode *a_vp;
1957 caddr_t a_id;
1958 int a_op;
1959 struct flock *a_fl;
1960 int a_flags;
1961 } */ *ap = v;
1962 struct inode *ip;
1963
1964 ip = VTOI(ap->a_vp);
1965 return lf_advlock(ap, &ip->i_lockf, ip->i_size);
1966 }
1967
1968 /*
1969 * Initialize the vnode associated with a new inode, handle aliased
1970 * vnodes.
1971 */
1972 void
1973 ufs_vinit(struct mount *mntp, int (**specops)(void *), int (**fifoops)(void *),
1974 struct vnode **vpp)
1975 {
1976 struct inode *ip;
1977 struct vnode *vp, *nvp;
1978 dev_t rdev;
1979
1980 vp = *vpp;
1981 ip = VTOI(vp);
1982 switch(vp->v_type = IFTOVT(ip->i_mode)) {
1983 case VCHR:
1984 case VBLK:
1985 vp->v_op = specops;
1986 if (ip->i_ump->um_fstype == UFS1)
1987 rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
1988 UFS_MPNEEDSWAP(vp->v_mount));
1989 else
1990 rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
1991 UFS_MPNEEDSWAP(vp->v_mount));
1992 if ((nvp = checkalias(vp, rdev, mntp)) != NULL) {
1993 /*
1994 * Discard unneeded vnode, but save its inode.
1995 */
1996 nvp->v_data = vp->v_data;
1997 vp->v_data = NULL;
1998 /* XXX spec_vnodeops has no locking, do it explicitly */
1999 VOP_UNLOCK(vp, 0);
2000 vp->v_op = spec_vnodeop_p;
2001 vrele(vp);
2002 vgone(vp);
2003 lockmgr(&nvp->v_lock, LK_EXCLUSIVE, &nvp->v_interlock);
2004 /*
2005 * Reinitialize aliased inode.
2006 */
2007 vp = nvp;
2008 ip->i_vnode = vp;
2009 }
2010 break;
2011 case VFIFO:
2012 vp->v_op = fifoops;
2013 break;
2014 case VNON:
2015 case VBAD:
2016 case VSOCK:
2017 case VLNK:
2018 case VDIR:
2019 case VREG:
2020 break;
2021 }
2022 if (ip->i_number == ROOTINO)
2023 vp->v_flag |= VROOT;
2024 /*
2025 * Initialize modrev times
2026 */
2027 ip->i_modrev = (uint64_t)(uint)mono_time.tv_sec << 32
2028 | mono_time.tv_usec * 4294u;
2029 *vpp = vp;
2030 }
2031
2032 /*
2033 * Allocate a new inode.
2034 */
2035 int
2036 ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
2037 struct componentname *cnp)
2038 {
2039 struct inode *ip, *pdir;
2040 struct direct newdir;
2041 struct vnode *tvp;
2042 int error;
2043
2044 pdir = VTOI(dvp);
2045 #ifdef DIAGNOSTIC
2046 if ((cnp->cn_flags & HASBUF) == 0)
2047 panic("ufs_makeinode: no name");
2048 #endif
2049 *vpp = NULL;
2050 if ((mode & IFMT) == 0)
2051 mode |= IFREG;
2052
2053 if ((error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp)) != 0) {
2054 PNBUF_PUT(cnp->cn_pnbuf);
2055 vput(dvp);
2056 return (error);
2057 }
2058 ip = VTOI(tvp);
2059 ip->i_gid = pdir->i_gid;
2060 DIP_ASSIGN(ip, gid, ip->i_gid);
2061 ip->i_uid = cnp->cn_cred->cr_uid;
2062 DIP_ASSIGN(ip, uid, ip->i_uid);
2063 #ifdef QUOTA
2064 if ((error = getinoquota(ip)) ||
2065 (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
2066 VOP_VFREE(tvp, ip->i_number, mode);
2067 vput(tvp);
2068 PNBUF_PUT(cnp->cn_pnbuf);
2069 vput(dvp);
2070 return (error);
2071 }
2072 #endif
2073 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2074 ip->i_mode = mode;
2075 DIP_ASSIGN(ip, mode, mode);
2076 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
2077 ip->i_ffs_effnlink = 1;
2078 ip->i_nlink = 1;
2079 DIP_ASSIGN(ip, nlink, 1);
2080 if (DOINGSOFTDEP(tvp))
2081 softdep_change_linkcnt(ip);
2082 if ((ip->i_mode & ISGID) &&
2083 !groupmember(ip->i_gid, cnp->cn_cred) &&
2084 suser(cnp->cn_cred, NULL)) {
2085 ip->i_mode &= ~ISGID;
2086 DIP_ASSIGN(ip, mode, ip->i_mode);
2087 }
2088
2089 if (cnp->cn_flags & ISWHITEOUT) {
2090 ip->i_flags |= UF_OPAQUE;
2091 DIP_ASSIGN(ip, flags, ip->i_flags);
2092 }
2093
2094 /*
2095 * Make sure inode goes to disk before directory entry.
2096 */
2097 if ((error = VOP_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0)
2098 goto bad;
2099 ufs_makedirentry(ip, cnp, &newdir);
2100 if ((error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL)) != 0)
2101 goto bad;
2102 if ((cnp->cn_flags & SAVESTART) == 0)
2103 PNBUF_PUT(cnp->cn_pnbuf);
2104 vput(dvp);
2105 *vpp = tvp;
2106 return (0);
2107
2108 bad:
2109 /*
2110 * Write error occurred trying to update the inode
2111 * or the directory so must deallocate the inode.
2112 */
2113 ip->i_ffs_effnlink = 0;
2114 ip->i_nlink = 0;
2115 DIP_ASSIGN(ip, nlink, 0);
2116 ip->i_flag |= IN_CHANGE;
2117 #ifdef LFS
2118 /* If IN_ADIROP, account for it */
2119 lfs_unmark_vnode(tvp);
2120 #endif
2121 if (DOINGSOFTDEP(tvp))
2122 softdep_change_linkcnt(ip);
2123 tvp->v_type = VNON; /* explodes later if VBLK */
2124 vput(tvp);
2125 PNBUF_PUT(cnp->cn_pnbuf);
2126 vput(dvp);
2127 return (error);
2128 }
2129
2130 /*
2131 * Allocate len bytes at offset off.
2132 */
2133 int
2134 ufs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
2135 struct ucred *cred)
2136 {
2137 struct inode *ip = VTOI(vp);
2138 int error, delta, bshift, bsize;
2139 UVMHIST_FUNC("ufs_gop_alloc"); UVMHIST_CALLED(ubchist);
2140
2141 error = 0;
2142 bshift = vp->v_mount->mnt_fs_bshift;
2143 bsize = 1 << bshift;
2144
2145 delta = off & (bsize - 1);
2146 off -= delta;
2147 len += delta;
2148
2149 while (len > 0) {
2150 bsize = MIN(bsize, len);
2151
2152 error = VOP_BALLOC(vp, off, bsize, cred, flags, NULL);
2153 if (error) {
2154 goto out;
2155 }
2156
2157 /*
2158 * increase file size now, VOP_BALLOC() requires that
2159 * EOF be up-to-date before each call.
2160 */
2161
2162 if (ip->i_size < off + bsize) {
2163 UVMHIST_LOG(ubchist, "vp %p old 0x%x new 0x%x",
2164 vp, ip->i_size, off + bsize, 0);
2165 ip->i_size = off + bsize;
2166 DIP_ASSIGN(ip, size, ip->i_size);
2167 }
2168
2169 off += bsize;
2170 len -= bsize;
2171 }
2172
2173 out:
2174 return error;
2175 }
Cache object: b759f96c161c6c2392927a1a6370efb6
|