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