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