Print this page
OS-5148 ftruncate at offset should emit proper events
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-3462 rename on NFSv4 filesystem induces panic
OS-3294 add support for inotify
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>


  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 /*
  32  *      Copyright 1983,1984,1985,1986,1987,1988,1989 AT&T.
  33  *      All Rights Reserved
  34  */
  35 
  36 /*
  37  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  38  */
  39 
  40 #include <sys/param.h>
  41 #include <sys/types.h>
  42 #include <sys/systm.h>
  43 #include <sys/cred.h>
  44 #include <sys/time.h>
  45 #include <sys/vnode.h>
  46 #include <sys/vfs.h>
  47 #include <sys/vfs_opreg.h>
  48 #include <sys/file.h>
  49 #include <sys/filio.h>
  50 #include <sys/uio.h>
  51 #include <sys/buf.h>
  52 #include <sys/mman.h>
  53 #include <sys/pathname.h>
  54 #include <sys/dirent.h>
  55 #include <sys/debug.h>
  56 #include <sys/vmsystm.h>
  57 #include <sys/fcntl.h>


3722 {
3723         int error;
3724 
3725         if (vap->va_mask & AT_NOSET)
3726                 return (EINVAL);
3727 
3728         if (nfs_zone() != VTOMI4(vp)->mi_zone)
3729                 return (EIO);
3730 
3731         /*
3732          * Don't call secpolicy_vnode_setattr, the client cannot
3733          * use its cached attributes to make security decisions
3734          * as the server may be faking mode bits or mapping uid/gid.
3735          * Always just let the server to the checking.
3736          * If we provide the ability to remove basic priviledges
3737          * to setattr (e.g. basic without chmod) then we will
3738          * need to add a check here before calling the server.
3739          */
3740         error = nfs4setattr(vp, vap, flags, cr, NULL);
3741 
3742         if (error == 0 && (vap->va_mask & AT_SIZE) && vap->va_size == 0)

3743                 vnevent_truncate(vp, ct);




3744 
3745         return (error);
3746 }
3747 
3748 /*
3749  * To replace the "guarded" version 3 setattr, we use two types of compound
3750  * setattr requests:
3751  * 1. The "normal" setattr, used when the size of the file isn't being
3752  *    changed - { Putfh <fh>; Setattr; Getattr }/
3753  * 2. If the size is changed, precede Setattr with: Getattr; Verify
3754  *    with only ctime as the argument. If the server ctime differs from
3755  *    what is cached on the client, the verify will fail, but we would
3756  *    already have the ctime from the preceding getattr, so just set it
3757  *    and retry. Thus the compound here is - { Putfh <fh>; Getattr; Verify;
3758  *      Setattr; Getattr }.
3759  *
3760  * The vsecattr_t * input parameter will be non-NULL if ACLs are being set in
3761  * this setattr and NULL if they are not.
3762  */
3763 static int


8046          */
8047         mutex_enter(&rp->r_statelock);
8048         if (rp->r_unldvp != NULL) {
8049                 if (strcmp(rp->r_unlname, onm) == 0) {
8050                         (void) strncpy(rp->r_unlname, nnm, MAXNAMELEN);
8051                         rp->r_unlname[MAXNAMELEN - 1] = '\0';
8052                         if (ndvp != rp->r_unldvp) {
8053                                 VN_RELE(rp->r_unldvp);
8054                                 rp->r_unldvp = ndvp;
8055                                 VN_HOLD(ndvp);
8056                         }
8057                 }
8058         }
8059         mutex_exit(&rp->r_statelock);
8060 
8061         /*
8062          * Notify the rename vnevents to source vnode, and to the target
8063          * vnode if it already existed.
8064          */
8065         if (error == 0) {
8066                 vnode_t *tvp;
8067                 rnode4_t *trp;

8068                 /*
8069                  * Notify the vnode. Each links is represented by
8070                  * a different vnode, in nfsv4.
8071                  */
8072                 if (nvp) {
8073                         trp = VTOR4(nvp);
8074                         tvp = nvp;
8075                         if (IS_SHADOW(nvp, trp))
8076                                 tvp = RTOV4(trp);
8077                         vnevent_rename_dest(tvp, ndvp, nnm, ct);
8078                 }
8079 
8080                 /*
8081                  * if the source and destination directory are not the
8082                  * same notify the destination directory.
8083                  */
8084                 if (VTOR4(odvp) != VTOR4(ndvp)) {


8085                         trp = VTOR4(ndvp);
8086                         tvp = ndvp;

8087                         if (IS_SHADOW(ndvp, trp))
8088                                 tvp = RTOV4(trp);
8089                         vnevent_rename_dest_dir(tvp, ct);
8090                 }
8091 
8092                 trp = VTOR4(ovp);
8093                 tvp = ovp;
8094                 if (IS_SHADOW(ovp, trp))
8095                         tvp = RTOV4(trp);
8096                 vnevent_rename_src(tvp, odvp, onm, ct);
8097         }
8098 
8099         if (nvp) {
8100                 VN_RELE(nvp);
8101         }
8102         VN_RELE(ovp);
8103 
8104         nfs_rw_exit(&odrp->r_rwlock);
8105         nfs_rw_exit(&ndrp->r_rwlock);
8106 
8107         return (error);
8108 }
8109 
8110 /*
8111  * When the parent directory has changed, sv_dfh must be updated
8112  */
8113 static void
8114 update_parentdir_sfh(vnode_t *vp, vnode_t *ndvp)
8115 {
8116         svnode_t *sv = VTOSV(vp);


10985     offset_t offset, cred_t *cr, caller_context_t *ct)
10986 {
10987         int error;
10988 
10989         if (nfs_zone() != VTOMI4(vp)->mi_zone)
10990                 return (EIO);
10991         ASSERT(vp->v_type == VREG);
10992         if (cmd != F_FREESP)
10993                 return (EINVAL);
10994 
10995         error = convoff(vp, bfp, 0, offset);
10996         if (!error) {
10997                 ASSERT(bfp->l_start >= 0);
10998                 if (bfp->l_len == 0) {
10999                         struct vattr va;
11000 
11001                         va.va_mask = AT_SIZE;
11002                         va.va_size = bfp->l_start;
11003                         error = nfs4setattr(vp, &va, 0, cr, NULL);
11004 
11005                         if (error == 0 && bfp->l_start == 0)

11006                                 vnevent_truncate(vp, ct);




11007                 } else
11008                         error = EINVAL;
11009         }
11010 
11011         return (error);
11012 }
11013 
11014 /* ARGSUSED */
11015 int
11016 nfs4_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
11017 {
11018         rnode4_t *rp;
11019         rp = VTOR4(vp);
11020 
11021         if (vp->v_type == VREG && IS_SHADOW(vp, rp)) {
11022                 vp = RTOV4(rp);
11023         }
11024         *vpp = vp;
11025         return (0);
11026 }




  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 /*
  32  *      Copyright 1983,1984,1985,1986,1987,1988,1989 AT&T.
  33  *      All Rights Reserved
  34  */
  35 
  36 /*
  37  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  38  */
  39 
  40 #include <sys/param.h>
  41 #include <sys/types.h>
  42 #include <sys/systm.h>
  43 #include <sys/cred.h>
  44 #include <sys/time.h>
  45 #include <sys/vnode.h>
  46 #include <sys/vfs.h>
  47 #include <sys/vfs_opreg.h>
  48 #include <sys/file.h>
  49 #include <sys/filio.h>
  50 #include <sys/uio.h>
  51 #include <sys/buf.h>
  52 #include <sys/mman.h>
  53 #include <sys/pathname.h>
  54 #include <sys/dirent.h>
  55 #include <sys/debug.h>
  56 #include <sys/vmsystm.h>
  57 #include <sys/fcntl.h>


3722 {
3723         int error;
3724 
3725         if (vap->va_mask & AT_NOSET)
3726                 return (EINVAL);
3727 
3728         if (nfs_zone() != VTOMI4(vp)->mi_zone)
3729                 return (EIO);
3730 
3731         /*
3732          * Don't call secpolicy_vnode_setattr, the client cannot
3733          * use its cached attributes to make security decisions
3734          * as the server may be faking mode bits or mapping uid/gid.
3735          * Always just let the server to the checking.
3736          * If we provide the ability to remove basic priviledges
3737          * to setattr (e.g. basic without chmod) then we will
3738          * need to add a check here before calling the server.
3739          */
3740         error = nfs4setattr(vp, vap, flags, cr, NULL);
3741 
3742         if (error == 0 && (vap->va_mask & AT_SIZE)) {
3743                 if (vap->va_size == 0) {
3744                         vnevent_truncate(vp, ct);
3745                 } else {
3746                         vnevent_resize(vp, ct);
3747                 }
3748         }
3749 
3750         return (error);
3751 }
3752 
3753 /*
3754  * To replace the "guarded" version 3 setattr, we use two types of compound
3755  * setattr requests:
3756  * 1. The "normal" setattr, used when the size of the file isn't being
3757  *    changed - { Putfh <fh>; Setattr; Getattr }/
3758  * 2. If the size is changed, precede Setattr with: Getattr; Verify
3759  *    with only ctime as the argument. If the server ctime differs from
3760  *    what is cached on the client, the verify will fail, but we would
3761  *    already have the ctime from the preceding getattr, so just set it
3762  *    and retry. Thus the compound here is - { Putfh <fh>; Getattr; Verify;
3763  *      Setattr; Getattr }.
3764  *
3765  * The vsecattr_t * input parameter will be non-NULL if ACLs are being set in
3766  * this setattr and NULL if they are not.
3767  */
3768 static int


8051          */
8052         mutex_enter(&rp->r_statelock);
8053         if (rp->r_unldvp != NULL) {
8054                 if (strcmp(rp->r_unlname, onm) == 0) {
8055                         (void) strncpy(rp->r_unlname, nnm, MAXNAMELEN);
8056                         rp->r_unlname[MAXNAMELEN - 1] = '\0';
8057                         if (ndvp != rp->r_unldvp) {
8058                                 VN_RELE(rp->r_unldvp);
8059                                 rp->r_unldvp = ndvp;
8060                                 VN_HOLD(ndvp);
8061                         }
8062                 }
8063         }
8064         mutex_exit(&rp->r_statelock);
8065 
8066         /*
8067          * Notify the rename vnevents to source vnode, and to the target
8068          * vnode if it already existed.
8069          */
8070         if (error == 0) {
8071                 vnode_t *tvp, *tovp;
8072                 rnode4_t *trp;
8073 
8074                 /*
8075                  * Notify the vnode. Each links is represented by
8076                  * a different vnode, in nfsv4.
8077                  */
8078                 if (nvp) {
8079                         trp = VTOR4(nvp);
8080                         tvp = nvp;
8081                         if (IS_SHADOW(nvp, trp))
8082                                 tvp = RTOV4(trp);
8083                         vnevent_rename_dest(tvp, ndvp, nnm, ct);
8084                 }
8085 
8086                 trp = VTOR4(ovp);
8087                 tovp = ovp;
8088                 if (IS_SHADOW(ovp, trp))
8089                         tovp = RTOV4(trp);
8090 
8091                 vnevent_rename_src(tovp, odvp, onm, ct);
8092 
8093                 trp = VTOR4(ndvp);
8094                 tvp = ndvp;
8095 
8096                 if (IS_SHADOW(ndvp, trp))
8097                         tvp = RTOV4(trp);


8098 
8099                 vnevent_rename_dest_dir(tvp, tovp, nnm, ct);




8100         }
8101 
8102         if (nvp) {
8103                 VN_RELE(nvp);
8104         }
8105         VN_RELE(ovp);
8106 
8107         nfs_rw_exit(&odrp->r_rwlock);
8108         nfs_rw_exit(&ndrp->r_rwlock);
8109 
8110         return (error);
8111 }
8112 
8113 /*
8114  * When the parent directory has changed, sv_dfh must be updated
8115  */
8116 static void
8117 update_parentdir_sfh(vnode_t *vp, vnode_t *ndvp)
8118 {
8119         svnode_t *sv = VTOSV(vp);


10988     offset_t offset, cred_t *cr, caller_context_t *ct)
10989 {
10990         int error;
10991 
10992         if (nfs_zone() != VTOMI4(vp)->mi_zone)
10993                 return (EIO);
10994         ASSERT(vp->v_type == VREG);
10995         if (cmd != F_FREESP)
10996                 return (EINVAL);
10997 
10998         error = convoff(vp, bfp, 0, offset);
10999         if (!error) {
11000                 ASSERT(bfp->l_start >= 0);
11001                 if (bfp->l_len == 0) {
11002                         struct vattr va;
11003 
11004                         va.va_mask = AT_SIZE;
11005                         va.va_size = bfp->l_start;
11006                         error = nfs4setattr(vp, &va, 0, cr, NULL);
11007 
11008                         if (error == 0) {
11009                                 if (bfp->l_start == 0) {
11010                                         vnevent_truncate(vp, ct);
11011                                 } else {
11012                                         vnevent_resize(vp, ct);
11013                                 }
11014                         }
11015                 } else
11016                         error = EINVAL;
11017         }
11018 
11019         return (error);
11020 }
11021 
11022 /* ARGSUSED */
11023 int
11024 nfs4_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
11025 {
11026         rnode4_t *rp;
11027         rp = VTOR4(vp);
11028 
11029         if (vp->v_type == VREG && IS_SHADOW(vp, rp)) {
11030                 vp = RTOV4(rp);
11031         }
11032         *vpp = vp;
11033         return (0);
11034 }