1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ffs_vnops.c 7.66 (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/lockf.h> 27 #include <ufs/ufs/quota.h> 28 #include <ufs/ufs/inode.h> 29 #include <ufs/ufs/dir.h> 30 #include <ufs/ufs/ufs_extern.h> 31 32 #include <ufs/ffs/fs.h> 33 #include <ufs/ffs/ffs_extern.h> 34 35 /* Global vfs data structures for ufs. */ 36 struct vnodeops ffs_vnodeops = { 37 ufs_lookup, /* lookup */ 38 ufs_create, /* create */ 39 ufs_mknod, /* mknod */ 40 ufs_open, /* open */ 41 ufs_close, /* close */ 42 ufs_access, /* access */ 43 ufs_getattr, /* getattr */ 44 ufs_setattr, /* setattr */ 45 ffs_read, /* read */ 46 ffs_write, /* write */ 47 ufs_ioctl, /* ioctl */ 48 ufs_select, /* select */ 49 ufs_mmap, /* mmap */ 50 ffs_fsync, /* fsync */ 51 ufs_seek, /* seek */ 52 ufs_remove, /* remove */ 53 ufs_link, /* link */ 54 ufs_rename, /* rename */ 55 ufs_mkdir, /* mkdir */ 56 ufs_rmdir, /* rmdir */ 57 ufs_symlink, /* symlink */ 58 ufs_readdir, /* readdir */ 59 ufs_readlink, /* readlink */ 60 ufs_abortop, /* abortop */ 61 ffs_inactive, /* inactive */ 62 ufs_reclaim, /* reclaim */ 63 ufs_lock, /* lock */ 64 ufs_unlock, /* unlock */ 65 ffs_bmap, /* bmap */ 66 ufs_strategy, /* strategy */ 67 ufs_print, /* print */ 68 ufs_islocked, /* islocked */ 69 ufs_advlock, /* advlock */ 70 ffs_blkatoff, /* blkatoff */ 71 ffs_vget, /* vget */ 72 ffs_valloc, /* valloc */ 73 ffs_vfree, /* vfree */ 74 ffs_truncate, /* truncate */ 75 ffs_update, /* update */ 76 bwrite, /* bwrite */ 77 }; 78 79 struct vnodeops ffs_specops = { 80 spec_lookup, /* lookup */ 81 spec_create, /* create */ 82 spec_mknod, /* mknod */ 83 spec_open, /* open */ 84 ufsspec_close, /* close */ 85 ufs_access, /* access */ 86 ufs_getattr, /* getattr */ 87 ufs_setattr, /* setattr */ 88 ufsspec_read, /* read */ 89 ufsspec_write, /* write */ 90 spec_ioctl, /* ioctl */ 91 spec_select, /* select */ 92 spec_mmap, /* mmap */ 93 spec_fsync, /* fsync */ 94 spec_seek, /* seek */ 95 spec_remove, /* remove */ 96 spec_link, /* link */ 97 spec_rename, /* rename */ 98 spec_mkdir, /* mkdir */ 99 spec_rmdir, /* rmdir */ 100 spec_symlink, /* symlink */ 101 spec_readdir, /* readdir */ 102 spec_readlink, /* readlink */ 103 spec_abortop, /* abortop */ 104 ffs_inactive, /* inactive */ 105 ufs_reclaim, /* reclaim */ 106 ufs_lock, /* lock */ 107 ufs_unlock, /* unlock */ 108 spec_bmap, /* bmap */ 109 spec_strategy, /* strategy */ 110 ufs_print, /* print */ 111 ufs_islocked, /* islocked */ 112 spec_advlock, /* advlock */ 113 spec_blkatoff, /* blkatoff */ 114 spec_vget, /* vget */ 115 spec_valloc, /* valloc */ 116 spec_vfree, /* vfree */ 117 spec_truncate, /* truncate */ 118 ffs_update, /* update */ 119 bwrite, /* bwrite */ 120 }; 121 122 #ifdef FIFO 123 struct vnodeops ffs_fifoops = { 124 fifo_lookup, /* lookup */ 125 fifo_create, /* create */ 126 fifo_mknod, /* mknod */ 127 fifo_open, /* open */ 128 ufsfifo_close, /* close */ 129 ufs_access, /* access */ 130 ufs_getattr, /* getattr */ 131 ufs_setattr, /* setattr */ 132 ufsfifo_read, /* read */ 133 ufsfifo_write, /* write */ 134 fifo_ioctl, /* ioctl */ 135 fifo_select, /* select */ 136 fifo_mmap, /* mmap */ 137 fifo_fsync, /* fsync */ 138 fifo_seek, /* seek */ 139 fifo_remove, /* remove */ 140 fifo_link, /* link */ 141 fifo_rename, /* rename */ 142 fifo_mkdir, /* mkdir */ 143 fifo_rmdir, /* rmdir */ 144 fifo_symlink, /* symlink */ 145 fifo_readdir, /* readdir */ 146 fifo_readlink, /* readlink */ 147 fifo_abortop, /* abortop */ 148 ffs_inactive, /* inactive */ 149 ufs_reclaim, /* reclaim */ 150 ufs_lock, /* lock */ 151 ufs_unlock, /* unlock */ 152 fifo_bmap, /* bmap */ 153 fifo_strategy, /* strategy */ 154 ufs_print, /* print */ 155 ufs_islocked, /* islocked */ 156 fifo_advlock, /* advlock */ 157 fifo_blkatoff, /* blkatoff */ 158 fifo_vget, /* vget */ 159 fifo_valloc, /* valloc */ 160 fifo_vfree, /* vfree */ 161 fifo_truncate, /* truncate */ 162 ffs_update, /* update */ 163 bwrite, /* bwrite */ 164 }; 165 #endif /* FIFO */ 166 167 int maknode __P((int, struct nameidata *, struct inode **)); 168 169 /* 170 * Vnode op for reading. 171 */ 172 /* ARGSUSED */ 173 ffs_read(vp, uio, ioflag, cred) 174 struct vnode *vp; 175 register struct uio *uio; 176 int ioflag; 177 struct ucred *cred; 178 { 179 register struct inode *ip = VTOI(vp); 180 register struct fs *fs; 181 struct buf *bp; 182 daddr_t lbn, bn, rablock; 183 int size, diff, error = 0; 184 long n, on, type; 185 186 #ifdef DIAGNOSTIC 187 if (uio->uio_rw != UIO_READ) 188 panic("ffs_read mode"); 189 type = ip->i_mode & IFMT; 190 if (type != IFDIR && type != IFREG && type != IFLNK) 191 panic("ffs_read type"); 192 #endif 193 if (uio->uio_resid == 0) 194 return (0); 195 if (uio->uio_offset < 0) 196 return (EINVAL); 197 ip->i_flag |= IACC; 198 fs = ip->i_fs; 199 do { 200 lbn = lblkno(fs, uio->uio_offset); 201 on = blkoff(fs, uio->uio_offset); 202 n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid); 203 diff = ip->i_size - uio->uio_offset; 204 if (diff <= 0) 205 return (0); 206 if (diff < n) 207 n = diff; 208 size = blksize(fs, ip, lbn); 209 rablock = lbn + 1; 210 if (vp->v_lastr + 1 == lbn && 211 lblktosize(fs, rablock) < ip->i_size) 212 error = breada(ITOV(ip), lbn, size, rablock, 213 blksize(fs, ip, rablock), NOCRED, &bp); 214 else 215 error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 216 vp->v_lastr = lbn; 217 n = MIN(n, size - bp->b_resid); 218 if (error) { 219 brelse(bp); 220 return (error); 221 } 222 error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 223 if (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size) 224 bp->b_flags |= B_AGE; 225 brelse(bp); 226 } while (error == 0 && uio->uio_resid > 0 && n != 0); 227 return (error); 228 } 229 230 /* 231 * Vnode op for writing. 232 */ 233 ffs_write(vp, uio, ioflag, cred) 234 register struct vnode *vp; 235 struct uio *uio; 236 int ioflag; 237 struct ucred *cred; 238 { 239 struct proc *p = uio->uio_procp; 240 register struct inode *ip = VTOI(vp); 241 register struct fs *fs; 242 struct buf *bp; 243 daddr_t lbn, bn; 244 u_long osize; 245 int n, on, flags; 246 int size, resid, error = 0; 247 248 #ifdef DIAGNOSTIC 249 if (uio->uio_rw != UIO_WRITE) 250 panic("ffs_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("ffs_write nonsync dir write"); 263 break; 264 265 default: 266 panic("ffs_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_fs; 285 flags = 0; 286 if (ioflag & IO_SYNC) 287 flags = B_SYNC; 288 do { 289 lbn = lblkno(fs, uio->uio_offset); 290 on = blkoff(fs, uio->uio_offset); 291 n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid); 292 if (n < fs->fs_bsize) 293 flags |= B_CLRBUF; 294 else 295 flags &= ~B_CLRBUF; 296 if (error = ffs_balloc(ip, lbn, (int)(on + n), &bp, flags)) 297 break; 298 bn = bp->b_blkno; 299 if (uio->uio_offset + n > ip->i_size) { 300 ip->i_size = uio->uio_offset + n; 301 vnode_pager_setsize(vp, ip->i_size); 302 } 303 size = blksize(fs, ip, lbn); 304 (void) vnode_pager_uncache(vp); 305 n = MIN(n, size - bp->b_resid); 306 error = uiomove(bp->b_un.b_addr + on, n, uio); 307 if (ioflag & IO_SYNC) 308 (void) bwrite(bp); 309 else if (n + on == fs->fs_bsize) { 310 bp->b_flags |= B_AGE; 311 bawrite(bp); 312 } else 313 bdwrite(bp); 314 ip->i_flag |= IUPD|ICHG; 315 if (cred->cr_uid != 0) 316 ip->i_mode &= ~(ISUID|ISGID); 317 } while (error == 0 && uio->uio_resid > 0 && n != 0); 318 if (error && (ioflag & IO_UNIT)) { 319 (void)ffs_truncate(vp, osize, ioflag & IO_SYNC); 320 uio->uio_offset -= resid - uio->uio_resid; 321 uio->uio_resid = resid; 322 } 323 if (!error && (ioflag & IO_SYNC)) 324 error = ffs_update(vp, &time, &time, 1); 325 return (error); 326 } 327 328 /* 329 * Synch an open file. 330 */ 331 /* ARGSUSED */ 332 int 333 ffs_fsync(vp, fflags, cred, waitfor, p) 334 struct vnode *vp; 335 int fflags; 336 struct ucred *cred; 337 int waitfor; 338 struct proc *p; 339 { 340 struct inode *ip = VTOI(vp); 341 342 if (fflags & FWRITE) 343 ip->i_flag |= ICHG; 344 vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0); 345 return (ffs_update(vp, &time, &time, waitfor == MNT_WAIT)); 346 } 347 348 /* 349 * Last reference to an inode, write the inode out and if necessary, 350 * truncate and deallocate the file. 351 */ 352 int 353 ffs_inactive(vp, p) 354 struct vnode *vp; 355 struct proc *p; 356 { 357 register struct inode *ip; 358 int mode, error; 359 extern int prtactive; 360 361 if (prtactive && vp->v_usecount != 0) 362 vprint("ffs_inactive: pushing active", vp); 363 364 /* Get rid of inodes related to stale file handles. */ 365 ip = VTOI(vp); 366 if (ip->i_mode == 0) { 367 if ((vp->v_flag & VXLOCK) == 0) 368 vgone(vp); 369 return (0); 370 } 371 372 error = 0; 373 ILOCK(ip); 374 if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 375 #ifdef QUOTA 376 if (!getinoquota(ip)) 377 (void)chkiq(ip, -1, NOCRED, 0); 378 #endif 379 error = ffs_truncate(vp, (u_long)0, 0); 380 mode = ip->i_mode; 381 ip->i_mode = 0; 382 ip->i_rdev = 0; 383 ip->i_flag |= IUPD|ICHG; 384 ffs_vfree(vp, ip->i_number, mode); 385 } 386 if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) 387 ffs_update(vp, &time, &time, 0); 388 IUNLOCK(ip); 389 ip->i_flag = 0; 390 /* 391 * If we are done with the inode, reclaim it 392 * so that it can be reused immediately. 393 */ 394 if (vp->v_usecount == 0 && ip->i_mode == 0) 395 vgone(vp); 396 return (error); 397 } 398