1 /* 2 * Copyright (c) 1986, 1989, 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_vnops.c 7.71 (Berkeley) 11/05/91 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/namei.h> 13 #include <sys/resourcevar.h> 14 #include <sys/kernel.h> 15 #include <sys/file.h> 16 #include <sys/stat.h> 17 #include <sys/buf.h> 18 #include <sys/proc.h> 19 #include <sys/conf.h> 20 #include <sys/mount.h> 21 #include <sys/vnode.h> 22 #include <sys/specdev.h> 23 #include <sys/fifo.h> 24 #include <sys/malloc.h> 25 26 #include <ufs/ufs/quota.h> 27 #include <ufs/ufs/inode.h> 28 #include <ufs/ufs/dir.h> 29 #include <ufs/ufs/ufs_extern.h> 30 31 #include <ufs/lfs/lfs.h> 32 #include <ufs/lfs/lfs_extern.h> 33 34 /* Global vfs data structures for lfs. */ 35 struct vnodeops lfs_vnodeops = { 36 ufs_lookup, /* lookup */ 37 ufs_create, /* create */ 38 ufs_mknod, /* mknod */ 39 ufs_open, /* open */ 40 ufs_close, /* close */ 41 ufs_access, /* access */ 42 ufs_getattr, /* getattr */ 43 ufs_setattr, /* setattr */ 44 lfs_read, /* read */ 45 lfs_write, /* write */ 46 ufs_ioctl, /* ioctl */ 47 ufs_select, /* select */ 48 ufs_mmap, /* mmap */ 49 lfs_fsync, /* fsync */ 50 ufs_seek, /* seek */ 51 ufs_remove, /* remove */ 52 ufs_link, /* link */ 53 ufs_rename, /* rename */ 54 ufs_mkdir, /* mkdir */ 55 ufs_rmdir, /* rmdir */ 56 ufs_symlink, /* symlink */ 57 ufs_readdir, /* readdir */ 58 ufs_readlink, /* readlink */ 59 ufs_abortop, /* abortop */ 60 lfs_inactive, /* inactive */ 61 ufs_reclaim, /* reclaim */ 62 ufs_lock, /* lock */ 63 ufs_unlock, /* unlock */ 64 lfs_bmap, /* bmap */ 65 ufs_strategy, /* strategy */ 66 ufs_print, /* print */ 67 ufs_islocked, /* islocked */ 68 ufs_advlock, /* advlock */ 69 lfs_blkatoff, /* blkatoff */ 70 lfs_vget, /* vget */ 71 lfs_valloc, /* valloc */ 72 lfs_vfree, /* vfree */ 73 lfs_truncate, /* truncate */ 74 lfs_update, /* update */ 75 lfs_bwrite, /* bwrite */ 76 }; 77 78 struct vnodeops lfs_specops = { 79 spec_lookup, /* lookup */ 80 spec_create, /* create */ 81 spec_mknod, /* mknod */ 82 spec_open, /* open */ 83 ufsspec_close, /* close */ 84 ufs_access, /* access */ 85 ufs_getattr, /* getattr */ 86 ufs_setattr, /* setattr */ 87 ufsspec_read, /* read */ 88 ufsspec_write, /* write */ 89 spec_ioctl, /* ioctl */ 90 spec_select, /* select */ 91 spec_mmap, /* mmap */ 92 spec_fsync, /* fsync */ 93 spec_seek, /* seek */ 94 spec_remove, /* remove */ 95 spec_link, /* link */ 96 spec_rename, /* rename */ 97 spec_mkdir, /* mkdir */ 98 spec_rmdir, /* rmdir */ 99 spec_symlink, /* symlink */ 100 spec_readdir, /* readdir */ 101 spec_readlink, /* readlink */ 102 spec_abortop, /* abortop */ 103 lfs_inactive, /* inactive */ 104 ufs_reclaim, /* reclaim */ 105 ufs_lock, /* lock */ 106 ufs_unlock, /* unlock */ 107 spec_bmap, /* bmap */ 108 spec_strategy, /* strategy */ 109 ufs_print, /* print */ 110 ufs_islocked, /* islocked */ 111 spec_advlock, /* advlock */ 112 spec_blkatoff, /* blkatoff */ 113 spec_vget, /* vget */ 114 spec_valloc, /* valloc */ 115 spec_vfree, /* vfree */ 116 spec_truncate, /* truncate */ 117 lfs_update, /* update */ 118 lfs_bwrite, /* bwrite */ 119 }; 120 121 #ifdef FIFO 122 struct vnodeops lfs_fifoops = { 123 fifo_lookup, /* lookup */ 124 fifo_create, /* create */ 125 fifo_mknod, /* mknod */ 126 fifo_open, /* open */ 127 ufsfifo_close, /* close */ 128 ufs_access, /* access */ 129 ufs_getattr, /* getattr */ 130 ufs_setattr, /* setattr */ 131 ufsfifo_read, /* read */ 132 ufsfifo_write, /* write */ 133 fifo_ioctl, /* ioctl */ 134 fifo_select, /* select */ 135 fifo_mmap, /* mmap */ 136 fifo_fsync, /* fsync */ 137 fifo_seek, /* seek */ 138 fifo_remove, /* remove */ 139 fifo_link, /* link */ 140 fifo_rename, /* rename */ 141 fifo_mkdir, /* mkdir */ 142 fifo_rmdir, /* rmdir */ 143 fifo_symlink, /* symlink */ 144 fifo_readdir, /* readdir */ 145 fifo_readlink, /* readlink */ 146 fifo_abortop, /* abortop */ 147 lfs_inactive, /* inactive */ 148 ufs_reclaim, /* reclaim */ 149 ufs_lock, /* lock */ 150 ufs_unlock, /* unlock */ 151 fifo_bmap, /* bmap */ 152 fifo_strategy, /* strategy */ 153 ufs_print, /* print */ 154 ufs_islocked, /* islocked */ 155 fifo_advlock, /* advlock */ 156 fifo_blkatoff, /* blkatoff */ 157 fifo_vget, /* vget */ 158 fifo_valloc, /* valloc */ 159 fifo_vfree, /* vfree */ 160 fifo_truncate, /* truncate */ 161 lfs_update, /* update */ 162 lfs_bwrite, /* bwrite */ 163 }; 164 #endif /* FIFO */ 165 166 /* 167 * Vnode op for reading. 168 */ 169 /* ARGSUSED */ 170 lfs_read(vp, uio, ioflag, cred) 171 struct vnode *vp; 172 register struct uio *uio; 173 int ioflag; 174 struct ucred *cred; 175 { 176 register struct inode *ip = VTOI(vp); 177 register struct lfs *fs; /* LFS */ 178 struct buf *bp; 179 daddr_t lbn, bn, rablock; 180 int size, diff, error = 0; 181 long n, on, type; 182 183 printf("lfs_read: ino %d\n", ip->i_number); 184 #ifdef DIAGNOSTIC 185 if (uio->uio_rw != UIO_READ) 186 panic("ufs_read mode"); 187 type = ip->i_mode & IFMT; 188 if (type != IFDIR && type != IFREG && type != IFLNK) 189 panic("ufs_read type"); 190 #endif 191 if (uio->uio_resid == 0) 192 return (0); 193 if (uio->uio_offset < 0) 194 return (EINVAL); 195 ip->i_flag |= IACC; 196 197 fs = ip->i_lfs; /* LFS */ 198 do { 199 lbn = lblkno(fs, uio->uio_offset); 200 on = blkoff(fs, uio->uio_offset); 201 n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 202 diff = ip->i_size - uio->uio_offset; 203 if (diff <= 0) 204 return (0); 205 if (diff < n) 206 n = diff; 207 size = blksize(fs); /* LFS */ 208 rablock = lbn + 1; 209 if (vp->v_lastr + 1 == lbn && 210 lblktosize(fs, rablock) < ip->i_size) 211 error = breada(ITOV(ip), lbn, size, rablock, 212 blksize(fs), NOCRED, &bp); 213 else 214 error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 215 vp->v_lastr = lbn; 216 n = MIN(n, size - bp->b_resid); 217 if (error) { 218 brelse(bp); 219 return (error); 220 } 221 error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 222 if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size) 223 bp->b_flags |= B_AGE; 224 brelse(bp); 225 } while (error == 0 && uio->uio_resid > 0 && n != 0); 226 return (error); 227 } 228 229 /* 230 * Vnode op for writing. 231 */ 232 lfs_write(vp, uio, ioflag, cred) 233 register struct vnode *vp; 234 struct uio *uio; 235 int ioflag; 236 struct ucred *cred; 237 { 238 struct proc *p = uio->uio_procp; 239 register struct inode *ip = VTOI(vp); 240 register struct lfs *fs; /* LFS */ 241 struct buf *bp; 242 daddr_t lbn, bn; 243 u_long osize; 244 int n, on, flags; 245 int size, resid, error = 0; 246 247 printf("lfs_write ino %d\n", ip->i_number); 248 #ifdef DIAGNOSTIC 249 if (uio->uio_rw != UIO_WRITE) 250 panic("ufs_write mode"); 251 #endif 252 switch (vp->v_type) { 253 case VREG: 254 if (ioflag & IO_APPEND) 255 uio->uio_offset = ip->i_size; 256 /* fall through */ 257 case VLNK: 258 break; 259 260 case VDIR: 261 if ((ioflag & IO_SYNC) == 0) 262 panic("ufs_write nonsync dir write"); 263 break; 264 265 default: 266 panic("ufs_write type"); 267 } 268 if (uio->uio_offset < 0) 269 return (EINVAL); 270 if (uio->uio_resid == 0) 271 return (0); 272 /* 273 * Maybe this should be above the vnode op call, but so long as 274 * file servers have no limits, i don't think it matters 275 */ 276 if (vp->v_type == VREG && p && 277 uio->uio_offset + uio->uio_resid > 278 p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 279 psignal(p, SIGXFSZ); 280 return (EFBIG); 281 } 282 resid = uio->uio_resid; 283 osize = ip->i_size; 284 fs = ip->i_lfs; /* LFS */ 285 flags = 0; 286 #ifdef NOTLFS 287 if (ioflag & IO_SYNC) 288 flags = B_SYNC; 289 #endif 290 do { 291 lbn = lblkno(fs, uio->uio_offset); 292 on = blkoff(fs, uio->uio_offset); /* LFS */ 293 n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 294 if (n < fs->lfs_bsize) /* LFS */ 295 flags |= B_CLRBUF; 296 else 297 flags &= ~B_CLRBUF; /* LFS */ 298 if (error = bread(vp, lbn, fs->lfs_bsize, NOCRED, &bp)) 299 break; 300 bn = bp->b_blkno; 301 if (uio->uio_offset + n > ip->i_size) { 302 ip->i_size = uio->uio_offset + n; 303 vnode_pager_setsize(vp, ip->i_size); 304 } 305 size = blksize(fs); 306 (void) vnode_pager_uncache(vp); 307 n = MIN(n, size - bp->b_resid); 308 error = uiomove(bp->b_un.b_addr + on, n, uio); 309 #ifdef NOTLFS /* LFS */ 310 if (ioflag & IO_SYNC) 311 (void) bwrite(bp); 312 else if (n + on == fs->fs_bsize) { 313 bp->b_flags |= B_AGE; 314 bawrite(bp); 315 } else 316 bdwrite(bp); 317 #else 318 /* 319 * Update segment usage information; call segment 320 * writer if necessary. 321 */ 322 lfs_bwrite(bp); 323 #endif 324 ip->i_flag |= IUPD|ICHG; 325 if (cred->cr_uid != 0) 326 ip->i_mode &= ~(ISUID|ISGID); 327 } while (error == 0 && uio->uio_resid > 0 && n != 0); 328 if (error && (ioflag & IO_UNIT)) { 329 #ifdef NOTLFS 330 /* This just doesn't work... */ 331 (void) lfs_itrunc(vp, osize, ioflag & IO_SYNC); 332 #endif 333 uio->uio_offset -= resid - uio->uio_resid; 334 uio->uio_resid = resid; 335 } 336 if (!error && (ioflag & IO_SYNC)) 337 ITIMES(ip, &time, &time); /* LFS */ 338 return (error); 339 } 340 341 /* 342 * Synch an open file. 343 */ 344 /* ARGSUSED */ 345 lfs_fsync(vp, fflags, cred, waitfor, p) 346 struct vnode *vp; 347 int fflags; 348 struct ucred *cred; 349 int waitfor; 350 struct proc *p; 351 { 352 struct inode *ip = VTOI(vp); 353 354 if (fflags & FWRITE) 355 ip->i_flag |= ICHG; 356 /* 357 * XXX 358 * Sync the mounted file system associated with the file 359 * descriptor. 360 */ 361 ITIMES(ip, &time, &time); /* LFS */ 362 return (0); 363 } 364 365 /* 366 * Last reference to an inode, write the inode out and if necessary, 367 * truncate and deallocate the file. 368 */ 369 int 370 lfs_inactive(vp, p) 371 struct vnode *vp; 372 struct proc *p; 373 { 374 register struct inode *ip; 375 int mode, error; 376 extern int prtactive; 377 378 if (prtactive && vp->v_usecount != 0) 379 vprint("lfs_inactive: pushing active", vp); 380 381 /* Get rid of inodes related to stale file handles. */ 382 ip = VTOI(vp); 383 if (ip->i_mode == 0) { 384 if ((vp->v_flag & VXLOCK) == 0) 385 vgone(vp); 386 return (0); 387 } 388 389 error = 0; 390 ILOCK(ip); 391 if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 392 #ifdef QUOTA 393 if (!getinoquota(ip)) 394 (void)chkiq(ip, -1, NOCRED, 0); 395 #endif 396 error = lfs_truncate(vp, (u_long)0, 0); 397 mode = ip->i_mode; 398 ip->i_mode = 0; 399 ip->i_rdev = 0; 400 ip->i_flag |= IUPD|ICHG; 401 lfs_vfree(vp, ip->i_number, mode); 402 } 403 if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) 404 lfs_update(vp, &time, &time, 0); 405 IUNLOCK(ip); 406 ip->i_flag = 0; 407 /* 408 * If we are done with the inode, reclaim it 409 * so that it can be reused immediately. 410 */ 411 if (vp->v_usecount == 0 && ip->i_mode == 0) 412 vgone(vp); 413 return (error); 414 } 415