The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 5034628c3495cec935394cae9af5d0b6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.