root/xfs/xfs_vnodeops-common.c

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

DEFINITIONS

This source file includes following definitions.
  1. xfs_handle_stale
  2. xfs_open_valid
  3. xfs_attr_valid
  4. xfs_data_valid
  5. xfs_open_common
  6. do_fsync
  7. xfs_fsync_common
  8. xfs_close_common
  9. xfs_uio_end_length
  10. xfs_read_common
  11. xfs_write_common
  12. xfs_getattr_common
  13. xfs_setattr_common
  14. check_rights
  15. xfs_access_common
  16. xfs_lookup_common
  17. xfs_create_common
  18. xfs_remove_common
  19. xfs_rename_common
  20. xfs_mkdir_common
  21. xfs_rmdir_common
  22. xfs_readdir_common
  23. xfs_link_common
  24. xfs_symlink_common
  25. xfs_readlink_common
  26. xfs_inactive_common
  27. xfs_reclaim_common
  28. xfs_advlock_common
  29. xfs_printnode_common

    1 /*
    2  * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
    3  * (Royal Institute of Technology, Stockholm, Sweden).
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  *
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * 3. Neither the name of the Institute nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * NNPFS operations.
   36  */
   37 
   38 #include <xfs/xfs_locl.h>
   39 #include <xfs/xfs_message.h>
   40 #include <xfs/xfs_common.h>
   41 #include <xfs/xfs_fs.h>
   42 #include <xfs/xfs_dev.h>
   43 #include <xfs/xfs_deb.h>
   44 #include <xfs/xfs_syscalls.h>
   45 #include <xfs/xfs_vnodeops.h>
   46 
   47 RCSID("$arla: xfs_vnodeops-common.c,v 1.94 2003/01/27 11:58:50 lha Exp $");
   48 
   49 static void
   50 xfs_handle_stale(struct xfs_node *xn)
   51 {
   52 #if __APPLE__
   53     struct vnode *vp = XNODE_TO_VNODE(xn);
   54 #endif
   55 
   56     if ((xn->flags & NNPFS_STALE) == 0)
   57         return;
   58 
   59 #if __APPLE__
   60     if (UBCISVALID(vp) && !ubc_isinuse(vp, 1)) {
   61         xn->flags &= ~NNPFS_STALE;
   62         ubc_setsize(vp, 0);
   63         NNPFS_TOKEN_CLEAR(xn, ~0,
   64                         NNPFS_OPEN_MASK | NNPFS_ATTR_MASK |
   65                         NNPFS_DATA_MASK | NNPFS_LOCK_MASK);
   66     }
   67 #endif
   68 }
   69 
   70 int
   71 xfs_open_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
   72                u_int tok)
   73 {
   74     struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
   75     struct xfs_node *xn = VNODE_TO_XNODE(vp);
   76     int error = 0;
   77 
   78     NNPFSDEB(XDEBVFOPS, ("xfs_open_valid\n"));
   79 
   80     xfs_handle_stale(xn);
   81 
   82     do {
   83         if (!NNPFS_TOKEN_GOT(xn, tok)) {
   84             struct xfs_message_open msg;
   85 
   86             msg.header.opcode = NNPFS_MSG_OPEN;
   87             msg.cred.uid = cred->cr_uid;
   88             msg.cred.pag = xfs_get_pag(cred);
   89             msg.handle = xn->handle;
   90             msg.tokens = tok;
   91 
   92             error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
   93 
   94             if (error == 0)
   95                 error = ((struct xfs_message_wakeup *) & msg)->error;
   96         } else {
   97             goto done;
   98         }
   99     } while (error == 0);
  100 
  101 done:
  102     NNPFSDEB(XDEBVFOPS, ("xfs_open_valid: error = %d\n", error));
  103 
  104     return error;
  105 }
  106 
  107 int
  108 xfs_attr_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
  109                u_int tok)
  110 {
  111     struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
  112     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  113     int error = 0;
  114     xfs_pag_t pag = xfs_get_pag(cred);
  115 
  116     do {
  117         if (!NNPFS_TOKEN_GOT(xn, tok) || !xfs_has_pag(xn, pag)) {
  118             struct xfs_message_getattr msg;
  119 
  120             msg.header.opcode = NNPFS_MSG_GETATTR;
  121             msg.cred.uid = cred->cr_uid;
  122             msg.cred.pag = pag;
  123             msg.handle = xn->handle;
  124             error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  125             if (error == 0)
  126                 error = ((struct xfs_message_wakeup *) & msg)->error;
  127         } else {
  128             goto done;
  129         }
  130     } while (error == 0);
  131 
  132 done:
  133     return error;
  134 }
  135 
  136 int
  137 xfs_data_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
  138                u_int tok, uint32_t want_offset)
  139 {
  140     struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
  141     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  142     int error = 0;
  143     uint32_t offset;
  144     struct xfs_message_getdata msg;
  145 
  146     do {
  147         offset = want_offset;
  148         if (NNPFS_TOKEN_GOT(xn, tok|NNPFS_ATTR_R) && offset > xn->attr.va_size) {
  149             offset = xn->attr.va_size;
  150         }
  151     
  152         NNPFSDEB(XDEBVNOPS, ("xfs_data_valid: offset: want %ld has %ld, "
  153                            "tokens: want %lx has %lx length: %ld\n",
  154                            (long) offset, (long) xn->offset,
  155                            (long) tok, (long) xn->tokens,
  156                            (long) xn->attr.va_size));
  157 
  158         if (NNPFS_TOKEN_GOT(xn, tok)) {
  159             if (offset <= xn->offset || xn->attr.va_type == VDIR) {
  160                 break;
  161             }
  162         }
  163 
  164         msg.header.opcode = NNPFS_MSG_GETDATA;
  165         msg.cred.uid = cred->cr_uid;
  166         msg.cred.pag = xfs_get_pag(cred);
  167         msg.handle = xn->handle;
  168         msg.tokens = tok;
  169         msg.offset = offset;
  170         
  171         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  172         
  173         if (error == 0)
  174             error = ((struct xfs_message_wakeup *) & msg)->error;
  175         
  176     } while (error == 0);
  177 
  178     return error;
  179 }
  180 
  181 int
  182 xfs_open_common(struct vnode *vp,
  183                 int mode,
  184                 struct ucred *cred,
  185                 d_thread_t *p)
  186 {
  187     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  188     int ret;
  189 
  190     NNPFSDEB(XDEBVNOPS, ("xfs_open\n"));
  191 
  192     if (mode & FWRITE) {
  193         ret = xfs_open_valid(vp, cred, p, NNPFS_OPEN_NW);
  194     } else {
  195         ret = xfs_open_valid(vp, cred, p, NNPFS_OPEN_NR);
  196     }
  197 
  198     /* always update the read cred */
  199 
  200     if (mode & FWRITE)
  201         xfs_update_write_cred(xn, cred);
  202     xfs_update_read_cred(xn, cred);
  203 
  204     return ret;
  205 }
  206 
  207 static int
  208 do_fsync(struct xfs *xfsp,
  209          struct xfs_node *xn,
  210          struct ucred *cred,
  211          d_thread_t *p,
  212          u_int flag)
  213 {
  214     int error;
  215     struct xfs_message_putdata msg;
  216 
  217     msg.header.opcode = NNPFS_MSG_PUTDATA;
  218     if (cred != NOCRED) {
  219         msg.cred.uid = cred->cr_uid;
  220         msg.cred.pag = xfs_get_pag(cred);
  221     } else {
  222         msg.cred.uid = 0;
  223         msg.cred.pag = NNPFS_ANONYMOUSID;
  224     }
  225     msg.handle = xn->handle;
  226     vattr2xfs_attr(&xn->attr, &msg.attr);
  227     msg.flag   = flag;
  228 
  229     error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  230 
  231     if (error == 0)
  232         error = ((struct xfs_message_wakeup *) & msg)->error;
  233 
  234     if (error == 0)
  235         xn->flags &= ~NNPFS_DATA_DIRTY;
  236 
  237     return error;
  238 }
  239 
  240 int
  241 xfs_fsync_common(struct vnode *vp, struct ucred *cred,
  242                  int waitfor, d_thread_t *proc)
  243 {
  244     struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
  245     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  246     int error = 0;
  247 
  248     NNPFSDEB(XDEBVNOPS, ("xfs_fsync: %lx\n", (unsigned long)vp));
  249 
  250     /*
  251      * It seems that fsync is sometimes called after reclaiming a node.
  252      * In that case we just look happy.
  253      */
  254 
  255     if (xn == NULL) {
  256         printf("NNPFS PANIC WARNING! xfs_fsync called after reclaiming!\n");
  257         return 0;
  258     }
  259     
  260     xfs_pushdirty(vp, cred, proc);
  261 
  262     if (xn->flags & NNPFS_DATA_DIRTY) {
  263 #ifdef FSYNC_RECLAIM
  264         /* writing back the data from this vnode failed */
  265         if (waitfor & FSYNC_RECLAIM) {
  266             printf("xfs_fsync: data lost, failed to write back\n");
  267             xn->flags &= ~NNPFS_DATA_DIRTY;
  268             return 0;
  269         }
  270 #endif    
  271         error = do_fsync(xfsp, xn, cred, proc, NNPFS_WRITE | NNPFS_FSYNC);
  272     }
  273 
  274     return error;
  275 }
  276 
  277 int
  278 xfs_close_common(struct vnode *vp, int fflag,
  279                  d_thread_t *proc, struct ucred *cred)
  280 {
  281     struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
  282     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  283     int error = 0;
  284     
  285     NNPFSDEB(XDEBVNOPS,
  286            ("xfs_close cred = %lx, fflag = %x, xn->flags = %x\n",
  287             (unsigned long)cred, fflag, xn->flags));
  288 
  289     if (vp->v_type == VREG)
  290         xfs_pushdirty(vp, cred, proc);
  291 
  292     if (fflag & FWRITE && xn->flags & NNPFS_DATA_DIRTY)
  293         error = do_fsync(xfsp, xn, cred, proc, NNPFS_WRITE);
  294 
  295     return error;
  296 }
  297 
  298 size_t
  299 xfs_uio_end_length (struct uio *uio)
  300 {
  301 #ifdef DIAGNOSTIC
  302     size_t sz = 0;
  303     int i;
  304 
  305     for (i = 0; i < uio->uio_iovcnt; i++)
  306         sz += uio->uio_iov[i].iov_len;
  307     if (sz != uio->uio_resid)
  308         panic("xfs_uio_end_length");
  309 #endif
  310     return uio->uio_offset + uio->uio_resid;
  311 }
  312 
  313 
  314 int
  315 xfs_read_common(struct vnode *vp, struct uio *uio, int ioflag,
  316                 struct ucred *cred)
  317 {
  318     int error = 0;
  319     int i;
  320 
  321     NNPFSDEB(XDEBVNOPS, ("xfs_read\n"));
  322 
  323     xfs_update_read_cred(VNODE_TO_XNODE(vp), cred);
  324 
  325 #ifdef HAVE_FREEBSD_THREAD
  326     error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uio), NNPFS_DATA_R,
  327                            xfs_uio_end_length(uio));
  328 #else
  329     error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uio), NNPFS_DATA_R,
  330                            xfs_uio_end_length(uio));
  331 #endif
  332 
  333     NNPFSDEB(XDEBVNOPS, ("xfs_read: iovcnt: %d\n", uio->uio_iovcnt));
  334     for (i = 0; i < uio->uio_iovcnt; i++)
  335         NNPFSDEB(XDEBVNOPS, ("  base: %lx len: %lu\n",
  336                            (unsigned long)uio->uio_iov[i].iov_base,
  337                            (unsigned long)uio->uio_iov[i].iov_len));
  338 
  339     if (error == 0) {
  340         struct vnode *t = DATA_FROM_VNODE(vp);
  341 
  342 #ifdef HAVE_FREEBSD_THREAD
  343         xfs_vfs_readlock(t, xfs_uio_to_thread(uio));
  344         xfs_vop_read(t, uio, ioflag, cred, error);
  345         xfs_vfs_unlock(t, xfs_uio_to_thread(uio));
  346 #else
  347         xfs_vfs_readlock(t, xfs_uio_to_proc(uio));
  348         xfs_vop_read(t, uio, ioflag, cred, error);
  349         xfs_vfs_unlock(t, xfs_uio_to_proc(uio));
  350 #endif
  351     }
  352 
  353     NNPFSDEB(XDEBVNOPS, ("xfs_read offset: %lu resid: %lu\n",
  354                        (unsigned long)uio->uio_offset,
  355                        (unsigned long)uio->uio_resid));
  356     NNPFSDEB(XDEBVNOPS, ("xfs_read error: %d\n", error));
  357 
  358     return error;
  359 }
  360 
  361 int
  362 xfs_write_common(struct vnode *vp, struct uio *uiop, int ioflag,
  363                  struct ucred *cred)
  364 {
  365     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  366     int error = 0;
  367 
  368     NNPFSDEB(XDEBVNOPS, ("xfs_write\n"));
  369 
  370     xfs_update_write_cred(xn, cred);
  371 
  372 #ifdef HAVE_FREEBSD_THREAD
  373     error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uiop), NNPFS_DATA_W,
  374                            VNODE_TO_XNODE(vp)->attr.va_size);
  375 #else
  376     error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uiop), NNPFS_DATA_W,
  377                            VNODE_TO_XNODE(vp)->attr.va_size);
  378 #endif
  379 
  380     if (error == 0) {
  381         struct vnode *t = DATA_FROM_XNODE(xn);
  382         struct vattr sub_attr;
  383         int error2 = 0;
  384  
  385  #ifdef HAVE_FREEBSD_THREAD
  386         xfs_vfs_writelock(t, xfs_uio_to_thread(uiop));
  387         xfs_vop_write(t, uiop, ioflag, cred, error);
  388         VNODE_TO_XNODE(vp)->flags |= NNPFS_DATA_DIRTY;
  389         xfs_vop_getattr(t, &sub_attr, cred, xfs_uio_to_thread(uiop), error2);
  390  #else
  391         xfs_vfs_writelock(t, xfs_uio_to_proc(uiop));
  392         xfs_vop_write(t, uiop, ioflag, cred, error);
  393         VNODE_TO_XNODE(vp)->flags |= NNPFS_DATA_DIRTY;
  394         xfs_vop_getattr(t, &sub_attr, cred, xfs_uio_to_proc(uiop), error2);
  395  #endif
  396 
  397         if (error2 == 0) {
  398             xn->attr.va_size  = sub_attr.va_size;
  399             xn->attr.va_bytes = sub_attr.va_size;
  400             xn->attr.va_mtime = sub_attr.va_mtime;
  401             xfs_set_vp_size(vp, sub_attr.va_size);
  402             xn->offset = sub_attr.va_size;
  403         }
  404 #ifdef HAVE_FREEBSD_THREAD
  405         xfs_vfs_unlock(t, xfs_uio_to_thread(uiop));
  406 #else
  407         xfs_vfs_unlock(t, xfs_uio_to_proc(uiop));
  408 #endif
  409     }
  410 
  411     return error;
  412 }
  413 
  414 int
  415 xfs_getattr_common(struct vnode *vp, struct vattr *vap,
  416                    struct ucred *cred, d_thread_t *p)
  417 {
  418     int error = 0;
  419 
  420     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  421 
  422     NNPFSDEB(XDEBVNOPS, ("xfs_getattr\n"));
  423 
  424     error = xfs_attr_valid(vp, cred, p, NNPFS_ATTR_R);
  425     if (error == 0)
  426         *vap = xn->attr;
  427     return error;
  428 }
  429 
  430 int
  431 xfs_setattr_common(struct vnode *vp, struct vattr *vap,
  432                    struct ucred *cred, d_thread_t *p)
  433 {
  434     struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
  435     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  436     int error = 0;
  437 
  438     NNPFSDEB(XDEBVNOPS, ("xfs_setattr\n"));
  439 
  440 #define CHECK_NNPFSATTR(A, cast) (vap->A == cast VNOVAL || vap->A == xn->attr.A)
  441         if (CHECK_NNPFSATTR(va_mode,(mode_t)) &&
  442             CHECK_NNPFSATTR(va_nlink,(short)) &&
  443             CHECK_NNPFSATTR(va_size,(va_size_t)) &&
  444             CHECK_NNPFSATTR(va_uid,(uid_t)) &&
  445             CHECK_NNPFSATTR(va_gid,(gid_t)) &&
  446             CHECK_NNPFSATTR(va_mtime.tv_sec,(unsigned int)) &&
  447             CHECK_NNPFSATTR(va_fileid,(long)) &&
  448             CHECK_NNPFSATTR(va_type,(enum vtype)))
  449                 return 0;               /* Nothing to do */
  450 #undef CHECK_NNPFSATTR
  451 
  452     if (NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_W)) {
  453         /* Update attributes and mark them dirty. */
  454         VNODE_TO_XNODE(vp)->flags |= NNPFS_ATTR_DIRTY;
  455         error = EINVAL;                /* XXX not yet implemented */
  456         goto done;
  457     } else {
  458         struct xfs_message_putattr msg;
  459 
  460         msg.header.opcode = NNPFS_MSG_PUTATTR;
  461         if (cred != NOCRED) {
  462             msg.cred.uid = cred->cr_uid;
  463             msg.cred.pag = xfs_get_pag(cred);
  464         } else {
  465             msg.cred.uid = 0;
  466             msg.cred.pag = NNPFS_ANONYMOUSID;
  467         }
  468         msg.handle = xn->handle;
  469         vattr2xfs_attr(vap, &msg.attr);
  470         if (NNPFS_TOKEN_GOT(xn, NNPFS_DATA_R)) {
  471             if (vp->v_type == VREG) {
  472                 if (vap->va_size != (va_size_t)VNOVAL)
  473                     XA_SET_SIZE(&msg.attr, vap->va_size);
  474                 else
  475                     XA_SET_SIZE(&msg.attr, xn->attr.va_size);
  476 #ifdef __APPLE__
  477                 /* XXX needed ? */
  478                 if (UBCINFOEXISTS(vp))
  479                     ubc_setsize(vp, msg.attr.xa_size);
  480 #endif
  481             }
  482             if (vap->va_mtime.tv_sec != (unsigned int)VNOVAL)
  483                 XA_SET_MTIME(&msg.attr, vap->va_mtime.tv_sec);
  484             else
  485                 XA_SET_MTIME(&msg.attr, xn->attr.va_mtime.tv_sec);
  486         }
  487 
  488         NNPFS_TOKEN_CLEAR(xn, NNPFS_ATTR_VALID, NNPFS_ATTR_MASK);
  489         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  490         if (error == 0)
  491             error = ((struct xfs_message_wakeup *) & msg)->error;
  492     }
  493 
  494 done:
  495     return error;
  496 }
  497 
  498 static int
  499 check_rights (u_char rights, int mode)
  500 {
  501     int error = 0;
  502 
  503     if (mode & VREAD)
  504         if ((rights & NNPFS_RIGHT_R) == 0)
  505             error = EACCES;
  506     if (mode & VWRITE)
  507         if ((rights & NNPFS_RIGHT_W) == 0)
  508             error = EACCES;
  509     if (mode & VEXEC)
  510         if ((rights & NNPFS_RIGHT_X) == 0)
  511             error = EACCES;
  512     return error;
  513 }
  514 
  515 int
  516 xfs_access_common(struct vnode *vp, int mode, struct ucred *cred,
  517                   d_thread_t *p)
  518 {
  519     int error = 0;
  520     xfs_pag_t pag = xfs_get_pag(cred);
  521 
  522     NNPFSDEB(XDEBVNOPS, ("xfs_access mode = 0%o\n", mode));
  523 
  524     error = xfs_attr_valid(vp, cred, p, NNPFS_ATTR_R);
  525     if (error == 0) {
  526         struct xfs_node *xn = VNODE_TO_XNODE(vp);
  527         int i;
  528 
  529         error = check_rights (xn->anonrights, mode);
  530 
  531         if (error == 0)
  532             goto done;
  533 
  534         NNPFSDEB(XDEBVNOPS, ("xfs_access anonaccess failed\n"));
  535 
  536         error = EACCES;         /* default to EACCES if pag isn't in xn->id */
  537 
  538         for (i = 0; i < MAXRIGHTS; i++)
  539             if (xn->id[i] == pag) {
  540                 error = check_rights (xn->rights[i], mode);
  541                 break;
  542             }
  543     }
  544 
  545 done:
  546     NNPFSDEB(XDEBVNOPS, ("xfs_access(0%o) = %d\n", mode, error));
  547 
  548     return error;
  549 }
  550 
  551 int
  552 xfs_lookup_common(struct vnode *dvp, 
  553                   xfs_componentname *cnp, 
  554                   struct vnode **vpp)
  555 {
  556     struct xfs_message_getnode msg;
  557     struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
  558     struct xfs_node *d = VNODE_TO_XNODE(dvp);
  559     int error = 0;
  560 #ifdef HAVE_FREEBSD_THREAD
  561     d_thread_t *proc  = xfs_cnp_to_thread(cnp);
  562     struct ucred *cred = xfs_thread_to_cred(proc);
  563 #else
  564     d_thread_t *proc  = xfs_cnp_to_proc(cnp);
  565     struct ucred *cred = xfs_proc_to_cred(proc);
  566 #endif
  567 
  568     NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: enter\n"));
  569 
  570     *vpp = NULL;
  571 
  572     if (cnp->cn_namelen >= NNPFS_MAX_NAME)
  573         return ENAMETOOLONG;
  574         
  575     if (dvp->v_type != VDIR)
  576         return ENOTDIR;
  577 
  578     if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
  579         *vpp = dvp;
  580         VREF(*vpp);
  581         return 0;
  582     }
  583     
  584     do {
  585         xfs_vop_access(dvp, VEXEC, cred, proc, error);
  586         if (error != 0)
  587             goto done;
  588 
  589         NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: dvp = %lx\n",
  590                            (unsigned long) dvp));
  591         NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: cnp = %lx, "
  592                            "cnp->cn_nameiop = %d\n", 
  593                            (unsigned long) cnp, (int)cnp->cn_nameiop));
  594         
  595 
  596         error = xfs_dnlc_lookup(dvp, cnp, vpp);
  597         if (error == 0) {
  598 
  599             /*
  600              * Doesn't quite work.
  601              */
  602 
  603 #if 0
  604             if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
  605                 && (cnp->cn_flags & ISLASTCN)) {
  606                 error = EJUSTRETURN;
  607                 goto done;
  608             }
  609 #endif
  610 
  611             msg.header.opcode = NNPFS_MSG_GETNODE;
  612             if (cnp->cn_cred != NOCRED) {
  613                 msg.cred.uid = cnp->cn_cred->cr_uid;
  614                 msg.cred.pag = xfs_get_pag(cnp->cn_cred);
  615             } else {
  616                 msg.cred.uid = 0;
  617                 msg.cred.pag = NNPFS_ANONYMOUSID;
  618             }
  619             msg.parent_handle = d->handle;
  620             memcpy(msg.name, cnp->cn_nameptr, cnp->cn_namelen);
  621             msg.name[cnp->cn_namelen] = '\0';
  622             error = xfs_message_rpc(xfsp->fd, &msg.header,
  623                                     sizeof(msg), proc);
  624             if (error == 0)
  625                 error = ((struct xfs_message_wakeup *) & msg)->error;
  626             if(error == ENOENT && cnp->cn_nameiop != CREATE) {
  627                 NNPFSDEB(XDEBVNOPS, ("xfs_lookup: neg cache %lx (%s, %ld)\n",
  628                                    (unsigned long)dvp,
  629                                    cnp->cn_nameptr, cnp->cn_namelen));
  630                 xfs_dnlc_enter (dvp, cnp, NULL);
  631             }
  632         } else if (error == -1) {
  633             error = 0;
  634             goto done;
  635         }
  636     } while (error == 0);
  637 
  638 done:
  639     NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: return error = %d\n", error));
  640     return error;
  641 }
  642 
  643 int
  644 xfs_create_common(struct vnode *dvp,
  645                   const char *name,
  646                   struct vattr *vap, 
  647                   struct ucred *cred,
  648                   d_thread_t *p)
  649 {
  650     struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
  651     struct xfs_node *xn = VNODE_TO_XNODE(dvp);
  652     int error = 0;
  653 
  654     NNPFSDEB(XDEBVNOPS, ("xfs_create: (%lx, %s)\n",
  655                        (unsigned long)dvp, name));
  656     {
  657         struct xfs_message_create msg;
  658 
  659         msg.header.opcode = NNPFS_MSG_CREATE;
  660         msg.parent_handle = xn->handle;
  661         if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
  662             return ENAMETOOLONG;
  663         vattr2xfs_attr(vap, &msg.attr);
  664 
  665         msg.mode = 0;                  /* XXX - mode */
  666         if (cred != NOCRED) {
  667             msg.cred.uid = cred->cr_uid;
  668             msg.cred.pag = xfs_get_pag(cred);
  669         } else {
  670             msg.cred.uid = 0;
  671             msg.cred.pag = NNPFS_ANONYMOUSID;
  672         }
  673 
  674 
  675         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  676 
  677         if (error == 0)
  678             error = ((struct xfs_message_wakeup *) & msg)->error;
  679     }
  680 
  681 #if 0
  682     if (error == EEXIST)
  683         error = 0;
  684 #endif
  685 
  686     return error;
  687 }
  688 
  689 int
  690 xfs_remove_common(struct vnode *dvp,
  691                   struct vnode *vp,
  692                   const char *name,
  693                   struct ucred *cred,
  694                   d_thread_t *p)
  695 {
  696     struct xfs *xfsp  = NNPFS_FROM_VNODE(dvp);
  697     struct xfs_node *xn = VNODE_TO_XNODE(dvp);
  698     struct xfs_message_remove msg;
  699     int error;
  700 
  701     NNPFSDEB(XDEBVNOPS, ("xfs_remove: %s\n", name));
  702 
  703     msg.header.opcode = NNPFS_MSG_REMOVE;
  704     msg.parent_handle = xn->handle;
  705     msg.cred.uid = cred->cr_uid;
  706     msg.cred.pag = xfs_get_pag(cred);
  707     
  708     if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
  709         error = ENAMETOOLONG;
  710     else
  711         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  712     if (error == 0)
  713         error = ((struct xfs_message_wakeup *) &msg)->error;
  714 
  715     if (error == 0)
  716         xfs_dnlc_purge (vp);
  717 
  718     return error;
  719 }
  720 
  721 int
  722 xfs_rename_common(struct vnode *fdvp, 
  723                   struct vnode *fvp,
  724                   const char *fname,
  725                   struct vnode *tdvp,
  726                   struct vnode *tvp,
  727                   const char *tname,
  728                   struct ucred *cred,
  729                   d_thread_t *p)
  730 {
  731     struct xfs *xfsp = NNPFS_FROM_VNODE(fdvp);
  732     int error;
  733 
  734     NNPFSDEB(XDEBVNOPS, ("xfs_rename: %s %s\n", fname, tname));
  735 
  736     if ((fvp->v_mount != tdvp->v_mount)
  737         || (tvp && (fvp->v_mount != tvp->v_mount))) {
  738         return  EXDEV;
  739     }
  740 
  741     {
  742         struct xfs_message_rename msg;
  743 
  744         msg.header.opcode = NNPFS_MSG_RENAME;
  745         msg.old_parent_handle = VNODE_TO_XNODE(fdvp)->handle;
  746         if (strlcpy(msg.old_name, fname, sizeof(msg.old_name)) >= NNPFS_MAX_NAME)
  747             return ENAMETOOLONG;
  748         msg.new_parent_handle = VNODE_TO_XNODE(tdvp)->handle;
  749         if (strlcpy(msg.new_name, tname, sizeof(msg.new_name)) >= NNPFS_MAX_NAME)
  750             return ENAMETOOLONG;
  751         msg.cred.uid = cred->cr_uid;
  752         msg.cred.pag = xfs_get_pag(cred);
  753         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  754         if (error == 0)
  755             error = ((struct xfs_message_wakeup *) &msg)->error;
  756 
  757     }
  758 
  759     NNPFSDEB(XDEBVNOPS, ("xfs_rename: error = %d\n", error));
  760 
  761     return error;
  762 }
  763 
  764 int
  765 xfs_mkdir_common(struct vnode *dvp, 
  766                  const char *name,
  767                  struct vattr *vap, 
  768                  struct ucred *cred,
  769                  d_thread_t *p)
  770 {
  771     struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
  772     struct xfs_node *xn = VNODE_TO_XNODE(dvp);
  773     int error = 0;
  774 
  775     NNPFSDEB(XDEBVNOPS, ("xfs_mkdir: %s\n", name));
  776     {
  777         struct xfs_message_mkdir msg;
  778 
  779         msg.header.opcode = NNPFS_MSG_MKDIR;
  780         msg.parent_handle = xn->handle;
  781         if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
  782             return ENAMETOOLONG;
  783         vattr2xfs_attr(vap, &msg.attr);
  784         if (cred != NOCRED) {
  785             msg.cred.uid = cred->cr_uid;
  786             msg.cred.pag = xfs_get_pag(cred);
  787         } else {
  788             msg.cred.uid = 0;
  789             msg.cred.pag = NNPFS_ANONYMOUSID;
  790         }
  791         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  792         if (error == 0)
  793             error = ((struct xfs_message_wakeup *) & msg)->error;
  794     }
  795 
  796     return error;
  797 }
  798 
  799 int
  800 xfs_rmdir_common(struct vnode *dvp,
  801                  struct vnode *vp,
  802                  const char *name,
  803                  struct ucred *cred,
  804                  d_thread_t *p)
  805 {
  806     struct xfs *xfsp  = NNPFS_FROM_VNODE(dvp);
  807     struct xfs_node *xn = VNODE_TO_XNODE(dvp);
  808     struct xfs_message_rmdir msg;
  809     int error;
  810 
  811     NNPFSDEB(XDEBVNOPS, ("xfs_rmdir: %s\n", name));
  812 
  813     msg.header.opcode = NNPFS_MSG_RMDIR;
  814     msg.parent_handle = xn->handle;
  815     msg.cred.uid = cred->cr_uid;
  816     msg.cred.pag = xfs_get_pag(cred);
  817     if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
  818         error = ENAMETOOLONG;
  819     else
  820         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  821     if (error == 0)
  822         error = ((struct xfs_message_wakeup *) &msg)->error;
  823 
  824     if (error == 0)
  825         xfs_dnlc_purge (vp);
  826 
  827     NNPFSDEB(XDEBVNOPS, ("xfs_rmdir error: %d\n", error));
  828 
  829     return error;
  830 }
  831 
  832 int
  833 xfs_readdir_common(struct vnode *vp, 
  834                    struct uio *uiop, 
  835                    struct ucred *cred,
  836                    d_thread_t *p,
  837                    int *eofflag)
  838 {
  839     int error = 0;
  840 
  841     NNPFSDEB(XDEBVNOPS, ("xfs_readdir\n"));
  842 
  843     if(eofflag)
  844         *eofflag = 0;
  845 #ifdef HAVE_FREEBSD_THREAD
  846     error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uiop), NNPFS_DATA_R,
  847                            xfs_uio_end_length(uiop));
  848 #else
  849     error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uiop), NNPFS_DATA_R,
  850                            xfs_uio_end_length(uiop));
  851 #endif
  852     if (error == 0) {
  853         struct vnode *t = DATA_FROM_VNODE(vp);
  854 
  855 #ifdef HAVE_FREEBSD_THREAD
  856         xfs_vfs_readlock(t, xfs_uio_to_thread(uiop));
  857 #else
  858         xfs_vfs_readlock(t, xfs_uio_to_proc(uiop));
  859 #endif
  860         xfs_vop_read(t, uiop, 0, cred, error);
  861         if (eofflag) {
  862             struct vattr t_attr;
  863             int error2;
  864 
  865 #ifdef HAVE_FREEBSD_THREAD
  866             xfs_vop_getattr(t, &t_attr, cred, xfs_uio_to_thread(uiop), error2);
  867 #else
  868             xfs_vop_getattr(t, &t_attr, cred, xfs_uio_to_proc(uiop), error2);
  869 #endif
  870             if (error2 == 0)
  871                 *eofflag = t_attr.va_size <= uiop->uio_offset;
  872         }
  873 #ifdef HAVE_FREEBSD_THREAD
  874         xfs_vfs_unlock(t, xfs_uio_to_thread(uiop));
  875 #else
  876         xfs_vfs_unlock(t, xfs_uio_to_proc(uiop));
  877 #endif
  878     }
  879     return error;
  880 }
  881 
  882 int
  883 xfs_link_common(struct vnode *dvp, 
  884                 struct vnode *vp, 
  885                 const char *name,
  886                 struct ucred *cred,
  887                 d_thread_t *p)
  888 {
  889     struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
  890     struct xfs_node *xn = VNODE_TO_XNODE(dvp);
  891     struct xfs_node *xn2 = VNODE_TO_XNODE(vp);
  892     struct xfs_message_link msg;
  893     int error = 0;
  894 
  895     NNPFSDEB(XDEBVNOPS, ("xfs_link: %s\n", name));
  896     
  897     msg.header.opcode = NNPFS_MSG_LINK;
  898     msg.parent_handle = xn->handle;
  899     msg.from_handle   = xn2->handle;
  900     if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
  901         return ENAMETOOLONG;
  902     msg.cred.uid = cred->cr_uid;
  903     msg.cred.pag = xfs_get_pag(cred);
  904 
  905     error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
  906     if (error == 0)
  907         error = ((struct xfs_message_wakeup *) & msg)->error;
  908     
  909     return error;
  910 }
  911 
  912 int
  913 xfs_symlink_common(struct vnode *dvp,
  914                    struct vnode **vpp,
  915                    xfs_componentname *cnp,
  916                    struct vattr *vap,
  917                    char *target)
  918 {
  919     struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
  920     struct xfs_node *xn = VNODE_TO_XNODE(dvp);
  921 #ifdef HAVE_FREEBSD_THREAD
  922     d_thread_t *proc  = xfs_cnp_to_thread(cnp);
  923     struct ucred *cred = xfs_thread_to_cred(proc);
  924 #else
  925     d_thread_t *proc  = xfs_cnp_to_proc(cnp);
  926     struct ucred *cred = xfs_proc_to_cred(proc);
  927 #endif
  928     struct xfs_message_symlink *msg = NULL;
  929     const char *name = cnp->cn_nameptr;
  930     int error = 0;
  931 
  932     NNPFSDEB(XDEBVNOPS, ("xfs_symlink: %s\n", name));
  933 
  934     msg = malloc(sizeof(struct xfs_message_symlink), M_TEMP, M_WAITOK);
  935     if (msg == NULL) {
  936         error = ENOMEM;
  937         goto done;
  938     }
  939     memset(msg, 0, sizeof(*msg));
  940 
  941     msg->header.opcode = NNPFS_MSG_SYMLINK;
  942     msg->parent_handle = xn->handle;
  943     vattr2xfs_attr(vap, &msg->attr);
  944     msg->cred.uid = cred->cr_uid;
  945     msg->cred.pag = xfs_get_pag(cred);
  946     if (strlcpy (msg->contents, target, sizeof(msg->contents)) >= NNPFS_MAX_SYMLINK_CONTENT) {
  947         error = ENAMETOOLONG;
  948         goto done;
  949     }
  950     if (strlcpy(msg->name, name, sizeof(msg->name)) >= NNPFS_MAX_NAME) {
  951         error = ENAMETOOLONG;
  952         goto done;
  953     }
  954     error = xfs_message_rpc(xfsp->fd, &msg->header, sizeof(*msg), proc);
  955     if (error == 0)
  956         error = ((struct xfs_message_wakeup *) msg)->error;
  957 
  958  done:
  959     free(msg, M_TEMP);
  960     return error;
  961 }
  962 
  963 int
  964 xfs_readlink_common(struct vnode *vp, struct uio *uiop, struct ucred *cred)
  965 {
  966     int error = 0;
  967 
  968     NNPFSDEB(XDEBVNOPS, ("xfs_readlink\n"));
  969 
  970 #ifdef HAVE_FREEBSD_THREAD
  971     error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uiop), NNPFS_DATA_R,
  972                            xfs_uio_end_length(uiop));
  973 #else
  974     error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uiop), NNPFS_DATA_R,
  975                            xfs_uio_end_length(uiop));
  976 #endif
  977     if (error == 0) {
  978         struct vnode *t = DATA_FROM_VNODE(vp);
  979 
  980 #ifdef HAVE_FREEBSD_THREAD
  981         xfs_vfs_readlock(t, xfs_uio_to_thread(uiop));
  982         xfs_vop_read(t, uiop, 0, cred, error);
  983         xfs_vfs_unlock(t, xfs_uio_to_thread(uiop));
  984 #else
  985         xfs_vfs_readlock(t, xfs_uio_to_proc(uiop));
  986         xfs_vop_read(t, uiop, 0, cred, error);
  987         xfs_vfs_unlock(t, xfs_uio_to_proc(uiop));
  988 #endif
  989     }
  990     return error;
  991 }
  992 
  993 int
  994 xfs_inactive_common(struct vnode *vp, d_thread_t *p)
  995 {
  996     int error;
  997     struct xfs_node *xn = VNODE_TO_XNODE(vp);
  998 
  999     NNPFSDEB(XDEBVNOPS, ("xfs_inactive, %lx\n",
 1000                        (unsigned long)vp));
 1001 
 1002     /*
 1003      * This seems rather bogus, but sometimes we get an already
 1004      * cleaned node to be made inactive.  Just ignoring it seems safe.
 1005      */
 1006 
 1007     if (xn == NULL) {
 1008         NNPFSDEB(XDEBVNOPS, ("xfs_inactive: clean node\n"));
 1009         return 0;
 1010     }
 1011 
 1012     /* xn->wr_cred not set -> NOCRED */
 1013 
 1014     if (vp->v_type == VREG)
 1015         xfs_pushdirty(vp, xn->wr_cred, p);
 1016 
 1017     error = xfs_fsync_common(vp, xn->wr_cred, /* XXX */ 0, p);
 1018     if (error) {
 1019         printf ("xfs_inactive: failed writing back data: %d\n", error);
 1020         xn->flags &= ~NNPFS_DATA_DIRTY;
 1021     }
 1022 
 1023     /* If this node is no longer valid, recycle immediately. */
 1024     if (!NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_R | NNPFS_ATTR_W)
 1025         || (xn->flags & NNPFS_STALE) == NNPFS_STALE)
 1026     {
 1027 #ifndef __osf__
 1028         xfs_vfs_unlock(vp, p);
 1029         NNPFSDEB(XDEBVNOPS, ("xfs_inactive: vrecycle\n"));
 1030         vrecycle(vp, p);
 1031 #else /* __osf__ */
 1032         NNPFSDEB(XDEBVNOPS, ("xfs_inactive: vp = %lx vp->v_usecount= %d\n",
 1033                              (unsigned long)vp, vp?vp->v_usecount:0));
 1034 #endif /* __osf__ */
 1035     } else {
 1036 #ifndef __osf__
 1037         xfs_vfs_unlock(vp, p);
 1038 #endif
 1039         xn->flags &= ~NNPFS_STALE;
 1040     }
 1041 
 1042     NNPFSDEB(XDEBVNOPS, ("return: xfs_inactive\n"));
 1043 
 1044     return 0;
 1045 }
 1046 
 1047 int
 1048 xfs_reclaim_common(struct vnode *vp)
 1049 {
 1050     struct xfs_message_inactivenode msg;
 1051     struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
 1052     struct xfs_node *xn = VNODE_TO_XNODE(vp);
 1053 
 1054     NNPFSDEB(XDEBVNOPS, ("xfs_reclaim: %lx\n",
 1055                        (unsigned long)vp));
 1056 
 1057     NNPFS_TOKEN_CLEAR(xn,
 1058                     ~0,
 1059                     NNPFS_OPEN_MASK | NNPFS_ATTR_MASK |
 1060                     NNPFS_DATA_MASK | NNPFS_LOCK_MASK);
 1061     /* Release, data if we still have it. */
 1062     if (DATA_FROM_XNODE(xn) != 0) {
 1063         vrele(DATA_FROM_XNODE(xn));
 1064         DATA_FROM_XNODE(xn) = 0;
 1065     }
 1066 
 1067     xfs_remove_node(&xfsp->nodehead, xn);
 1068 
 1069     msg.header.opcode = NNPFS_MSG_INACTIVENODE;
 1070     msg.handle = xn->handle;
 1071     msg.flag   = NNPFS_NOREFS | NNPFS_DELETE;
 1072     xfs_message_send(xfsp->fd, &msg.header, sizeof(msg));
 1073 
 1074     xfs_dnlc_purge(vp);
 1075     free_xfs_node(xn);
 1076     return 0;
 1077 }
 1078 
 1079 /*
 1080  *
 1081  */
 1082 
 1083 #if 0
 1084 
 1085 int
 1086 xfs_advlock_common(struct vnode *dvp, 
 1087                    int locktype,
 1088                    unsigned long lockid, /* XXX this good ? */
 1089                    struct ucred *cred)
 1090 {
 1091     struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
 1092     struct xfs_node *xn = VNODE_TO_XNODE(dvp);
 1093     int error = 0;
 1094 
 1095     NNPFSDEB(XDEBVNOPS, ("xfs_advlock\n"));
 1096     {
 1097         struct xfs_message_advlock msg;
 1098 
 1099         msg.header.opcode = NNPFS_MSG_ADVLOCK;
 1100         msg.handle = xn->handle;
 1101         msg.locktype = locktype;
 1102         msg.lockid = lockid;
 1103 
 1104         if (cred != NOCRED) {
 1105             msg.cred.uid = cred->cr_uid;
 1106             msg.cred.pag = xfs_get_pag(cred);
 1107         } else {
 1108             msg.cred.uid = 0;
 1109             msg.cred.pag = NNPFS_ANONYMOUSID;
 1110         }
 1111         error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
 1112         if (error == 0)
 1113             error = ((struct xfs_message_wakeup *) & msg)->error;
 1114     }
 1115 
 1116     if (error == 0) {
 1117         
 1118         /* sleep until woken */
 1119 
 1120     } else {
 1121 
 1122         /* die */
 1123     }
 1124 
 1125     return error;
 1126 }
 1127 
 1128 #endif
 1129 
 1130 /*
 1131  *
 1132  */
 1133 
 1134 void
 1135 xfs_printnode_common (struct vnode *vp)
 1136 {
 1137     struct xfs_node *xn = VNODE_TO_XNODE(vp);
 1138 
 1139     printf ("xnode: fid: %d.%d.%d.%d\n", 
 1140             xn->handle.a, xn->handle.b, xn->handle.c, xn->handle.d);
 1141     printf ("\tattr: %svalid\n", 
 1142             NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_VALID) ? "": "in");
 1143     printf ("\tdata: %svalid\n", 
 1144             NNPFS_TOKEN_GOT(xn, NNPFS_DATA_VALID) ? "": "in");
 1145     printf ("\tflags: 0x%x\n", xn->flags);
 1146     printf ("\toffset: %d\n", xn->offset);
 1147 }

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