Print this page
basic FSH


  48 #include <sys/vfs.h>
  49 #include <sys/vfs_opreg.h>
  50 #include <sys/vnode.h>
  51 #include <sys/rwstlock.h>
  52 #include <sys/fem.h>
  53 #include <sys/stat.h>
  54 #include <sys/mode.h>
  55 #include <sys/conf.h>
  56 #include <sys/sysmacros.h>
  57 #include <sys/cmn_err.h>
  58 #include <sys/systm.h>
  59 #include <sys/kmem.h>
  60 #include <sys/debug.h>
  61 #include <c2/audit.h>
  62 #include <sys/acl.h>
  63 #include <sys/nbmlock.h>
  64 #include <sys/fcntl.h>
  65 #include <fs/fs_subr.h>
  66 #include <sys/taskq.h>
  67 #include <fs/fs_reparse.h>

  68 
  69 /* Determine if this vnode is a file that is read-only */
  70 #define ISROFILE(vp)    \
  71         ((vp)->v_type != VCHR && (vp)->v_type != VBLK && \
  72             (vp)->v_type != VFIFO && vn_is_readonly(vp))
  73 
  74 /* Tunable via /etc/system; used only by admin/install */
  75 int nfs_global_client_only;
  76 
  77 /*
  78  * Array of vopstats_t for per-FS-type vopstats.  This array has the same
  79  * number of entries as and parallel to the vfssw table.  (Arguably, it could
  80  * be part of the vfssw table.)  Once it's initialized, it's accessed using
  81  * the same fstype index that is used to index into the vfssw table.
  82  */
  83 vopstats_t **vopstats_fstype;
  84 
  85 /* vopstats initialization template used for fast initialization via bcopy() */
  86 static vopstats_t *vs_templatep;
  87 


3125          * Adding to the vnode counts before calling open
3126          * avoids the need for a mutex. It circumvents a race
3127          * condition where a query made on the vnode counts results in a
3128          * false negative. The inquirer goes away believing the file is
3129          * not open when there is an open on the file already under way.
3130          *
3131          * The counts are meant to prevent NFS from granting a delegation
3132          * when it would be dangerous to do so.
3133          *
3134          * The vnode counts are only kept on regular files
3135          */
3136         if ((*vpp)->v_type == VREG) {
3137                 if (mode & FREAD)
3138                         atomic_add_32(&((*vpp)->v_rdcnt), 1);
3139                 if (mode & FWRITE)
3140                         atomic_add_32(&((*vpp)->v_wrcnt), 1);
3141         }
3142 
3143         VOPXID_MAP_CR(vp, cr);
3144 
3145         ret = (*(*(vpp))->v_op->vop_open)(vpp, mode, cr, ct);
3146 
3147         if (ret) {
3148                 /*
3149                  * Use the saved vp just in case the vnode ptr got trashed
3150                  * by the error.
3151                  */
3152                 VOPSTATS_UPDATE(vp, open);
3153                 if ((vp->v_type == VREG) && (mode & FREAD))
3154                         atomic_add_32(&(vp->v_rdcnt), -1);
3155                 if ((vp->v_type == VREG) && (mode & FWRITE))
3156                         atomic_add_32(&(vp->v_wrcnt), -1);
3157         } else {
3158                 /*
3159                  * Some filesystems will return a different vnode,
3160                  * but the same path was still used to open it.
3161                  * So if we do change the vnode and need to
3162                  * copy over the path, do so here, rather than special
3163                  * casing each filesystem. Adjust the vnode counts to
3164                  * reflect the vnode switch.
3165                  */


3176                                 atomic_add_32(&(vp->v_wrcnt), -1);
3177                 }
3178         }
3179         VN_RELE(vp);
3180         return (ret);
3181 }
3182 
3183 int
3184 fop_close(
3185         vnode_t *vp,
3186         int flag,
3187         int count,
3188         offset_t offset,
3189         cred_t *cr,
3190         caller_context_t *ct)
3191 {
3192         int err;
3193 
3194         VOPXID_MAP_CR(vp, cr);
3195 
3196         err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr, ct);
3197         VOPSTATS_UPDATE(vp, close);
3198         /*
3199          * Check passed in count to handle possible dups. Vnode counts are only
3200          * kept on regular files
3201          */
3202         if ((vp->v_type == VREG) && (count == 1))  {
3203                 if (flag & FREAD) {
3204                         ASSERT(vp->v_rdcnt > 0);
3205                         atomic_add_32(&(vp->v_rdcnt), -1);
3206                 }
3207                 if (flag & FWRITE) {
3208                         ASSERT(vp->v_wrcnt > 0);
3209                         atomic_add_32(&(vp->v_wrcnt), -1);
3210                 }
3211         }
3212         return (err);
3213 }
3214 
3215 int
3216 fop_read(
3217         vnode_t *vp,
3218         uio_t *uiop,
3219         int ioflag,
3220         cred_t *cr,
3221         caller_context_t *ct)
3222 {
3223         int     err;
3224         ssize_t resid_start = uiop->uio_resid;
3225 
3226         VOPXID_MAP_CR(vp, cr);
3227 
3228         err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct);
3229         VOPSTATS_UPDATE_IO(vp, read,
3230             read_bytes, (resid_start - uiop->uio_resid));
3231         return (err);
3232 }
3233 
3234 int
3235 fop_write(
3236         vnode_t *vp,
3237         uio_t *uiop,
3238         int ioflag,
3239         cred_t *cr,
3240         caller_context_t *ct)
3241 {
3242         int     err;
3243         ssize_t resid_start = uiop->uio_resid;
3244 
3245         VOPXID_MAP_CR(vp, cr);
3246 
3247         err = (*(vp)->v_op->vop_write)(vp, uiop, ioflag, cr, ct);
3248         VOPSTATS_UPDATE_IO(vp, write,
3249             write_bytes, (resid_start - uiop->uio_resid));
3250         return (err);
3251 }
3252 
3253 int
3254 fop_ioctl(
3255         vnode_t *vp,
3256         int cmd,
3257         intptr_t arg,
3258         int flag,
3259         cred_t *cr,
3260         int *rvalp,
3261         caller_context_t *ct)
3262 {
3263         int     err;
3264 
3265         VOPXID_MAP_CR(vp, cr);
3266 
3267         err = (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp, ct);




  48 #include <sys/vfs.h>
  49 #include <sys/vfs_opreg.h>
  50 #include <sys/vnode.h>
  51 #include <sys/rwstlock.h>
  52 #include <sys/fem.h>
  53 #include <sys/stat.h>
  54 #include <sys/mode.h>
  55 #include <sys/conf.h>
  56 #include <sys/sysmacros.h>
  57 #include <sys/cmn_err.h>
  58 #include <sys/systm.h>
  59 #include <sys/kmem.h>
  60 #include <sys/debug.h>
  61 #include <c2/audit.h>
  62 #include <sys/acl.h>
  63 #include <sys/nbmlock.h>
  64 #include <sys/fcntl.h>
  65 #include <fs/fs_subr.h>
  66 #include <sys/taskq.h>
  67 #include <fs/fs_reparse.h>
  68 #include <sys/fsh_impl.h>
  69 
  70 /* Determine if this vnode is a file that is read-only */
  71 #define ISROFILE(vp)    \
  72         ((vp)->v_type != VCHR && (vp)->v_type != VBLK && \
  73             (vp)->v_type != VFIFO && vn_is_readonly(vp))
  74 
  75 /* Tunable via /etc/system; used only by admin/install */
  76 int nfs_global_client_only;
  77 
  78 /*
  79  * Array of vopstats_t for per-FS-type vopstats.  This array has the same
  80  * number of entries as and parallel to the vfssw table.  (Arguably, it could
  81  * be part of the vfssw table.)  Once it's initialized, it's accessed using
  82  * the same fstype index that is used to index into the vfssw table.
  83  */
  84 vopstats_t **vopstats_fstype;
  85 
  86 /* vopstats initialization template used for fast initialization via bcopy() */
  87 static vopstats_t *vs_templatep;
  88 


3126          * Adding to the vnode counts before calling open
3127          * avoids the need for a mutex. It circumvents a race
3128          * condition where a query made on the vnode counts results in a
3129          * false negative. The inquirer goes away believing the file is
3130          * not open when there is an open on the file already under way.
3131          *
3132          * The counts are meant to prevent NFS from granting a delegation
3133          * when it would be dangerous to do so.
3134          *
3135          * The vnode counts are only kept on regular files
3136          */
3137         if ((*vpp)->v_type == VREG) {
3138                 if (mode & FREAD)
3139                         atomic_add_32(&((*vpp)->v_rdcnt), 1);
3140                 if (mode & FWRITE)
3141                         atomic_add_32(&((*vpp)->v_wrcnt), 1);
3142         }
3143 
3144         VOPXID_MAP_CR(vp, cr);
3145 
3146         ret = fsh_open(vpp, mode, cr, ct);
3147 
3148         if (ret) {
3149                 /*
3150                  * Use the saved vp just in case the vnode ptr got trashed
3151                  * by the error.
3152                  */
3153                 VOPSTATS_UPDATE(vp, open);
3154                 if ((vp->v_type == VREG) && (mode & FREAD))
3155                         atomic_add_32(&(vp->v_rdcnt), -1);
3156                 if ((vp->v_type == VREG) && (mode & FWRITE))
3157                         atomic_add_32(&(vp->v_wrcnt), -1);
3158         } else {
3159                 /*
3160                  * Some filesystems will return a different vnode,
3161                  * but the same path was still used to open it.
3162                  * So if we do change the vnode and need to
3163                  * copy over the path, do so here, rather than special
3164                  * casing each filesystem. Adjust the vnode counts to
3165                  * reflect the vnode switch.
3166                  */


3177                                 atomic_add_32(&(vp->v_wrcnt), -1);
3178                 }
3179         }
3180         VN_RELE(vp);
3181         return (ret);
3182 }
3183 
3184 int
3185 fop_close(
3186         vnode_t *vp,
3187         int flag,
3188         int count,
3189         offset_t offset,
3190         cred_t *cr,
3191         caller_context_t *ct)
3192 {
3193         int err;
3194 
3195         VOPXID_MAP_CR(vp, cr);
3196 
3197         err = fsh_close(vp, flag, count, offset, cr, ct);
3198         VOPSTATS_UPDATE(vp, close);
3199         /*
3200          * Check passed in count to handle possible dups. Vnode counts are only
3201          * kept on regular files
3202          */
3203         if ((vp->v_type == VREG) && (count == 1))  {
3204                 if (flag & FREAD) {
3205                         ASSERT(vp->v_rdcnt > 0);
3206                         atomic_add_32(&(vp->v_rdcnt), -1);
3207                 }
3208                 if (flag & FWRITE) {
3209                         ASSERT(vp->v_wrcnt > 0);
3210                         atomic_add_32(&(vp->v_wrcnt), -1);
3211                 }
3212         }
3213         return (err);
3214 }
3215 
3216 int
3217 fop_read(
3218         vnode_t *vp,
3219         uio_t *uiop,
3220         int ioflag,
3221         cred_t *cr,
3222         caller_context_t *ct)
3223 {
3224         int     err;
3225         ssize_t resid_start = uiop->uio_resid;
3226 
3227         VOPXID_MAP_CR(vp, cr);
3228 
3229         err = fsh_read(vp, uiop, ioflag, cr, ct);
3230         VOPSTATS_UPDATE_IO(vp, read,
3231             read_bytes, (resid_start - uiop->uio_resid));
3232         return (err);
3233 }
3234 
3235 int
3236 fop_write(
3237         vnode_t *vp,
3238         uio_t *uiop,
3239         int ioflag,
3240         cred_t *cr,
3241         caller_context_t *ct)
3242 {
3243         int     err;
3244         ssize_t resid_start = uiop->uio_resid;
3245 
3246         VOPXID_MAP_CR(vp, cr);
3247 
3248         err = fsh_write(vp, uiop, ioflag, cr, ct);
3249         VOPSTATS_UPDATE_IO(vp, write,
3250             write_bytes, (resid_start - uiop->uio_resid));
3251         return (err);
3252 }
3253 
3254 int
3255 fop_ioctl(
3256         vnode_t *vp,
3257         int cmd,
3258         intptr_t arg,
3259         int flag,
3260         cred_t *cr,
3261         int *rvalp,
3262         caller_context_t *ct)
3263 {
3264         int     err;
3265 
3266         VOPXID_MAP_CR(vp, cr);
3267 
3268         err = (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp, ct);