1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)vfs_vnops.c 7.15 (Berkeley) 02/08/90 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "user.h" 23 #include "kernel.h" 24 #include "file.h" 25 #include "stat.h" 26 #include "buf.h" 27 #include "proc.h" 28 #include "uio.h" 29 #include "socket.h" 30 #include "socketvar.h" 31 #include "mount.h" 32 #include "vnode.h" 33 #include "../ufs/fs.h" 34 #include "../ufs/quota.h" 35 #include "ioctl.h" 36 #include "tty.h" 37 #include "tsleep.h" 38 39 int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); 40 struct fileops vnops = 41 { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; 42 43 /* 44 * Common code for vnode open operations. 45 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 46 */ 47 vn_open(ndp, fmode, cmode) 48 register struct nameidata *ndp; 49 int fmode, cmode; 50 { 51 register struct vnode *vp; 52 struct vattr vat; 53 struct vattr *vap = &vat; 54 int error; 55 56 if (fmode & FCREAT) { 57 ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 58 if ((fmode & FEXCL) == 0) 59 ndp->ni_nameiop |= FOLLOW; 60 if (error = namei(ndp)) 61 return (error); 62 if (ndp->ni_vp == NULL) { 63 vattr_null(vap); 64 vap->va_type = VREG; 65 vap->va_mode = cmode; 66 if (error = VOP_CREATE(ndp, vap)) 67 return (error); 68 fmode &= ~FTRUNC; 69 vp = ndp->ni_vp; 70 } else { 71 if (ndp->ni_dvp == ndp->ni_vp) 72 vrele(ndp->ni_dvp); 73 else if (ndp->ni_dvp != NULL) 74 vput(ndp->ni_dvp); 75 ndp->ni_dvp = NULL; 76 vp = ndp->ni_vp; 77 if (fmode & FEXCL) { 78 error = EEXIST; 79 goto bad; 80 } 81 fmode &= ~FCREAT; 82 } 83 } else { 84 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 85 if (error = namei(ndp)) 86 return (error); 87 vp = ndp->ni_vp; 88 } 89 if (vp->v_type == VSOCK) { 90 error = EOPNOTSUPP; 91 goto bad; 92 } 93 if ((fmode & FCREAT) == 0) { 94 if (fmode & FREAD) { 95 if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred)) 96 goto bad; 97 } 98 if (fmode & (FWRITE|FTRUNC)) { 99 if (vp->v_type == VDIR) { 100 error = EISDIR; 101 goto bad; 102 } 103 if ((error = vn_writechk(vp)) || 104 (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred))) 105 goto bad; 106 } 107 } 108 if (fmode & FTRUNC) { 109 vattr_null(vap); 110 vap->va_size = 0; 111 if (error = VOP_SETATTR(vp, vap, ndp->ni_cred)) 112 goto bad; 113 } 114 VOP_UNLOCK(vp); 115 if (setjmp(&u.u_qsave)) { 116 if (error == 0) 117 error = EINTR; 118 return (error); 119 } 120 error = VOP_OPEN(vp, fmode, ndp->ni_cred); 121 if (error) 122 vrele(vp); 123 return (error); 124 125 bad: 126 vput(vp); 127 return(error); 128 } 129 130 /* 131 * Check for write permissions on the specified vnode. 132 * The read-only status of the file system is checked. 133 * Also, prototype text segments cannot be written. 134 */ 135 vn_writechk(vp) 136 register struct vnode *vp; 137 { 138 139 /* 140 * Disallow write attempts on read-only file systems; 141 * unless the file is a socket or a block or character 142 * device resident on the file system. 143 */ 144 if ((vp->v_mount->m_flag & M_RDONLY) && vp->v_type != VCHR && 145 vp->v_type != VBLK && vp->v_type != VSOCK) 146 return (EROFS); 147 /* 148 * If there's shared text associated with 149 * the vnode, try to free it up once. If 150 * we fail, we can't allow writing. 151 */ 152 if (vp->v_flag & VTEXT) 153 xrele(vp); 154 if (vp->v_flag & VTEXT) 155 return (ETXTBSY); 156 return (0); 157 } 158 159 /* 160 * Vnode version of rdwri() for calls on file systems. 161 */ 162 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 163 enum uio_rw rw; 164 struct vnode *vp; 165 caddr_t base; 166 int len; 167 off_t offset; 168 enum uio_seg segflg; 169 int ioflg; 170 struct ucred *cred; 171 int *aresid; 172 { 173 struct uio auio; 174 struct iovec aiov; 175 int error; 176 177 if ((ioflg & IO_NODELOCKED) == 0) 178 VOP_LOCK(vp); 179 auio.uio_iov = &aiov; 180 auio.uio_iovcnt = 1; 181 aiov.iov_base = base; 182 aiov.iov_len = len; 183 auio.uio_resid = len; 184 auio.uio_offset = offset; 185 auio.uio_segflg = segflg; 186 auio.uio_rw = rw; 187 if (rw == UIO_READ) 188 error = VOP_READ(vp, &auio, ioflg, cred); 189 else 190 error = VOP_WRITE(vp, &auio, ioflg, cred); 191 if (aresid) 192 *aresid = auio.uio_resid; 193 else 194 if (auio.uio_resid && error == 0) 195 error = EIO; 196 if ((ioflg & IO_NODELOCKED) == 0) 197 VOP_UNLOCK(vp); 198 return (error); 199 } 200 201 vn_read(fp, uio, cred) 202 struct file *fp; 203 struct uio *uio; 204 struct ucred *cred; 205 { 206 register struct vnode *vp = (struct vnode *)fp->f_data; 207 int count, error; 208 209 VOP_LOCK(vp); 210 uio->uio_offset = fp->f_offset; 211 count = uio->uio_resid; 212 error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred); 213 fp->f_offset += count - uio->uio_resid; 214 VOP_UNLOCK(vp); 215 return (error); 216 } 217 218 vn_write(fp, uio, cred) 219 struct file *fp; 220 struct uio *uio; 221 struct ucred *cred; 222 { 223 register struct vnode *vp = (struct vnode *)fp->f_data; 224 int count, error, ioflag = 0; 225 226 if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 227 ioflag |= IO_APPEND; 228 if (fp->f_flag & FNDELAY) 229 ioflag |= IO_NDELAY; 230 VOP_LOCK(vp); 231 uio->uio_offset = fp->f_offset; 232 count = uio->uio_resid; 233 error = VOP_WRITE(vp, uio, ioflag, cred); 234 if (ioflag & IO_APPEND) 235 fp->f_offset = uio->uio_offset; 236 else 237 fp->f_offset += count - uio->uio_resid; 238 VOP_UNLOCK(vp); 239 return (error); 240 } 241 242 /* 243 * Get stat info for a vnode. 244 */ 245 vn_stat(vp, sb) 246 struct vnode *vp; 247 register struct stat *sb; 248 { 249 struct vattr vattr; 250 register struct vattr *vap; 251 int error; 252 u_short mode; 253 254 vap = &vattr; 255 error = VOP_GETATTR(vp, vap, u.u_cred); 256 if (error) 257 return (error); 258 /* 259 * Copy from vattr table 260 */ 261 sb->st_dev = vap->va_fsid; 262 sb->st_ino = vap->va_fileid; 263 mode = vap->va_mode; 264 switch (vp->v_type) { 265 case VREG: 266 mode |= S_IFREG; 267 break; 268 case VDIR: 269 mode |= S_IFDIR; 270 break; 271 case VBLK: 272 mode |= S_IFBLK; 273 break; 274 case VCHR: 275 mode |= S_IFCHR; 276 break; 277 case VLNK: 278 mode |= S_IFLNK; 279 break; 280 case VSOCK: 281 mode |= S_IFSOCK; 282 break; 283 default: 284 return (EBADF); 285 }; 286 sb->st_mode = mode; 287 sb->st_nlink = vap->va_nlink; 288 sb->st_uid = vap->va_uid; 289 sb->st_gid = vap->va_gid; 290 sb->st_rdev = vap->va_rdev; 291 sb->st_size = vap->va_size; 292 sb->st_atime = vap->va_atime.tv_sec; 293 sb->st_spare1 = 0; 294 sb->st_mtime = vap->va_mtime.tv_sec; 295 sb->st_spare2 = 0; 296 sb->st_ctime = vap->va_ctime.tv_sec; 297 sb->st_spare3 = 0; 298 sb->st_blksize = vap->va_blocksize; 299 sb->st_flags = vap->va_flags; 300 sb->st_gen = vap->va_gen; 301 sb->st_blocks = vap->va_bytes / S_BLKSIZE; 302 return (0); 303 } 304 305 /* 306 * Vnode ioctl call 307 */ 308 vn_ioctl(fp, com, data) 309 struct file *fp; 310 int com; 311 caddr_t data; 312 { 313 register struct vnode *vp = ((struct vnode *)fp->f_data); 314 struct vattr vattr; 315 int error; 316 317 switch (vp->v_type) { 318 319 case VREG: 320 case VDIR: 321 if (com == FIONREAD) { 322 if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) 323 return (error); 324 *(off_t *)data = vattr.va_size - fp->f_offset; 325 return (0); 326 } 327 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 328 return (0); /* XXX */ 329 /* fall into ... */ 330 331 default: 332 return (ENOTTY); 333 334 case VCHR: 335 case VBLK: 336 u.u_r.r_val1 = 0; 337 if (setjmp(&u.u_qsave)) { 338 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 339 return(EINTR); 340 u.u_eosys = RESTARTSYS; 341 return (0); 342 } 343 error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred); 344 if (error == 0 && com == TIOCSCTTY) { 345 u.u_procp->p_session->s_ttyvp = vp; 346 VREF(vp); 347 } 348 return (error); 349 } 350 } 351 352 /* 353 * Vnode select call 354 */ 355 vn_select(fp, which) 356 struct file *fp; 357 int which; 358 { 359 return(VOP_SELECT(((struct vnode *)fp->f_data), which, u.u_cred)); 360 } 361 362 /* 363 * Vnode close call 364 */ 365 vn_close(fp) 366 register struct file *fp; 367 { 368 struct vnode *vp = ((struct vnode *)fp->f_data); 369 int error; 370 371 if (fp->f_flag & (FSHLOCK|FEXLOCK)) 372 vn_unlock(fp, FSHLOCK|FEXLOCK); 373 /* 374 * Must delete vnode reference from this file entry 375 * before VOP_CLOSE, so that only other references 376 * will prevent close. 377 */ 378 fp->f_data = (caddr_t) 0; 379 error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); 380 vrele(vp); 381 return (error); 382 } 383 384 /* 385 * Place an advisory lock on a vnode. 386 * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries 387 */ 388 vn_lock(fp, cmd) 389 register struct file *fp; 390 int cmd; 391 { 392 register int priority = PLOCK; 393 register struct vnode *vp = (struct vnode *)fp->f_data; 394 395 if ((cmd & LOCK_EX) == 0) 396 priority += 4; 397 if (setjmp(&u.u_qsave)) { 398 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 399 return(EINTR); 400 u.u_eosys = RESTARTSYS; 401 return (0); 402 } 403 /* 404 * If there's a exclusive lock currently applied 405 * to the file, then we've gotta wait for the 406 * lock with everyone else. 407 */ 408 again: 409 while (vp->v_flag & VEXLOCK) { 410 /* 411 * If we're holding an exclusive 412 * lock, then release it. 413 */ 414 if (fp->f_flag & FEXLOCK) { 415 vn_unlock(fp, FEXLOCK); 416 continue; 417 } 418 if (cmd & LOCK_NB) 419 return (EWOULDBLOCK); 420 vp->v_flag |= VLWAIT; 421 tsleep((caddr_t)&vp->v_exlockc, priority, SLP_EXLCK, 0); 422 } 423 if ((cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { 424 /* 425 * Must wait for any shared locks to finish 426 * before we try to apply a exclusive lock. 427 * 428 * If we're holding a shared 429 * lock, then release it. 430 */ 431 if (fp->f_flag & FSHLOCK) { 432 vn_unlock(fp, FSHLOCK); 433 goto again; 434 } 435 if (cmd & LOCK_NB) 436 return (EWOULDBLOCK); 437 vp->v_flag |= VLWAIT; 438 tsleep((caddr_t)&vp->v_shlockc, PLOCK, SLP_SHLCK, 0); 439 goto again; 440 } 441 if (fp->f_flag & FEXLOCK) 442 panic("vn_lock"); 443 if (cmd & LOCK_EX) { 444 cmd &= ~LOCK_SH; 445 vp->v_exlockc++; 446 vp->v_flag |= VEXLOCK; 447 fp->f_flag |= FEXLOCK; 448 } 449 if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { 450 vp->v_shlockc++; 451 vp->v_flag |= VSHLOCK; 452 fp->f_flag |= FSHLOCK; 453 } 454 return (0); 455 } 456 457 /* 458 * Unlock a file. 459 */ 460 vn_unlock(fp, kind) 461 register struct file *fp; 462 int kind; 463 { 464 register struct vnode *vp = (struct vnode *)fp->f_data; 465 int flags; 466 467 kind &= fp->f_flag; 468 if (vp == NULL || kind == 0) 469 return; 470 flags = vp->v_flag; 471 if (kind & FSHLOCK) { 472 if ((flags & VSHLOCK) == 0) 473 panic("vn_unlock: SHLOCK"); 474 if (--vp->v_shlockc == 0) { 475 vp->v_flag &= ~VSHLOCK; 476 if (flags & VLWAIT) 477 wakeup((caddr_t)&vp->v_shlockc); 478 } 479 fp->f_flag &= ~FSHLOCK; 480 } 481 if (kind & FEXLOCK) { 482 if ((flags & VEXLOCK) == 0) 483 panic("vn_unlock: EXLOCK"); 484 if (--vp->v_exlockc == 0) { 485 vp->v_flag &= ~(VEXLOCK|VLWAIT); 486 if (flags & VLWAIT) 487 wakeup((caddr_t)&vp->v_exlockc); 488 } 489 fp->f_flag &= ~FEXLOCK; 490 } 491 } 492 493 /* 494 * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 495 * - look up fsid in mount list (if not found ret error) 496 * - get vp by calling VFS_FHTOVP() macro 497 * - if lockflag lock it with VOP_LOCK() 498 */ 499 vn_fhtovp(fhp, lockflag, vpp) 500 fhandle_t *fhp; 501 int lockflag; 502 struct vnode **vpp; 503 { 504 register struct mount *mp; 505 506 if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 507 return (ESTALE); 508 if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 509 return (ESTALE); 510 if (!lockflag) 511 VOP_UNLOCK(*vpp); 512 return (0); 513 } 514 515 /* 516 * Noop 517 */ 518 vfs_noop() 519 { 520 521 return (ENXIO); 522 } 523 524 /* 525 * Null op 526 */ 527 vfs_nullop() 528 { 529 530 return (0); 531 } 532