checkpoint, but not because it's working
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
CommitLineData
da7c5cc6 1/*
0b4d6502 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
7188ac27 3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
d5075120 7 * @(#)lfs_vnops.c 7.67 (Berkeley) %G%
da7c5cc6 8 */
6459ebe0 9
94368568
JB
10#include "param.h"
11#include "systm.h"
c6f5111d
MK
12#include "namei.h"
13#include "resourcevar.h"
94368568
JB
14#include "kernel.h"
15#include "file.h"
16#include "stat.h"
94368568
JB
17#include "buf.h"
18#include "proc.h"
7188ac27 19#include "conf.h"
94368568 20#include "mount.h"
7188ac27 21#include "vnode.h"
0f93ba7b 22#include "specdev.h"
5b169cb7 23#include "fifo.h"
0b0bf936 24#include "malloc.h"
c6f5111d 25
0b4d6502
KB
26#include "../ufs/lockf.h"
27#include "../ufs/quota.h"
28#include "../ufs/inode.h"
29#include "../ufs/dir.h"
a8c062c5 30#include "lfs.h"
0b4d6502 31#include "lfs_extern.h"
a8c062c5
KB
32
33static int chmod1 __P((struct vnode *, int, struct proc *));
34static int chown1 __P((struct vnode *, uid_t, gid_t, struct proc *));
35static int maknode __P((int, struct nameidata *, struct inode **));
3e78e260 36
4f083fd7 37/*
7188ac27 38 * Create a regular file
4f083fd7 39 */
a8c062c5 40lfs_create(ndp, vap, p)
7188ac27
KM
41 struct nameidata *ndp;
42 struct vattr *vap;
5b169cb7 43 struct proc *p;
3e78e260 44{
7188ac27
KM
45 struct inode *ip;
46 int error;
3e78e260 47
0b4d6502 48printf("lfs_create\n");
7188ac27
KM
49 if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
50 return (error);
51 ndp->ni_vp = ITOV(ip);
52 return (0);
3e78e260
BJ
53}
54
4f083fd7 55/*
7188ac27 56 * Mknod vnode call
4f083fd7 57 */
7188ac27 58/* ARGSUSED */
a8c062c5 59lfs_mknod(ndp, vap, cred, p)
7188ac27
KM
60 struct nameidata *ndp;
61 struct ucred *cred;
62 struct vattr *vap;
5b169cb7 63 struct proc *p;
3e78e260 64{
f09fe6d3 65 register struct vnode *vp;
7188ac27
KM
66 struct inode *ip;
67 int error;
3e78e260 68
0b4d6502 69printf("lfs_mknod\n");
7188ac27
KM
70 if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
71 return (error);
d1c43d7f
KM
72 ip->i_flag |= IACC|IUPD|ICHG;
73 if (vap->va_rdev != VNOVAL) {
7188ac27
KM
74 /*
75 * Want to be able to use this to make badblock
76 * inodes, so don't truncate the dev number.
77 */
b373e060 78 ip->i_rdev = vap->va_rdev;
7188ac27 79 }
7188ac27
KM
80 /*
81 * Remove inode so that it will be reloaded by iget and
82 * checked to see if it is an alias of an existing entry
83 * in the inode cache.
84 */
d1c43d7f
KM
85 vp = ITOV(ip);
86 vput(vp);
f09fe6d3
KM
87 vp->v_type = VNON;
88 vgone(vp);
7188ac27 89 return (0);
3e78e260
BJ
90}
91
7188ac27 92/* ARGSUSED */
a8c062c5 93lfs_getattr(vp, vap, cred, p)
7188ac27
KM
94 struct vnode *vp;
95 register struct vattr *vap;
96 struct ucred *cred;
5b169cb7 97 struct proc *p;
3e78e260 98{
7188ac27 99 register struct inode *ip = VTOI(vp);
3e78e260 100
0b4d6502 101printf("lfs_getattr\n");
d5075120 102 ITIMES(ip, &time, &time); /* LFS */
3e78e260 103 /*
7188ac27 104 * Copy from inode table
3e78e260 105 */
7188ac27
KM
106 vap->va_fsid = ip->i_dev;
107 vap->va_fileid = ip->i_number;
108 vap->va_mode = ip->i_mode & ~IFMT;
109 vap->va_nlink = ip->i_nlink;
110 vap->va_uid = ip->i_uid;
111 vap->va_gid = ip->i_gid;
112 vap->va_rdev = (dev_t)ip->i_rdev;
4b61628b
KM
113#ifdef tahoe
114 vap->va_size = ip->i_size;
115 vap->va_size_rsv = 0;
116#else
8fae943a 117 vap->va_qsize = ip->i_din.di_qsize;
4b61628b 118#endif
7188ac27 119 vap->va_atime.tv_sec = ip->i_atime;
6ef53d70 120 vap->va_atime.tv_usec = 0;
7188ac27 121 vap->va_mtime.tv_sec = ip->i_mtime;
6ef53d70 122 vap->va_mtime.tv_usec = 0;
7188ac27 123 vap->va_ctime.tv_sec = ip->i_ctime;
6ef53d70 124 vap->va_ctime.tv_usec = 0;
d07fc92a
KM
125 vap->va_flags = ip->i_flags;
126 vap->va_gen = ip->i_gen;
7188ac27
KM
127 /* this doesn't belong here */
128 if (vp->v_type == VBLK)
129 vap->va_blocksize = BLKDEV_IOSIZE;
130 else if (vp->v_type == VCHR)
131 vap->va_blocksize = MAXBSIZE;
8eee8525 132 else
0b4d6502 133 vap->va_blocksize = ip->i_lfs->lfs_bsize; /* LFS */
a61a68d6 134 vap->va_bytes = dbtob(ip->i_blocks);
8fae943a 135 vap->va_bytes_rsv = 0;
7188ac27
KM
136 vap->va_type = vp->v_type;
137 return (0);
3e78e260
BJ
138}
139
140/*
7188ac27 141 * Set attribute vnode op. called from several syscalls
3e78e260 142 */
a8c062c5 143lfs_setattr(vp, vap, cred, p)
7188ac27
KM
144 register struct vnode *vp;
145 register struct vattr *vap;
146 register struct ucred *cred;
5b169cb7 147 struct proc *p;
3e78e260 148{
7188ac27
KM
149 register struct inode *ip = VTOI(vp);
150 int error = 0;
b4d1aee9 151
0b4d6502 152printf("lfs_setattr\n");
7188ac27 153 /*
0b4d6502 154 * Check for unsettable attributes.
7188ac27
KM
155 */
156 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
157 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
158 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
d07fc92a 159 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
7188ac27 160 return (EINVAL);
b4d1aee9 161 }
7188ac27
KM
162 /*
163 * Go through the fields and update iff not VNOVAL.
164 */
165 if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
c6f5111d 166 if (error = chown1(vp, vap->va_uid, vap->va_gid, p))
7188ac27
KM
167 return (error);
168 if (vap->va_size != VNOVAL) {
169 if (vp->v_type == VDIR)
0b4d6502
KB
170 return (EISDIR); /* LFS */
171 if (error = lfs_itrunc(ip, vap->va_size, 0)) /* XXX IO_SYNC? */
7188ac27 172 return (error);
3e78e260 173 }
7188ac27 174 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
de412887 175 if (cred->cr_uid != ip->i_uid &&
c6f5111d 176 (error = suser(cred, &p->p_acflag)))
de412887 177 return (error);
7188ac27
KM
178 if (vap->va_atime.tv_sec != VNOVAL)
179 ip->i_flag |= IACC;
180 if (vap->va_mtime.tv_sec != VNOVAL)
181 ip->i_flag |= IUPD;
0b4d6502 182 ip->i_flag |= ICHG; /* LFS */
d5075120 183 ITIMES(ip, &vap->va_atime, &vap->va_mtime); /* LFS */
5485e062 184 }
7188ac27 185 if (vap->va_mode != (u_short)VNOVAL)
c6f5111d 186 error = chmod1(vp, (int)vap->va_mode, p);
d07fc92a
KM
187 if (vap->va_flags != VNOVAL) {
188 if (cred->cr_uid != ip->i_uid &&
c6f5111d 189 (error = suser(cred, &p->p_acflag)))
d07fc92a
KM
190 return (error);
191 if (cred->cr_uid == 0) {
192 ip->i_flags = vap->va_flags;
193 } else {
194 ip->i_flags &= 0xffff0000;
195 ip->i_flags |= (vap->va_flags & 0xffff);
196 }
197 ip->i_flag |= ICHG;
198 }
7188ac27 199 return (error);
528f664c
SL
200}
201
b373e060
KM
202/*
203 * Vnode op for reading.
204 */
205/* ARGSUSED */
a8c062c5 206lfs_read(vp, uio, ioflag, cred)
b373e060
KM
207 struct vnode *vp;
208 register struct uio *uio;
209 int ioflag;
210 struct ucred *cred;
211{
212 register struct inode *ip = VTOI(vp);
0b4d6502 213 register LFS *fs; /* LFS */
b373e060
KM
214 struct buf *bp;
215 daddr_t lbn, bn, rablock;
20aa076b 216 int size, diff, error = 0;
b373e060
KM
217 long n, on, type;
218
0b4d6502 219printf("lfs_read: ino %d\n", ip->i_number);
5b169cb7 220#ifdef DIAGNOSTIC
b373e060
KM
221 if (uio->uio_rw != UIO_READ)
222 panic("ufs_read mode");
223 type = ip->i_mode & IFMT;
224 if (type != IFDIR && type != IFREG && type != IFLNK)
225 panic("ufs_read type");
5b169cb7 226#endif
b373e060
KM
227 if (uio->uio_resid == 0)
228 return (0);
229 if (uio->uio_offset < 0)
230 return (EINVAL);
231 ip->i_flag |= IACC;
0b4d6502
KB
232
233 fs = ip->i_lfs; /* LFS */
b373e060
KM
234 do {
235 lbn = lblkno(fs, uio->uio_offset);
236 on = blkoff(fs, uio->uio_offset);
0b4d6502 237 n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
b373e060
KM
238 diff = ip->i_size - uio->uio_offset;
239 if (diff <= 0)
240 return (0);
241 if (diff < n)
242 n = diff;
0b4d6502 243 size = blksize(fs); /* LFS */
e16fa59e 244 rablock = lbn + 1;
20aa076b
KM
245 if (vp->v_lastr + 1 == lbn &&
246 lblktosize(fs, rablock) < ip->i_size)
247 error = breada(ITOV(ip), lbn, size, rablock,
0b4d6502 248 blksize(fs), NOCRED, &bp);
b373e060 249 else
e16fa59e 250 error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
de67eefc 251 vp->v_lastr = lbn;
b373e060
KM
252 n = MIN(n, size - bp->b_resid);
253 if (error) {
254 brelse(bp);
255 return (error);
256 }
257 error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
0b4d6502 258 if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size)
b373e060
KM
259 bp->b_flags |= B_AGE;
260 brelse(bp);
261 } while (error == 0 && uio->uio_resid > 0 && n != 0);
262 return (error);
263}
264
265/*
266 * Vnode op for writing.
267 */
a8c062c5 268lfs_write(vp, uio, ioflag, cred)
b373e060
KM
269 register struct vnode *vp;
270 struct uio *uio;
271 int ioflag;
272 struct ucred *cred;
273{
5b169cb7 274 struct proc *p = uio->uio_procp;
b373e060 275 register struct inode *ip = VTOI(vp);
d5075120 276 register LFS *fs; /* LFS */
b373e060
KM
277 struct buf *bp;
278 daddr_t lbn, bn;
279 u_long osize;
8986c97c
KM
280 int n, on, flags;
281 int size, resid, error = 0;
b373e060 282
0b4d6502 283printf("lfs_write ino %d\n", ip->i_number);
5b169cb7 284#ifdef DIAGNOSTIC
b373e060
KM
285 if (uio->uio_rw != UIO_WRITE)
286 panic("ufs_write mode");
5b169cb7 287#endif
b373e060
KM
288 switch (vp->v_type) {
289 case VREG:
290 if (ioflag & IO_APPEND)
291 uio->uio_offset = ip->i_size;
292 /* fall through */
293 case VLNK:
294 break;
295
296 case VDIR:
297 if ((ioflag & IO_SYNC) == 0)
298 panic("ufs_write nonsync dir write");
299 break;
300
301 default:
302 panic("ufs_write type");
303 }
304 if (uio->uio_offset < 0)
305 return (EINVAL);
306 if (uio->uio_resid == 0)
307 return (0);
308 /*
309 * Maybe this should be above the vnode op call, but so long as
310 * file servers have no limits, i don't think it matters
311 */
b326e282 312 if (vp->v_type == VREG && p &&
b373e060 313 uio->uio_offset + uio->uio_resid >
c6f5111d
MK
314 p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
315 psignal(p, SIGXFSZ);
b373e060
KM
316 return (EFBIG);
317 }
318 resid = uio->uio_resid;
319 osize = ip->i_size;
d5075120 320 fs = ip->i_lfs; /* LFS */
e16fa59e 321 flags = 0;
d5075120 322#ifdef NOTLFS
e16fa59e
KM
323 if (ioflag & IO_SYNC)
324 flags = B_SYNC;
d5075120 325#endif
b373e060
KM
326 do {
327 lbn = lblkno(fs, uio->uio_offset);
d5075120
KB
328 on = blkoff(fs, uio->uio_offset); /* LFS */
329 n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
330 if (n < fs->lfs_bsize) /* LFS */
e16fa59e 331 flags |= B_CLRBUF;
b373e060 332 else
d5075120
KB
333 flags &= ~B_CLRBUF; /* LFS */
334 if (error = bread(vp, lbn, fs->lfs_bsize, NOCRED, &bp))
b373e060 335 break;
e16fa59e 336 bn = bp->b_blkno;
8986c97c 337 if (uio->uio_offset + n > ip->i_size) {
b373e060 338 ip->i_size = uio->uio_offset + n;
8986c97c
KM
339 vnode_pager_setsize(vp, ip->i_size);
340 }
d5075120 341 size = blksize(fs);
8986c97c 342 (void) vnode_pager_uncache(vp);
b373e060 343 n = MIN(n, size - bp->b_resid);
b373e060 344 error = uiomove(bp->b_un.b_addr + on, n, uio);
d5075120 345#ifdef NOTLFS /* LFS */
b373e060
KM
346 if (ioflag & IO_SYNC)
347 (void) bwrite(bp);
348 else if (n + on == fs->fs_bsize) {
349 bp->b_flags |= B_AGE;
350 bawrite(bp);
351 } else
352 bdwrite(bp);
d5075120
KB
353#else
354 /*
355 * Update segment usage information; call segment
356 * writer if necessary.
357 */
358 lfs_bwrite(bp);
359#endif
b373e060
KM
360 ip->i_flag |= IUPD|ICHG;
361 if (cred->cr_uid != 0)
362 ip->i_mode &= ~(ISUID|ISGID);
363 } while (error == 0 && uio->uio_resid > 0 && n != 0);
364 if (error && (ioflag & IO_UNIT)) {
d5075120
KB
365#ifdef NOTLFS
366 /* This just doesn't work... */
0b4d6502 367 (void) lfs_itrunc(ip, osize, ioflag & IO_SYNC);
d5075120 368#endif
b373e060
KM
369 uio->uio_offset -= resid - uio->uio_resid;
370 uio->uio_resid = resid;
371 }
1c05ecaf 372 if (!error && (ioflag & IO_SYNC))
d5075120 373 ITIMES(ip, &time, &time); /* LFS */
b373e060
KM
374 return (error);
375}
376
4f083fd7 377/*
7188ac27 378 * Synch an open file.
4f083fd7 379 */
7188ac27 380/* ARGSUSED */
a8c062c5 381lfs_fsync(vp, fflags, cred, waitfor, p)
7188ac27
KM
382 struct vnode *vp;
383 int fflags;
384 struct ucred *cred;
86cdabf6 385 int waitfor;
5b169cb7 386 struct proc *p;
528f664c 387{
86cdabf6 388 struct inode *ip = VTOI(vp);
7188ac27 389
0b4d6502 390printf("lfs_sync: ino %d\n", ip->i_number);
5b169cb7 391 if (fflags & FWRITE)
7188ac27 392 ip->i_flag |= ICHG;
d5075120 393 ITIMES(ip, &time, &time); /* LFS */
0b4d6502 394 vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0); /* LFS */
d5075120 395 return (0);
7188ac27
KM
396}
397
398/*
399 * ufs remove
400 * Hard to avoid races here, especially
401 * in unlinking directories.
402 */
a8c062c5 403lfs_remove(ndp, p)
7188ac27 404 struct nameidata *ndp;
5b169cb7 405 struct proc *p;
7188ac27
KM
406{
407 register struct inode *ip, *dp;
408 int error;
409
0b4d6502 410printf("lfs_remove\n");
7188ac27
KM
411 ip = VTOI(ndp->ni_vp);
412 dp = VTOI(ndp->ni_dvp);
0b4d6502 413 error = lfs_dirremove(ndp); /* LFS */
7188ac27
KM
414 if (!error) {
415 ip->i_nlink--;
416 ip->i_flag |= ICHG;
528f664c 417 }
7188ac27
KM
418 if (dp == ip)
419 vrele(ITOV(ip));
420 else
421 iput(ip);
422 iput(dp);
423 return (error);
4f083fd7 424}
4f083fd7 425/*
7188ac27 426 * link vnode call
4f083fd7 427 */
a8c062c5 428lfs_link(vp, ndp, p)
7188ac27
KM
429 register struct vnode *vp;
430 register struct nameidata *ndp;
5b169cb7 431 struct proc *p;
4f083fd7 432{
7188ac27
KM
433 register struct inode *ip = VTOI(vp);
434 int error;
4f083fd7 435
0b4d6502 436printf("lfs_link\n");
655da945
KM
437#ifdef DIANOSTIC
438 if ((ndp->ni_nameiop & HASBUF) == 0)
439 panic("ufs_link: no name");
440#endif
441 if ((unsigned short)ip->i_nlink >= LINK_MAX) {
442 free(ndp->ni_pnbuf, M_NAMEI);
986aedaa 443 return (EMLINK);
655da945 444 }
7188ac27
KM
445 if (ndp->ni_dvp != vp)
446 ILOCK(ip);
7188ac27
KM
447 ip->i_nlink++;
448 ip->i_flag |= ICHG;
d5075120
KB
449 ITIMES(ip, &time, &time); /* LFS */
450 error = lfs_direnter(ip, ndp); /* LFS */
7188ac27
KM
451 if (ndp->ni_dvp != vp)
452 IUNLOCK(ip);
655da945 453 FREE(ndp->ni_pnbuf, M_NAMEI);
394d67a8 454 vput(ndp->ni_dvp);
7188ac27
KM
455 if (error) {
456 ip->i_nlink--;
82252d2b 457 ip->i_flag |= ICHG;
7188ac27
KM
458 }
459 return (error);
528f664c
SL
460}
461
4f083fd7
SL
462/*
463 * Rename system call.
464 * rename("foo", "bar");
465 * is essentially
466 * unlink("bar");
467 * link("foo", "bar");
468 * unlink("foo");
469 * but ``atomically''. Can't do full commit without saving state in the
470 * inode on disk which isn't feasible at this time. Best we can do is
471 * always guarantee the target exists.
472 *
473 * Basic algorithm is:
474 *
475 * 1) Bump link count on source while we're linking it to the
7188ac27 476 * target. This also ensure the inode won't be deleted out
68f21562
KM
477 * from underneath us while we work (it may be truncated by
478 * a concurrent `trunc' or `open' for creation).
4f083fd7
SL
479 * 2) Link source to destination. If destination already exists,
480 * delete it first.
68f21562
KM
481 * 3) Unlink source reference to inode if still around. If a
482 * directory was moved and the parent of the destination
4f083fd7
SL
483 * is different from the source, patch the ".." entry in the
484 * directory.
4f083fd7 485 */
a8c062c5 486lfs_rename(fndp, tndp, p)
7188ac27 487 register struct nameidata *fndp, *tndp;
5b169cb7 488 struct proc *p;
528f664c 489{
4f083fd7 490 register struct inode *ip, *xp, *dp;
68f21562
KM
491 struct dirtemplate dirbuf;
492 int doingdirectory = 0, oldparent = 0, newparent = 0;
a5390dce 493 int error = 0;
4f083fd7 494
0b4d6502 495printf("lfs_rename\n");
655da945
KM
496#ifdef DIANOSTIC
497 if ((tndp->ni_nameiop & HASBUF) == 0 ||
498 (fndp->ni_nameiop & HASBUF) == 0)
499 panic("ufs_rename: no name");
500#endif
7188ac27
KM
501 dp = VTOI(fndp->ni_dvp);
502 ip = VTOI(fndp->ni_vp);
655da945
KM
503 /*
504 * Check if just deleting a link name.
505 */
506 if (fndp->ni_vp == tndp->ni_vp) {
507 VOP_ABORTOP(tndp);
508 vput(tndp->ni_dvp);
509 vput(tndp->ni_vp);
510 vrele(fndp->ni_dvp);
511 if ((ip->i_mode&IFMT) == IFDIR) {
512 VOP_ABORTOP(fndp);
513 vrele(fndp->ni_vp);
514 return (EINVAL);
515 }
516 doingdirectory = 0;
517 goto unlinkit;
518 }
7188ac27 519 ILOCK(ip);
4f083fd7 520 if ((ip->i_mode&IFMT) == IFDIR) {
4f083fd7 521 /*
046f18d1 522 * Avoid ".", "..", and aliases of "." for obvious reasons.
4f083fd7 523 */
655da945
KM
524 if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
525 dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
66955caf
KM
526 VOP_ABORTOP(tndp);
527 vput(tndp->ni_dvp);
528 if (tndp->ni_vp)
529 vput(tndp->ni_vp);
530 VOP_ABORTOP(fndp);
531 vrele(fndp->ni_dvp);
532 vput(fndp->ni_vp);
7188ac27 533 return (EINVAL);
4f083fd7 534 }
68f21562 535 ip->i_flag |= IRENAME;
4f083fd7
SL
536 oldparent = dp->i_number;
537 doingdirectory++;
538 }
7188ac27 539 vrele(fndp->ni_dvp);
4f083fd7
SL
540
541 /*
542 * 1) Bump link count while we're moving stuff
543 * around. If we crash somewhere before
544 * completing our work, the link count
545 * may be wrong, but correctable.
546 */
547 ip->i_nlink++;
548 ip->i_flag |= ICHG;
d5075120 549 ITIMES(ip, &time, &time); /* LFS */
a388503d 550 IUNLOCK(ip);
4f083fd7
SL
551
552 /*
553 * When the target exists, both the directory
7188ac27 554 * and target vnodes are returned locked.
4f083fd7 555 */
7188ac27
KM
556 dp = VTOI(tndp->ni_dvp);
557 xp = NULL;
558 if (tndp->ni_vp)
559 xp = VTOI(tndp->ni_vp);
046f18d1
SL
560 /*
561 * If ".." must be changed (ie the directory gets a new
81552f0f
KM
562 * parent) then the source directory must not be in the
563 * directory heirarchy above the target, as this would
564 * orphan everything below the source directory. Also
565 * the user must have write permission in the source so
566 * as to be able to change "..". We must repeat the call
567 * to namei, as the parent directory is unlocked by the
568 * call to checkpath().
046f18d1 569 */
68f21562
KM
570 if (oldparent != dp->i_number)
571 newparent = dp->i_number;
572 if (doingdirectory && newparent) {
48c3b6e8 573 VOP_LOCK(fndp->ni_vp);
5b169cb7 574 error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred, p);
48c3b6e8
KM
575 VOP_UNLOCK(fndp->ni_vp);
576 if (error)
81552f0f 577 goto bad;
655da945 578 if (xp != NULL)
0b4d6502
KB
579 iput(xp); /* LFS */
580 if (error = lfs_checkpath(ip, dp, tndp->ni_cred))
655da945
KM
581 goto out;
582 if ((tndp->ni_nameiop & SAVESTART) == 0)
583 panic("ufs_rename: lost to startdir");
5e03b55d 584 p->p_spare[1]--;
655da945
KM
585 if (error = lookup(tndp, p))
586 goto out;
587 dp = VTOI(tndp->ni_dvp);
588 xp = NULL;
589 if (tndp->ni_vp)
590 xp = VTOI(tndp->ni_vp);
81552f0f 591 }
4f083fd7
SL
592 /*
593 * 2) If target doesn't exist, link the target
594 * to the source and unlink the source.
595 * Otherwise, rewrite the target directory
596 * entry to reference the source inode and
597 * expunge the original entry's existence.
598 */
4f083fd7 599 if (xp == NULL) {
7188ac27
KM
600 if (dp->i_dev != ip->i_dev)
601 panic("rename: EXDEV");
4f083fd7 602 /*
68f21562
KM
603 * Account for ".." in new directory.
604 * When source and destination have the same
605 * parent we don't fool with the link count.
4f083fd7 606 */
68f21562 607 if (doingdirectory && newparent) {
986aedaa
KM
608 if ((unsigned short)dp->i_nlink >= LINK_MAX) {
609 error = EMLINK;
610 goto bad;
611 }
4f083fd7 612 dp->i_nlink++;
0b4d6502 613 dp->i_flag |= ICHG; /* LFS */
d5075120 614 ITIMES(dp, &time, &time); /* LFS */
4f083fd7 615 }
0b4d6502 616 if (error = lfs_direnter(ip, tndp)) {
394d67a8
KM
617 if (doingdirectory && newparent) {
618 dp->i_nlink--;
0b4d6502 619 dp->i_flag |= ICHG; /* LFS */
d5075120 620 ITIMES(dp, &time, &time); /* LFS */
394d67a8
KM
621 }
622 goto bad;
623 }
4093ba31 624 iput(dp);
4f083fd7 625 } else {
7188ac27
KM
626 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
627 panic("rename: EXDEV");
e69c3c9c
SL
628 /*
629 * Short circuit rename(foo, foo).
630 */
631 if (xp->i_number == ip->i_number)
7188ac27 632 panic("rename: same file");
80cee150
JB
633 /*
634 * If the parent directory is "sticky", then the user must
635 * own the parent directory, or the destination of the rename,
636 * otherwise the destination may not be changed (except by
637 * root). This implements append-only directories.
638 */
7188ac27
KM
639 if ((dp->i_mode & ISVTX) && tndp->ni_cred->cr_uid != 0 &&
640 tndp->ni_cred->cr_uid != dp->i_uid &&
641 xp->i_uid != tndp->ni_cred->cr_uid) {
80cee150
JB
642 error = EPERM;
643 goto bad;
644 }
4f083fd7 645 /*
655da945
KM
646 * Target must be empty if a directory and have no links
647 * to it. Also, ensure source and target are compatible
648 * (both directories, or both not directories).
4f083fd7
SL
649 */
650 if ((xp->i_mode&IFMT) == IFDIR) {
7188ac27
KM
651 if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
652 xp->i_nlink > 2) {
a5390dce 653 error = ENOTEMPTY;
4f083fd7
SL
654 goto bad;
655 }
656 if (!doingdirectory) {
a5390dce 657 error = ENOTDIR;
4f083fd7
SL
658 goto bad;
659 }
7188ac27 660 cache_purge(ITOV(dp));
4f083fd7 661 } else if (doingdirectory) {
a5390dce 662 error = EISDIR;
4f083fd7
SL
663 goto bad;
664 }
7188ac27
KM
665 if (error = dirrewrite(dp, ip, tndp))
666 goto bad;
a62786b9
KM
667 /*
668 * If the target directory is in the same
669 * directory as the source directory,
670 * decrement the link count on the parent
671 * of the target directory.
672 */
673 if (doingdirectory && !newparent) {
674 dp->i_nlink--;
675 dp->i_flag |= ICHG;
676 }
7188ac27 677 vput(ITOV(dp));
4f083fd7 678 /*
a5390dce
SL
679 * Adjust the link count of the target to
680 * reflect the dirrewrite above. If this is
681 * a directory it is empty and there are
682 * no links to it, so we can squash the inode and
683 * any space associated with it. We disallowed
684 * renaming over top of a directory with links to
68f21562
KM
685 * it above, as the remaining link would point to
686 * a directory without "." or ".." entries.
4f083fd7 687 */
a5390dce 688 xp->i_nlink--;
4f083fd7 689 if (doingdirectory) {
0b4d6502 690 if (--xp->i_nlink != 0) /* LFS */
a5390dce 691 panic("rename: linked directory");
0b4d6502 692 error = lfs_itrunc(xp, (u_long)0, IO_SYNC);
a5390dce 693 }
4f083fd7 694 xp->i_flag |= ICHG;
88d931ba 695 iput(xp);
31db12cb 696 xp = NULL;
4f083fd7
SL
697 }
698
699 /*
700 * 3) Unlink the source.
701 */
655da945
KM
702unlinkit:
703 fndp->ni_nameiop &= ~MODMASK;
704 fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
705 if ((fndp->ni_nameiop & SAVESTART) == 0)
706 panic("ufs_rename: lost from startdir");
5e03b55d 707 p->p_spare[1]--;
655da945 708 (void) lookup(fndp, p);
7188ac27
KM
709 if (fndp->ni_vp != NULL) {
710 xp = VTOI(fndp->ni_vp);
711 dp = VTOI(fndp->ni_dvp);
712 } else {
d9d75b8f
KM
713 /*
714 * From name has disappeared.
715 */
716 if (doingdirectory)
717 panic("rename: lost dir entry");
718 vrele(ITOV(ip));
719 return (0);
7188ac27 720 }
4f083fd7 721 /*
7188ac27 722 * Ensure that the directory entry still exists and has not
68f21562
KM
723 * changed while the new name has been entered. If the source is
724 * a file then the entry may have been unlinked or renamed. In
725 * either case there is no further work to be done. If the source
726 * is a directory then it cannot have been rmdir'ed; its link
727 * count of three would cause a rmdir to fail with ENOTEMPTY.
7188ac27 728 * The IRENAME flag ensures that it cannot be moved by another
68f21562 729 * rename.
4f083fd7 730 */
4f1a9037 731 if (xp != ip) {
68f21562 732 if (doingdirectory)
4f1a9037 733 panic("rename: lost dir entry");
68f21562 734 } else {
4f083fd7 735 /*
68f21562
KM
736 * If the source is a directory with a
737 * new parent, the link count of the old
738 * parent directory must be decremented
739 * and ".." set to point to the new parent.
4f083fd7 740 */
68f21562 741 if (doingdirectory && newparent) {
4f083fd7
SL
742 dp->i_nlink--;
743 dp->i_flag |= ICHG;
86cdabf6 744 error = vn_rdwr(UIO_READ, ITOV(xp), (caddr_t)&dirbuf,
7188ac27 745 sizeof (struct dirtemplate), (off_t)0,
86cdabf6 746 UIO_SYSSPACE, IO_NODELOCKED,
5b169cb7 747 tndp->ni_cred, (int *)0, (struct proc *)0);
68f21562
KM
748 if (error == 0) {
749 if (dirbuf.dotdot_namlen != 2 ||
750 dirbuf.dotdot_name[0] != '.' ||
751 dirbuf.dotdot_name[1] != '.') {
0b4d6502
KB
752 lfs_dirbad(xp, 12,
753 "rename: mangled dir");
68f21562
KM
754 } else {
755 dirbuf.dotdot_ino = newparent;
86cdabf6 756 (void) vn_rdwr(UIO_WRITE, ITOV(xp),
68f21562
KM
757 (caddr_t)&dirbuf,
758 sizeof (struct dirtemplate),
93e273b9 759 (off_t)0, UIO_SYSSPACE,
86cdabf6 760 IO_NODELOCKED|IO_SYNC,
5b169cb7
KM
761 tndp->ni_cred, (int *)0,
762 (struct proc *)0);
7188ac27 763 cache_purge(ITOV(dp));
68f21562
KM
764 }
765 }
4f083fd7 766 }
0b4d6502 767 error = lfs_dirremove(fndp); /* LFS */
7188ac27 768 if (!error) {
68f21562
KM
769 xp->i_nlink--;
770 xp->i_flag |= ICHG;
4f083fd7 771 }
68f21562 772 xp->i_flag &= ~IRENAME;
4f083fd7 773 }
4f083fd7 774 if (dp)
7188ac27 775 vput(ITOV(dp));
68f21562 776 if (xp)
7188ac27
KM
777 vput(ITOV(xp));
778 vrele(ITOV(ip));
779 return (error);
a5390dce 780
4f083fd7 781bad:
4f083fd7 782 if (xp)
7188ac27
KM
783 vput(ITOV(xp));
784 vput(ITOV(dp));
4f083fd7
SL
785out:
786 ip->i_nlink--;
787 ip->i_flag |= ICHG;
7188ac27
KM
788 vrele(ITOV(ip));
789 return (error);
64d3a787 790}
88a7a62a
SL
791
792/*
793 * A virgin directory (no blushing please).
794 */
0b4d6502 795static struct dirtemplate mastertemplate = {
88a7a62a
SL
796 0, 12, 1, ".",
797 0, DIRBLKSIZ - 12, 2, ".."
798};
799
800/*
801 * Mkdir system call
802 */
a8c062c5 803lfs_mkdir(ndp, vap, p)
7188ac27
KM
804 struct nameidata *ndp;
805 struct vattr *vap;
5b169cb7 806 struct proc *p;
88a7a62a 807{
88a7a62a 808 register struct inode *ip, *dp;
7188ac27
KM
809 struct inode *tip;
810 struct vnode *dvp;
88a7a62a 811 struct dirtemplate dirtemplate;
7188ac27
KM
812 int error;
813 int dmode;
814
0b4d6502 815printf("lfs_mkdir\n");
655da945
KM
816#ifdef DIANOSTIC
817 if ((ndp->ni_nameiop & HASBUF) == 0)
818 panic("ufs_mkdir: no name");
819#endif
7188ac27
KM
820 dvp = ndp->ni_dvp;
821 dp = VTOI(dvp);
986aedaa 822 if ((unsigned short)dp->i_nlink >= LINK_MAX) {
655da945 823 free(ndp->ni_pnbuf, M_NAMEI);
986aedaa
KM
824 iput(dp);
825 return (EMLINK);
826 }
7188ac27
KM
827 dmode = vap->va_mode&0777;
828 dmode |= IFDIR;
88a7a62a 829 /*
655da945
KM
830 * Must simulate part of maknode here to acquire the inode, but
831 * not have it entered in the parent directory. The entry is made
832 * later after writing "." and ".." entries.
88a7a62a 833 */
0b4d6502 834#ifdef NOTLFS /* LFS */
4b61628b 835 if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
0b4d6502
KB
836#else
837 if (error = lfs_ialloc(dp->i_lfs, dp, &tip, ndp->ni_cred)) {
838#endif
655da945 839 free(ndp->ni_pnbuf, M_NAMEI);
88a7a62a 840 iput(dp);
7188ac27 841 return (error);
88a7a62a 842 }
7188ac27 843 ip = tip;
4b61628b
KM
844 ip->i_uid = ndp->ni_cred->cr_uid;
845 ip->i_gid = dp->i_gid;
88a7a62a 846#ifdef QUOTA
4b61628b
KM
847 if ((error = getinoquota(ip)) ||
848 (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
655da945 849 free(ndp->ni_pnbuf, M_NAMEI);
0b4d6502 850#ifdef NOTLFS /* LFS */
4b61628b 851 ifree(ip, ip->i_number, dmode);
0b4d6502
KB
852#else
853 lfs_ifree(ip);
854#endif
4b61628b
KM
855 iput(ip);
856 iput(dp);
857 return (error);
858 }
88a7a62a
SL
859#endif
860 ip->i_flag |= IACC|IUPD|ICHG;
7188ac27
KM
861 ip->i_mode = dmode;
862 ITOV(ip)->v_type = VDIR; /* Rest init'd in iget() */
88a7a62a 863 ip->i_nlink = 2;
d5075120 864 ITIMES(ip, &time, &time); /* LFS */
88a7a62a
SL
865
866 /*
867 * Bump link count in parent directory
868 * to reflect work done below. Should
869 * be done before reference is created
870 * so reparation is possible if we crash.
871 */
872 dp->i_nlink++;
873 dp->i_flag |= ICHG;
d5075120 874 ITIMES(dp, &time, &time); /* LFS */
88a7a62a
SL
875
876 /*
877 * Initialize directory with "."
878 * and ".." from static template.
879 */
880 dirtemplate = mastertemplate;
881 dirtemplate.dot_ino = ip->i_number;
882 dirtemplate.dotdot_ino = dp->i_number;
86cdabf6 883 error = vn_rdwr(UIO_WRITE, ITOV(ip), (caddr_t)&dirtemplate,
5b169cb7
KM
884 sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
885 IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0, (struct proc *)0);
7188ac27 886 if (error) {
88a7a62a
SL
887 dp->i_nlink--;
888 dp->i_flag |= ICHG;
889 goto bad;
890 }
0b4d6502 891 if (DIRBLKSIZ > dp->i_lfs->lfs_fsize) {
7188ac27 892 panic("mkdir: blksize"); /* XXX - should grow w/balloc() */
15365e07 893 } else {
23de9f20 894 ip->i_size = DIRBLKSIZ;
15365e07
KM
895 ip->i_flag |= ICHG;
896 }
88a7a62a
SL
897 /*
898 * Directory all set up, now
899 * install the entry for it in
900 * the parent directory.
901 */
0b4d6502 902 if (error = lfs_direnter(ip, ndp)) { /* LFS */
2a5d2f56
KM
903 dp->i_nlink--;
904 dp->i_flag |= ICHG;
88a7a62a
SL
905 }
906bad:
907 /*
0b4d6502 908 * No need to do an explicit lfs_itrunc here,
7188ac27 909 * vrele will do this for us because we set
88a7a62a
SL
910 * the link count to 0.
911 */
7188ac27 912 if (error) {
88a7a62a
SL
913 ip->i_nlink = 0;
914 ip->i_flag |= ICHG;
cbcdacd6
KM
915 iput(ip);
916 } else
917 ndp->ni_vp = ITOV(ip);
655da945 918 FREE(ndp->ni_pnbuf, M_NAMEI);
394d67a8 919 iput(dp);
7188ac27 920 return (error);
88a7a62a
SL
921}
922
923/*
924 * Rmdir system call.
925 */
a8c062c5 926lfs_rmdir(ndp, p)
7188ac27 927 register struct nameidata *ndp;
5b169cb7 928 struct proc *p;
88a7a62a 929{
88a7a62a 930 register struct inode *ip, *dp;
7188ac27
KM
931 int error = 0;
932
0b4d6502 933printf("lfs_rmdir\n");
7188ac27
KM
934 ip = VTOI(ndp->ni_vp);
935 dp = VTOI(ndp->ni_dvp);
88a7a62a
SL
936 /*
937 * No rmdir "." please.
938 */
939 if (dp == ip) {
7188ac27 940 vrele(ITOV(dp));
88a7a62a 941 iput(ip);
7188ac27 942 return (EINVAL);
88a7a62a
SL
943 }
944 /*
945 * Verify the directory is empty (and valid).
946 * (Rmdir ".." won't be valid since
947 * ".." will contain a reference to
948 * the current directory and thus be
949 * non-empty.)
950 */
7188ac27
KM
951 if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number, ndp->ni_cred)) {
952 error = ENOTEMPTY;
88a7a62a
SL
953 goto out;
954 }
955 /*
956 * Delete reference to directory before purging
957 * inode. If we crash in between, the directory
958 * will be reattached to lost+found,
959 */
0b4d6502 960 if (error = lfs_dirremove(ndp)) /* LFS */
88a7a62a
SL
961 goto out;
962 dp->i_nlink--;
963 dp->i_flag |= ICHG;
7188ac27 964 cache_purge(ITOV(dp));
88a7a62a 965 iput(dp);
7188ac27 966 ndp->ni_dvp = NULL;
88a7a62a
SL
967 /*
968 * Truncate inode. The only stuff left
969 * in the directory is "." and "..". The
970 * "." reference is inconsequential since
971 * we're quashing it. The ".." reference
972 * has already been adjusted above. We've
973 * removed the "." reference and the reference
974 * in the parent directory, but there may be
975 * other hard links so decrement by 2 and
976 * worry about them later.
977 */
978 ip->i_nlink -= 2;
0b4d6502 979 error = lfs_itrunc(ip, (u_long)0, IO_SYNC); /* LFS */
7188ac27 980 cache_purge(ITOV(ip));
88a7a62a 981out:
7188ac27 982 if (ndp->ni_dvp)
88a7a62a
SL
983 iput(dp);
984 iput(ip);
7188ac27 985 return (error);
88a7a62a
SL
986}
987
7188ac27
KM
988/*
989 * symlink -- make a symbolic link
990 */
a8c062c5 991lfs_symlink(ndp, vap, target, p)
7188ac27
KM
992 struct nameidata *ndp;
993 struct vattr *vap;
994 char *target;
5b169cb7 995 struct proc *p;
7188ac27
KM
996{
997 struct inode *ip;
998 int error;
999
0b4d6502 1000printf("lfs_symlink\n");
7188ac27
KM
1001 error = maknode(IFLNK | vap->va_mode, ndp, &ip);
1002 if (error)
1003 return (error);
86cdabf6 1004 error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0,
5b169cb7
KM
1005 UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0,
1006 (struct proc *)0);
7188ac27
KM
1007 iput(ip);
1008 return (error);
1009}
1010
1011/*
1012 * Vnode op for read and write
1013 */
a8c062c5 1014lfs_readdir(vp, uio, cred, eofflagp)
7188ac27
KM
1015 struct vnode *vp;
1016 register struct uio *uio;
7188ac27 1017 struct ucred *cred;
930730fd 1018 int *eofflagp;
88a7a62a 1019{
86cdabf6 1020 int count, lost, error;
88a7a62a 1021
0b4d6502 1022printf("lfs_readdir\n");
7188ac27
KM
1023 count = uio->uio_resid;
1024 count &= ~(DIRBLKSIZ - 1);
86cdabf6
KM
1025 lost = uio->uio_resid - count;
1026 if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
7188ac27 1027 return (EINVAL);
7188ac27
KM
1028 uio->uio_resid = count;
1029 uio->uio_iov->iov_len = count;
0b4d6502 1030 error = lfs_read(vp, uio, 0, cred); /* LFS */
86cdabf6 1031 uio->uio_resid += lost;
930730fd
KM
1032 if ((VTOI(vp)->i_size - uio->uio_offset) <= 0)
1033 *eofflagp = 1;
1034 else
1035 *eofflagp = 0;
7188ac27
KM
1036 return (error);
1037}
1038
1039/*
1040 * Return target name of a symbolic link
1041 */
a8c062c5 1042lfs_readlink(vp, uiop, cred)
7188ac27
KM
1043 struct vnode *vp;
1044 struct uio *uiop;
1045 struct ucred *cred;
1046{
1047
0b4d6502
KB
1048printf("lfs_readlink\n");
1049 return (lfs_read(vp, uiop, 0, cred)); /* LFS */
1c3ebc10
KM
1050}
1051
7188ac27
KM
1052/*
1053 * Get access to bmap
1054 */
0b4d6502 1055lfs_vbmap(vp, bn, vpp, bnp)
7188ac27
KM
1056 struct vnode *vp;
1057 daddr_t bn;
1058 struct vnode **vpp;
1059 daddr_t *bnp;
1060{
1061 struct inode *ip = VTOI(vp);
1062
0b4d6502 1063printf("lfs_vbmap\n");
7188ac27
KM
1064 if (vpp != NULL)
1065 *vpp = ip->i_devvp;
1066 if (bnp == NULL)
1067 return (0);
0b4d6502 1068 return (lfs_bmap(ip, bn, bnp)); /* LFS */
88a7a62a
SL
1069}
1070
1071/*
4f1ff475
KM
1072 * Calculate the logical to physical mapping if not done already,
1073 * then call the device strategy routine.
88a7a62a 1074 */
a8c062c5 1075lfs_strategy(bp)
7188ac27 1076 register struct buf *bp;
88a7a62a 1077{
e16fa59e 1078 register struct inode *ip = VTOI(bp->b_vp);
e16fa59e 1079 struct vnode *vp;
e16fa59e
KM
1080 int error;
1081
0b4d6502
KB
1082printf("lfs_strategy: type: %d lblk %d pblk %d\n", bp->b_vp->v_type,
1083 bp->b_lblkno, bp->b_blkno);
e16fa59e
KM
1084 if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
1085 panic("ufs_strategy: spec");
0b4d6502
KB
1086 if (bp->b_blkno == bp->b_lblkno) { /* LFS */
1087 if (error = lfs_bmap(ip, bp->b_lblkno, &bp->b_blkno))
e16fa59e 1088 return (error);
20aa076b 1089 if ((long)bp->b_blkno == -1)
e16fa59e 1090 clrbuf(bp);
e16fa59e 1091 }
20aa076b
KM
1092 if ((long)bp->b_blkno == -1) {
1093 biodone(bp);
e16fa59e 1094 return (0);
20aa076b 1095 }
e16fa59e
KM
1096 vp = ip->i_devvp;
1097 bp->b_dev = vp->v_rdev;
20454d5a 1098 (*(vp->v_op->vop_strategy))(bp);
7188ac27
KM
1099 return (0);
1100}
88a7a62a 1101
7188ac27 1102/*
36979c87 1103 * Allocate a new inode.
7188ac27 1104 */
a8c062c5 1105static int
7188ac27
KM
1106maknode(mode, ndp, ipp)
1107 int mode;
1108 register struct nameidata *ndp;
1109 struct inode **ipp;
1110{
1111 register struct inode *ip;
1112 struct inode *tip;
1113 register struct inode *pdir = VTOI(ndp->ni_dvp);
1114 ino_t ipref;
1115 int error;
1116
0b4d6502 1117printf("maknode\n");
655da945
KM
1118#ifdef DIANOSTIC
1119 if ((ndp->ni_nameiop & HASBUF) == 0)
1120 panic("maknode: no name");
1121#endif
7188ac27 1122 *ipp = 0;
4b61628b
KM
1123 if ((mode & IFMT) == 0)
1124 mode |= IFREG;
0b4d6502 1125#ifdef NOTLFS /* LFS */
7188ac27
KM
1126 if ((mode & IFMT) == IFDIR)
1127 ipref = dirpref(pdir->i_fs);
1128 else
1129 ipref = pdir->i_number;
4b61628b 1130 if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
0b4d6502
KB
1131#else
1132 if (error = lfs_ialloc(pdir->i_lfs, pdir, &tip, ndp->ni_cred)) {
1133#endif
655da945 1134 free(ndp->ni_pnbuf, M_NAMEI);
7188ac27
KM
1135 iput(pdir);
1136 return (error);
1137 }
1138 ip = tip;
4b61628b
KM
1139 ip->i_uid = ndp->ni_cred->cr_uid;
1140 ip->i_gid = pdir->i_gid;
7188ac27 1141#ifdef QUOTA
4b61628b
KM
1142 if ((error = getinoquota(ip)) ||
1143 (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
655da945 1144 free(ndp->ni_pnbuf, M_NAMEI);
0b4d6502 1145#ifdef NOTLFS /* LFS */
4b61628b 1146 ifree(ip, ip->i_number, mode);
0b4d6502
KB
1147#else
1148 lfs_ifree(ip);
1149#endif
4b61628b
KM
1150 iput(ip);
1151 iput(pdir);
1152 return (error);
1153 }
7188ac27
KM
1154#endif
1155 ip->i_flag |= IACC|IUPD|ICHG;
7188ac27
KM
1156 ip->i_mode = mode;
1157 ITOV(ip)->v_type = IFTOVT(mode); /* Rest init'd in iget() */
1158 ip->i_nlink = 1;
7188ac27
KM
1159 if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
1160 suser(ndp->ni_cred, NULL))
1161 ip->i_mode &= ~ISGID;
7188ac27 1162
d5075120 1163 ITIMES(ip, &time, &time); /* LFS */
0b4d6502 1164 if (error = lfs_direnter(ip, ndp)) /* LFS */
4b61628b 1165 goto bad;
655da945
KM
1166 if ((ndp->ni_nameiop & SAVESTART) == 0)
1167 FREE(ndp->ni_pnbuf, M_NAMEI);
394d67a8 1168 iput(pdir);
7188ac27
KM
1169 *ipp = ip;
1170 return (0);
4b61628b
KM
1171
1172bad:
1173 /*
1174 * Write error occurred trying to update the inode
1175 * or the directory so must deallocate the inode.
1176 */
655da945 1177 free(ndp->ni_pnbuf, M_NAMEI);
394d67a8 1178 iput(pdir);
4b61628b
KM
1179 ip->i_nlink = 0;
1180 ip->i_flag |= ICHG;
1181 iput(ip);
1182 return (error);
88a7a62a 1183}
0b0bf936 1184
5b169cb7 1185/*
a8c062c5 1186 * Global vfs data structures for lfs
5b169cb7 1187 */
a8c062c5 1188struct vnodeops lfs_vnodeops = {
0b4d6502
KB
1189 lfs_lookup, /* lookup */
1190 lfs_create, /* create */
1191 lfs_mknod, /* mknod */
5b169cb7
KM
1192 ufs_open, /* open */
1193 ufs_close, /* close */
1194 ufs_access, /* access */
0b4d6502
KB
1195 lfs_getattr, /* getattr */
1196 lfs_setattr, /* setattr */
1197 lfs_read, /* read */
1198 lfs_write, /* write */
5b169cb7
KM
1199 ufs_ioctl, /* ioctl */
1200 ufs_select, /* select */
1201 ufs_mmap, /* mmap */
0b4d6502 1202 lfs_fsync, /* fsync */
5b169cb7 1203 ufs_seek, /* seek */
0b4d6502
KB
1204 lfs_remove, /* remove */
1205 lfs_link, /* link */
1206 lfs_rename, /* rename */
1207 lfs_mkdir, /* mkdir */
1208 lfs_rmdir, /* rmdir */
1209 lfs_symlink, /* symlink */
1210 lfs_readdir, /* readdir */
1211 lfs_readlink, /* readlink */
5b169cb7 1212 ufs_abortop, /* abortop */
0b4d6502 1213 lfs_inactive, /* inactive */
5b169cb7
KM
1214 ufs_reclaim, /* reclaim */
1215 ufs_lock, /* lock */
1216 ufs_unlock, /* unlock */
0b4d6502
KB
1217 lfs_vbmap, /* bmap */
1218 lfs_strategy, /* strategy */
5b169cb7
KM
1219 ufs_print, /* print */
1220 ufs_islocked, /* islocked */
1221 ufs_advlock, /* advlock */
1222};