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/gnu/fs/reiserfs/reiserfs_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 2000 Hans Reiser
    3  * See README for licensing and copyright details
    4  * 
    5  * Ported to FreeBSD by Jean-Sébastien Pédron <jspedron@club-internet.fr>
    6  * 
    7  * $FreeBSD$
    8  */
    9 
   10 #include <gnu/fs/reiserfs/reiserfs_fs.h>
   11 
   12 static vop_access_t     reiserfs_access;
   13 static vop_bmap_t       reiserfs_bmap;
   14 static vop_getattr_t    reiserfs_getattr;
   15 static vop_open_t       reiserfs_open;
   16 static vop_pathconf_t   reiserfs_pathconf;
   17 static vop_readlink_t   reiserfs_readlink;
   18 static vop_strategy_t   reiserfs_strategy;
   19 static vop_vptofh_t     reiserfs_vptofh;
   20 
   21 /* Global vfs data structures for ReiserFS */
   22 struct vop_vector reiserfs_vnodeops = {
   23         .vop_default      = &default_vnodeops,
   24 
   25         .vop_access       = reiserfs_access,
   26         .vop_bmap         = reiserfs_bmap,
   27         .vop_cachedlookup = reiserfs_lookup,
   28         .vop_getattr      = reiserfs_getattr,
   29         .vop_inactive     = reiserfs_inactive,
   30         .vop_lookup       = vfs_cache_lookup,
   31         .vop_open         = reiserfs_open,
   32         .vop_reclaim      = reiserfs_reclaim,
   33         .vop_read         = reiserfs_read,
   34         .vop_readdir      = reiserfs_readdir,
   35         .vop_readlink     = reiserfs_readlink,
   36         .vop_pathconf     = reiserfs_pathconf,
   37         .vop_strategy     = reiserfs_strategy,
   38         .vop_vptofh       = reiserfs_vptofh,
   39 };
   40 
   41 struct vop_vector reiserfs_specops = {
   42         .vop_default  = &default_vnodeops,
   43 
   44         .vop_access   = reiserfs_access,
   45         .vop_getattr  = reiserfs_getattr,
   46         .vop_inactive = reiserfs_inactive,
   47         .vop_reclaim  = reiserfs_reclaim,
   48 };
   49 
   50 /* -------------------------------------------------------------------
   51  * vnode operations
   52  * -------------------------------------------------------------------*/
   53 
   54 static int
   55 reiserfs_access(struct vop_access_args *ap)
   56 {
   57         int error;
   58         struct vnode *vp = ap->a_vp;
   59         struct reiserfs_node *ip = VTOI(vp);
   60         accmode_t accmode = ap->a_accmode;
   61 
   62         /*
   63          * Disallow write attempts on read-only file systems; unless the file
   64          * is a socket, fifo, or a block or character device resident on the
   65          * file system.
   66          */
   67         if (accmode & VWRITE) {
   68                 switch (vp->v_type) {
   69                 case VDIR:
   70                 case VLNK:
   71                 case VREG:
   72                         if (vp->v_mount->mnt_flag & MNT_RDONLY) {
   73                                 reiserfs_log(LOG_DEBUG,
   74                                     "no write access (read-only fs)\n");
   75                                 return (EROFS);
   76                         }
   77                         break;
   78                 default:
   79                         break;
   80                 }
   81         }
   82 
   83         /* If immutable bit set, nobody gets to write it. */
   84         if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) {
   85                 reiserfs_log(LOG_DEBUG, "no write access (immutable)\n");
   86                 return (EPERM);
   87         }
   88 
   89         error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
   90             ap->a_accmode, ap->a_cred, NULL);
   91         return (error);
   92 }
   93 
   94 static int
   95 reiserfs_getattr(struct vop_getattr_args *ap)
   96 {
   97         struct vnode *vp         = ap->a_vp;
   98         struct vattr *vap        = ap->a_vap;
   99         struct reiserfs_node *ip = VTOI(vp);
  100 
  101         vap->va_fsid      = dev2udev(ip->i_dev);
  102         vap->va_fileid    = ip->i_number;
  103         vap->va_mode      = ip->i_mode & ~S_IFMT;
  104         vap->va_nlink     = ip->i_nlink;
  105         vap->va_uid       = ip->i_uid;
  106         vap->va_gid       = ip->i_gid;
  107         //XXX vap->va_rdev      = ip->i_rdev;
  108         vap->va_size      = ip->i_size;
  109         vap->va_atime     = ip->i_atime;
  110         vap->va_mtime     = ip->i_mtime;
  111         vap->va_ctime     = ip->i_ctime;
  112         vap->va_flags     = ip->i_flags;
  113         vap->va_gen       = ip->i_generation;
  114         vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
  115         vap->va_bytes     = dbtob((u_quad_t)ip->i_blocks);
  116         vap->va_type      = vp->v_type;
  117         //XXX vap->va_filerev   = ip->i_modrev;
  118 
  119         return (0);
  120 }
  121 
  122 /* Return POSIX pathconf information applicable to ReiserFS filesystems */
  123 static int
  124 reiserfs_pathconf(struct vop_pathconf_args *ap)
  125 {
  126         switch (ap->a_name) {
  127         case _PC_LINK_MAX:
  128                 *ap->a_retval = REISERFS_LINK_MAX;
  129                 return (0);
  130         case _PC_NAME_MAX:
  131                 *ap->a_retval =
  132                     REISERFS_MAX_NAME(VTOI(ap->a_vp)->i_reiserfs->s_blocksize);
  133                 return (0);
  134         case _PC_PATH_MAX:
  135                 *ap->a_retval = PATH_MAX;
  136                 return (0);
  137         case _PC_PIPE_BUF:
  138                 *ap->a_retval = PIPE_BUF;
  139                 return (0);
  140         case _PC_CHOWN_RESTRICTED:
  141                 *ap->a_retval = 1;
  142                 return (0);
  143         case _PC_NO_TRUNC:
  144                 *ap->a_retval = 1;
  145                 return (0);
  146         default:
  147                 return (EINVAL);
  148         }
  149 }
  150 
  151 static int
  152 reiserfs_open(struct vop_open_args *ap)
  153 {
  154         /* Files marked append-only must be opened for appending. */
  155         if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
  156             (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
  157                 return (EPERM);
  158 
  159         vnode_create_vobject(ap->a_vp, VTOI(ap->a_vp)->i_size, ap->a_td);
  160 
  161         return (0);
  162 }
  163 
  164 /* Return target name of a symbolic link */
  165 static int
  166 reiserfs_readlink(struct vop_readlink_args *ap)
  167 {
  168         struct vnode *vp = ap->a_vp;
  169 
  170         reiserfs_log(LOG_DEBUG, "redirect to VOP_READ()\n");
  171         return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
  172 }
  173 
  174 /* Bmap converts the logical block number of a file to its physical
  175  * block number on the disk. */
  176 static int
  177 reiserfs_bmap(ap)
  178         struct vop_bmap_args /* {
  179                                 struct vnode *a_vp;
  180                                 daddr_t a_bn;
  181                                 struct bufobj **a_bop;
  182                                 daddr_t *a_bnp;
  183                                 int *a_runp;
  184                                 int *a_runb;
  185                                 } */ *ap;
  186 {
  187         daddr_t blkno;
  188         struct buf *bp;
  189         struct cpu_key key;
  190         struct item_head *ih;
  191 
  192         struct vnode *vp = ap->a_vp;
  193         struct reiserfs_node *ip = VTOI(vp);
  194         struct reiserfs_sb_info *sbi = ip->i_reiserfs;
  195         INITIALIZE_PATH(path);
  196 
  197         /* Prepare the key to look for the 'block'-th block of file
  198          * (XXX we suppose that statfs.f_iosize == sbi->s_blocksize) */
  199         make_cpu_key(&key, ip, (off_t)ap->a_bn * sbi->s_blocksize + 1,
  200             TYPE_ANY, 3);
  201 
  202         /* Search item */
  203         if (search_for_position_by_key(sbi, &key, &path) != POSITION_FOUND) {
  204                 reiserfs_log(LOG_DEBUG, "position not found\n");
  205                 pathrelse(&path);
  206                 return (ENOENT);
  207         }
  208 
  209         bp = get_last_bp(&path);
  210         ih = get_ih(&path);
  211 
  212         if (is_indirect_le_ih(ih)) {
  213                 /* Indirect item can be read by the underlying layer, instead of
  214                  * VOP_STRATEGY. */
  215                 int i;
  216                 uint32_t *ind_item = (uint32_t *)B_I_PITEM(bp, ih);
  217                 reiserfs_log(LOG_DEBUG, "found an INDIRECT item\n");
  218                 blkno = get_block_num(ind_item, path.pos_in_item);
  219 
  220                 /* Read-ahead */
  221                 if (ap->a_runb) {
  222                         uint32_t count = 0;
  223                         for (i = path.pos_in_item - 1; i >= 0; --i) {
  224                                 if ((blkno - get_block_num(ind_item, i)) !=
  225                                     count + 1)
  226                                         break;
  227                                 ++count;
  228                         }
  229 
  230                         /*
  231                          * This count isn't expressed in DEV_BSIZE base but
  232                          * in fs' own block base
  233                          * (see sys/vm/vnode_pager.c:vnode_pager_addr())
  234                          */
  235                         *ap->a_runb = count;
  236                         reiserfs_log(LOG_DEBUG,
  237                             " read-ahead: %d blocks before\n", *ap->a_runb);
  238                 }
  239                 if (ap->a_runp) {
  240                         uint32_t count = 0;
  241                         /*
  242                          * ih is an uint32_t array, that's why we use
  243                          * its length (in bytes) divided by 4 to know
  244                          * the number of items
  245                          */
  246                         for (i = path.pos_in_item + 1;
  247                             i < ih_item_len(ih) / 4; ++i) {
  248                                 if ((get_block_num(ind_item, i) - blkno) !=
  249                                     count + 1)
  250                                         break;
  251                                 ++count;
  252                         }
  253 
  254                         /*
  255                          * This count isn't expressed in DEV_BSIZE base but
  256                          * in fs' own block base
  257                          * (see sys/vm/vnode_pager.c:vnode_pager_addr()) */
  258                         *ap->a_runp = count;
  259                         reiserfs_log(LOG_DEBUG,
  260                             " read-ahead: %d blocks after\n", *ap->a_runp);
  261                 }
  262 
  263                 /* Indirect items can be read using the device VOP_STRATEGY */
  264                 if (ap->a_bop)
  265                         *ap->a_bop = &VTOI(ap->a_vp)->i_devvp->v_bufobj;
  266 
  267                 /* Convert the block number into DEV_BSIZE base */
  268                 blkno *= btodb(sbi->s_blocksize);
  269         } else {
  270                 /*
  271                  * Direct item are not DEV_BSIZE aligned, VOP_STRATEGY will
  272                  * have to handle this case specifically
  273                  */
  274                 reiserfs_log(LOG_DEBUG, "found a DIRECT item\n");
  275                 blkno = ap->a_bn;
  276 
  277                 if (ap->a_runp)
  278                         *ap->a_runp = 0;
  279                 if (ap->a_runb)
  280                         *ap->a_runb = 0;
  281 
  282                 /* Direct item must be read by reiserfs_strategy */
  283                 if (ap->a_bop)
  284                         *ap->a_bop = &vp->v_bufobj;
  285         }
  286 
  287         if (ap->a_bnp)
  288                 *ap->a_bnp = blkno;
  289 
  290         pathrelse(&path);
  291 
  292         if (ap->a_bnp) {
  293                 reiserfs_log(LOG_DEBUG, "logical block: %ju (%ju),"
  294                     " physical block: %ju (%ju)\n",
  295                     (intmax_t)ap->a_bn,
  296                     (intmax_t)(ap->a_bn / btodb(sbi->s_blocksize)),
  297                     (intmax_t)*ap->a_bnp,
  298                     (intmax_t)(*ap->a_bnp / btodb(sbi->s_blocksize)));
  299         }
  300 
  301         return (0);
  302 }
  303 
  304 /* Does simply the same as reiserfs_read. It's called when reiserfs_bmap find
  305  * an direct item. */
  306 static int
  307 reiserfs_strategy(struct vop_strategy_args /* {
  308                                               struct vnode *a_vp;
  309                                               struct buf *a_bp;
  310                                               } */ *ap)
  311 {
  312         int error;
  313         struct uio auio;
  314         struct iovec aiov;
  315         struct reiserfs_node *ip;
  316         struct buf *bp = ap->a_bp;
  317         struct vnode *vp = ap->a_vp;
  318 
  319         reiserfs_log(LOG_DEBUG, "logical block: %ju,"
  320             " physical block: %ju\n", (intmax_t)bp->b_lblkno,
  321             (intmax_t)bp->b_blkno);
  322 
  323         ip = VTOI(vp);
  324 
  325         if (bp->b_iocmd == BIO_READ) {
  326                 /* Prepare the uio structure */
  327                 reiserfs_log(LOG_DEBUG, "prepare uio structure\n");
  328                 aiov.iov_base = bp->b_data;
  329                 aiov.iov_len  = MIN(bp->b_bcount, ip->i_size);
  330                 reiserfs_log(LOG_DEBUG, "  vector length: %ju\n",
  331                     (intmax_t)aiov.iov_len);
  332 
  333                 auio.uio_iov    = &aiov;
  334                 auio.uio_iovcnt = 1;
  335                 auio.uio_offset = 0;
  336                 auio.uio_rw     = UIO_READ;
  337                 auio.uio_segflg = UIO_SYSSPACE;
  338                 auio.uio_td     = curthread;
  339                 auio.uio_resid  = bp->b_bcount;
  340                 reiserfs_log(LOG_DEBUG, "  buffer length: %u\n",
  341                     auio.uio_resid);
  342 
  343                 reiserfs_log(LOG_DEBUG, "reading block #%ju\n",
  344                     (intmax_t)bp->b_blkno);
  345                 error = reiserfs_get_block(ip, bp->b_blkno, 0, &auio);
  346         } else {
  347                 /* No write support yet */
  348                 error = (EOPNOTSUPP);
  349                 bp->b_error    = error;
  350                 bp->b_ioflags |= BIO_ERROR;
  351         }
  352 
  353         if (error) {
  354                 bp->b_ioflags |= BIO_ERROR;
  355                 bp->b_error = error;
  356         }
  357 
  358         bufdone(bp);
  359         return (0);
  360 }
  361 
  362 /*
  363  * Vnode pointer to File handle
  364  */
  365 static int
  366 reiserfs_vptofh(struct vop_vptofh_args /* {
  367                                           struct vnode *a_vp;
  368                                           struct fid *a_fhp;
  369                                           } */ *ap)
  370 {
  371         struct rfid *rfhp;
  372         struct reiserfs_node *ip;
  373 
  374         ip = VTOI(ap->a_vp);
  375         reiserfs_log(LOG_DEBUG,
  376             "fill *fhp with inode (dirid=%d, objectid=%d)\n",
  377             ip->i_ino, ip->i_number);
  378 
  379         rfhp = (struct rfid *)ap->a_fhp;
  380         rfhp->rfid_len      = sizeof(struct rfid);
  381         rfhp->rfid_dirid    = ip->i_ino;
  382         rfhp->rfid_objectid = ip->i_number;
  383         rfhp->rfid_gen      = ip->i_generation;
  384 
  385         reiserfs_log(LOG_DEBUG, "return it\n");
  386         return (0);
  387 }

Cache object: e5bd86f48f851e5898c91dffd878c16f


[ 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.