root/kern/vfs_vnops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vn_open
  2. vn_writechk
  3. vn_marktext
  4. vn_close
  5. vn_rdwr
  6. vn_read
  7. vn_write
  8. vn_statfile
  9. vn_stat
  10. vn_ioctl
  11. vn_poll
  12. vn_lock
  13. vn_closefile
  14. vn_kqfilter
  15. vn_isunder

    1 /*      $OpenBSD: vfs_vnops.c,v 1.58 2007/06/14 20:36:34 otto Exp $     */
    2 /*      $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $  */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1989, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  * (c) UNIX System Laboratories, Inc.
    8  * All or some portions of this file are derived from material licensed
    9  * to the University of California by American Telephone and Telegraph
   10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   11  * the permission of UNIX System Laboratories, Inc.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)vfs_vnops.c 8.5 (Berkeley) 12/8/94
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/kernel.h>
   43 #include <sys/malloc.h>
   44 #include <sys/file.h>
   45 #include <sys/stat.h>
   46 #include <sys/buf.h>
   47 #include <sys/proc.h>
   48 #include <sys/mount.h>
   49 #include <sys/namei.h>
   50 #include <sys/vnode.h>
   51 #include <sys/ioctl.h>
   52 #include <sys/tty.h>
   53 #include <sys/cdio.h>
   54 #include <sys/poll.h>
   55 
   56 #include <uvm/uvm_extern.h>
   57 #include <miscfs/specfs/specdev.h>
   58 
   59 int vn_read(struct file *, off_t *, struct uio *, struct ucred *);
   60 int vn_write(struct file *, off_t *, struct uio *, struct ucred *);
   61 int vn_poll(struct file *, int, struct proc *);
   62 int vn_kqfilter(struct file *, struct knote *);
   63 int vn_closefile(struct file *, struct proc *);
   64 
   65 struct  fileops vnops =
   66         { vn_read, vn_write, vn_ioctl, vn_poll, vn_kqfilter, vn_statfile,
   67           vn_closefile };
   68 
   69 /*
   70  * Common code for vnode open operations.
   71  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
   72  */
   73 int
   74 vn_open(struct nameidata *ndp, int fmode, int cmode)
   75 {
   76         struct vnode *vp;
   77         struct proc *p = ndp->ni_cnd.cn_proc;
   78         struct ucred *cred = p->p_ucred;
   79         struct vattr va;
   80         int error;
   81 
   82         if ((fmode & (FREAD|FWRITE)) == 0)
   83                 return (EINVAL);
   84         if ((fmode & (O_TRUNC | FWRITE)) == O_TRUNC)
   85                 return (EINVAL);
   86         if (fmode & O_CREAT) {
   87                 ndp->ni_cnd.cn_nameiop = CREATE;
   88                 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
   89                 if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0)
   90                         ndp->ni_cnd.cn_flags |= FOLLOW;
   91                 if ((error = namei(ndp)) != 0)
   92                         return (error);
   93 
   94                 if (ndp->ni_vp == NULL) {
   95                         VATTR_NULL(&va);
   96                         va.va_type = VREG;
   97                         va.va_mode = cmode;
   98                         error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
   99                                            &ndp->ni_cnd, &va);
  100                         if (error)
  101                                 return (error);
  102                         fmode &= ~O_TRUNC;
  103                         vp = ndp->ni_vp;
  104                 } else {
  105                         VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
  106                         if (ndp->ni_dvp == ndp->ni_vp)
  107                                 vrele(ndp->ni_dvp);
  108                         else
  109                                 vput(ndp->ni_dvp);
  110                         ndp->ni_dvp = NULL;
  111                         vp = ndp->ni_vp;
  112                         if (fmode & O_EXCL) {
  113                                 error = EEXIST;
  114                                 goto bad;
  115                         }
  116                         fmode &= ~O_CREAT;
  117                 }
  118         } else {
  119                 ndp->ni_cnd.cn_nameiop = LOOKUP;
  120                 ndp->ni_cnd.cn_flags =
  121                     ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF;
  122                 if ((error = namei(ndp)) != 0)
  123                         return (error);
  124                 vp = ndp->ni_vp;
  125         }
  126         if (vp->v_type == VSOCK) {
  127                 error = EOPNOTSUPP;
  128                 goto bad;
  129         }
  130         if (vp->v_type == VLNK) {
  131                 error = EMLINK;
  132                 goto bad;
  133         }
  134         if ((fmode & O_CREAT) == 0) {
  135                 if (fmode & FREAD) {
  136                         if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
  137                                 goto bad;
  138                 }
  139                 if (fmode & FWRITE) {
  140                         if (vp->v_type == VDIR) {
  141                                 error = EISDIR;
  142                                 goto bad;
  143                         }
  144                         if ((error = vn_writechk(vp)) != 0 ||
  145                             (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
  146                                 goto bad;
  147                 }
  148         }
  149         if ((fmode & O_TRUNC) && vp->v_type == VREG) {
  150                 VATTR_NULL(&va);
  151                 va.va_size = 0;
  152                 if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
  153                         goto bad;
  154         }
  155         if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0)
  156                 goto bad;
  157 
  158         if (vp->v_flag & VCLONED) {
  159                 struct cloneinfo *cip = (struct cloneinfo *) vp->v_data;
  160 
  161                 vp->v_flag &= ~VCLONED;
  162                 ndp->ni_vp = cip->ci_vp; /* return cloned vnode */
  163                 vp->v_data = cip->ci_data; /* restore v_data */
  164                 VOP_UNLOCK(vp, 0, p); /* keep a reference */
  165                 vp = ndp->ni_vp; /* for the increment below */
  166 
  167                 free(cip, M_TEMP);
  168         }
  169 
  170         if (fmode & FWRITE)
  171                 vp->v_writecount++;
  172         return (0);
  173 bad:
  174         vput(vp);
  175         return (error);
  176 }
  177 
  178 /*
  179  * Check for write permissions on the specified vnode.
  180  * Prototype text segments cannot be written.
  181  */
  182 int
  183 vn_writechk(struct vnode *vp)
  184 {
  185         /*
  186          * Disallow write attempts on read-only file systems;
  187          * unless the file is a socket or a block or character
  188          * device resident on the file system.
  189          */
  190         if (vp->v_mount->mnt_flag & MNT_RDONLY) {
  191                 switch (vp->v_type) {
  192                 case VREG:
  193                 case VDIR:
  194                 case VLNK:
  195                         return (EROFS);
  196                 case VNON:
  197                 case VCHR:
  198                 case VSOCK:
  199                 case VFIFO:
  200                 case VBAD:
  201                 case VBLK:
  202                         break;
  203                 }
  204         }
  205         /*
  206          * If there's shared text associated with
  207          * the vnode, try to free it up once.  If
  208          * we fail, we can't allow writing.
  209          */
  210         if ((vp->v_flag & VTEXT) && !uvm_vnp_uncache(vp))
  211                 return (ETXTBSY);
  212 
  213         return (0);
  214 }
  215 
  216 /*
  217  * Mark a vnode as being the text image of a running process.
  218  */
  219 void
  220 vn_marktext(struct vnode *vp)
  221 {
  222         vp->v_flag |= VTEXT;
  223 }
  224 
  225 /*
  226  * Vnode close call
  227  */
  228 int
  229 vn_close(struct vnode *vp, int flags, struct ucred *cred, struct proc *p)
  230 {
  231         int error;
  232 
  233         if (flags & FWRITE)
  234                 vp->v_writecount--;
  235         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  236         error = VOP_CLOSE(vp, flags, cred, p);
  237         vput(vp);
  238         return (error);
  239 }
  240 
  241 /*
  242  * Package up an I/O request on a vnode into a uio and do it.
  243  */
  244 int
  245 vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset,
  246     enum uio_seg segflg, int ioflg, struct ucred *cred, size_t *aresid,
  247     struct proc *p)
  248 {
  249         struct uio auio;
  250         struct iovec aiov;
  251         int error;
  252 
  253         if ((ioflg & IO_NODELOCKED) == 0)
  254                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  255         auio.uio_iov = &aiov;
  256         auio.uio_iovcnt = 1;
  257         aiov.iov_base = base;
  258         aiov.iov_len = len;
  259         auio.uio_resid = len;
  260         auio.uio_offset = offset;
  261         auio.uio_segflg = segflg;
  262         auio.uio_rw = rw;
  263         auio.uio_procp = p;
  264         if (rw == UIO_READ) {
  265                 error = VOP_READ(vp, &auio, ioflg, cred);
  266         } else {
  267                 error = VOP_WRITE(vp, &auio, ioflg, cred);
  268         }
  269         if (aresid)
  270                 *aresid = auio.uio_resid;
  271         else
  272                 if (auio.uio_resid && error == 0)
  273                         error = EIO;
  274         if ((ioflg & IO_NODELOCKED) == 0)
  275                 VOP_UNLOCK(vp, 0, p);
  276         return (error);
  277 }
  278 
  279 /*
  280  * File table vnode read routine.
  281  */
  282 int
  283 vn_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
  284 {
  285         struct vnode *vp = (struct vnode *)fp->f_data;
  286         int error = 0;
  287         size_t count;
  288         struct proc *p = uio->uio_procp;
  289 
  290         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  291         uio->uio_offset = *poff;
  292         count = uio->uio_resid;
  293         if (vp->v_type != VDIR)
  294                 error = VOP_READ(vp, uio,
  295                     (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred);
  296         *poff += count - uio->uio_resid;
  297         VOP_UNLOCK(vp, 0, p);
  298         return (error);
  299 }
  300 
  301 /*
  302  * File table vnode write routine.
  303  */
  304 int
  305 vn_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
  306 {
  307         struct vnode *vp = (struct vnode *)fp->f_data;
  308         struct proc *p = uio->uio_procp;
  309         int error, ioflag = IO_UNIT;
  310         size_t count;
  311 
  312         if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
  313                 ioflag |= IO_APPEND;
  314         if (fp->f_flag & FNONBLOCK)
  315                 ioflag |= IO_NDELAY;
  316         if ((fp->f_flag & FFSYNC) ||
  317             (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
  318                 ioflag |= IO_SYNC;
  319         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  320         uio->uio_offset = *poff;
  321         count = uio->uio_resid;
  322         error = VOP_WRITE(vp, uio, ioflag, cred);
  323         if (ioflag & IO_APPEND)
  324                 *poff = uio->uio_offset;
  325         else
  326                 *poff += count - uio->uio_resid;
  327         VOP_UNLOCK(vp, 0, p);
  328         return (error);
  329 }
  330 
  331 /*
  332  * File table wrapper for vn_stat
  333  */
  334 int
  335 vn_statfile(struct file *fp, struct stat *sb, struct proc *p)
  336 {
  337         struct vnode *vp = (struct vnode *)fp->f_data;
  338         return vn_stat(vp, sb, p);
  339 }
  340 
  341 /*
  342  * vnode stat routine.
  343  */
  344 int
  345 vn_stat(struct vnode *vp, struct stat *sb, struct proc *p)
  346 {
  347         struct vattr va;
  348         int error;
  349         mode_t mode;
  350 
  351         error = VOP_GETATTR(vp, &va, p->p_ucred, p);
  352         if (error)
  353                 return (error);
  354         /*
  355          * Copy from vattr table
  356          */
  357         sb->st_dev = va.va_fsid;
  358         sb->st_ino = va.va_fileid;
  359         mode = va.va_mode;
  360         switch (vp->v_type) {
  361         case VREG:
  362                 mode |= S_IFREG;
  363                 break;
  364         case VDIR:
  365                 mode |= S_IFDIR;
  366                 break;
  367         case VBLK:
  368                 mode |= S_IFBLK;
  369                 break;
  370         case VCHR:
  371                 mode |= S_IFCHR;
  372                 break;
  373         case VLNK:
  374                 mode |= S_IFLNK;
  375                 break;
  376         case VSOCK:
  377                 mode |= S_IFSOCK;
  378                 break;
  379         case VFIFO:
  380                 mode |= S_IFIFO;
  381                 break;
  382         default:
  383                 return (EBADF);
  384         }
  385         sb->st_mode = mode;
  386         sb->st_nlink = va.va_nlink;
  387         sb->st_uid = va.va_uid;
  388         sb->st_gid = va.va_gid;
  389         sb->st_rdev = va.va_rdev;
  390         sb->st_size = va.va_size;
  391         sb->st_atimespec = va.va_atime;
  392         sb->st_mtimespec = va.va_mtime;
  393         sb->st_ctimespec = va.va_ctime;
  394         sb->st_blksize = va.va_blocksize;
  395         sb->st_flags = va.va_flags;
  396         sb->st_gen = va.va_gen;
  397         sb->st_blocks = va.va_bytes / S_BLKSIZE;
  398         return (0);
  399 }
  400 
  401 /*
  402  * File table vnode ioctl routine.
  403  */
  404 int
  405 vn_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
  406 {
  407         struct vnode *vp = ((struct vnode *)fp->f_data);
  408         struct vattr vattr;
  409         int error;
  410 
  411         switch (vp->v_type) {
  412 
  413         case VREG:
  414         case VDIR:
  415                 if (com == FIONREAD) {
  416                         error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
  417                         if (error)
  418                                 return (error);
  419                         *(int *)data = vattr.va_size - fp->f_offset;
  420                         return (0);
  421                 }
  422                 if (com == FIONBIO || com == FIOASYNC)  /* XXX */
  423                         return (0);                     /* XXX */
  424                 /* FALLTHROUGH */
  425         default:
  426                 return (ENOTTY);
  427                 
  428         case VFIFO:
  429         case VCHR:
  430         case VBLK:
  431                 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
  432                 if (error == 0 && com == TIOCSCTTY) {
  433                         if (p->p_session->s_ttyvp)
  434                                 vrele(p->p_session->s_ttyvp);
  435                         p->p_session->s_ttyvp = vp;
  436                         VREF(vp);
  437                 }
  438                 return (error);
  439         }
  440 }
  441 
  442 /*
  443  * File table vnode poll routine.
  444  */
  445 int
  446 vn_poll(struct file *fp, int events, struct proc *p)
  447 {
  448         return (VOP_POLL(((struct vnode *)fp->f_data), events, p));
  449 }
  450 
  451 /*
  452  * Check that the vnode is still valid, and if so
  453  * acquire requested lock.
  454  */
  455 int
  456 vn_lock(struct vnode *vp, int flags, struct proc *p)
  457 {
  458         int error;
  459 
  460         if ((flags & LK_RECURSEFAIL) == 0)
  461                 flags |= LK_CANRECURSE;
  462         
  463         do {
  464                 if (vp->v_flag & VXLOCK) {
  465                         vp->v_flag |= VXWANT;
  466                         tsleep(vp, PINOD, "vn_lock", 0);
  467                         error = ENOENT;
  468                 } else {
  469                         error = VOP_LOCK(vp, flags, p);
  470                         if (error == 0)
  471                                 return (error);
  472                 }
  473         } while (flags & LK_RETRY);
  474         return (error);
  475 }
  476 
  477 /*
  478  * File table vnode close routine.
  479  */
  480 int
  481 vn_closefile(struct file *fp, struct proc *p)
  482 {
  483         return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
  484                 fp->f_cred, p));
  485 }
  486 
  487 int
  488 vn_kqfilter(struct file *fp, struct knote *kn)
  489 {
  490         return (VOP_KQFILTER(((struct vnode *)fp->f_data), kn));
  491 }
  492 
  493 /*
  494  * Common code for vnode access operations.
  495  */
  496 
  497 /* Check if a directory can be found inside another in the hierarchy */
  498 int
  499 vn_isunder(struct vnode *lvp, struct vnode *rvp, struct proc *p)
  500 {
  501         int error;
  502 
  503         error = vfs_getcwd_common(lvp, rvp, NULL, NULL, MAXPATHLEN/2, 0, p);
  504 
  505         if (!error)
  506                 return (1);
  507 
  508         return (0);
  509 }

/* [<][>][^][v][top][bottom][index][help] */