Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*


1227 
1228 /*
1229  * The following two accessor functions are for the NFSv4 server.  Since there
1230  * is no VOP_OPEN_UP/DOWNGRADE we need a way for the NFS server to keep the
1231  * vnode open counts correct when a client "upgrades" an open or does an
1232  * open_downgrade.  In NFS, an upgrade or downgrade can not only change the
1233  * open mode (add or subtract read or write), but also change the share/deny
1234  * modes.  However, share reservations are not integrated with OPEN, yet, so
1235  * we need to handle each separately.  These functions are cleaner than having
1236  * the NFS server manipulate the counts directly, however, nobody else should
1237  * use these functions.
1238  */
1239 void
1240 vn_open_upgrade(
1241         vnode_t *vp,
1242         int filemode)
1243 {
1244         ASSERT(vp->v_type == VREG);
1245 
1246         if (filemode & FREAD)
1247                 atomic_add_32(&(vp->v_rdcnt), 1);
1248         if (filemode & FWRITE)
1249                 atomic_add_32(&(vp->v_wrcnt), 1);
1250 
1251 }
1252 
1253 void
1254 vn_open_downgrade(
1255         vnode_t *vp,
1256         int filemode)
1257 {
1258         ASSERT(vp->v_type == VREG);
1259 
1260         if (filemode & FREAD) {
1261                 ASSERT(vp->v_rdcnt > 0);
1262                 atomic_add_32(&(vp->v_rdcnt), -1);
1263         }
1264         if (filemode & FWRITE) {
1265                 ASSERT(vp->v_wrcnt > 0);
1266                 atomic_add_32(&(vp->v_wrcnt), -1);
1267         }
1268 
1269 }
1270 
1271 int
1272 vn_create(
1273         char *pnamep,
1274         enum uio_seg seg,
1275         struct vattr *vap,
1276         enum vcexcl excl,
1277         int mode,
1278         struct vnode **vpp,
1279         enum create why,
1280         int flag,
1281         mode_t umask)
1282 {
1283         return (vn_createat(pnamep, seg, vap, excl, mode, vpp, why, flag,
1284             umask, NULL));
1285 }
1286 


2901                         loc = (fs_generic_func_p *)
2902                             ((char *)(vop) + otdp->offset);
2903                         break;
2904                 }
2905         }
2906 
2907         return ((loc != NULL) && (*loc == funcp));
2908 }
2909 
2910 /*
2911  * fs_new_caller_id() needs to return a unique ID on a given local system.
2912  * The IDs do not need to survive across reboots.  These are primarily
2913  * used so that (FEM) monitors can detect particular callers (such as
2914  * the NFS server) to a given vnode/vfs operation.
2915  */
2916 u_longlong_t
2917 fs_new_caller_id()
2918 {
2919         static uint64_t next_caller_id = 0LL; /* First call returns 1 */
2920 
2921         return ((u_longlong_t)atomic_add_64_nv(&next_caller_id, 1));
2922 }
2923 
2924 /*
2925  * Given a starting vnode and a path, updates the path in the target vnode in
2926  * a safe manner.  If the vnode already has path information embedded, then the
2927  * cached path is left untouched.
2928  */
2929 
2930 size_t max_vnode_path = 4 * MAXPATHLEN;
2931 
2932 void
2933 vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp,
2934     const char *path, size_t plen)
2935 {
2936         char    *rpath;
2937         vnode_t *base;
2938         size_t  rpathlen, rpathalloc;
2939         int     doslash = 1;
2940 
2941         if (*path == '/') {


3129         caller_context_t *ct)
3130 {
3131         int ret;
3132         vnode_t *vp = *vpp;
3133 
3134         VN_HOLD(vp);
3135         /*
3136          * Adding to the vnode counts before calling open
3137          * avoids the need for a mutex. It circumvents a race
3138          * condition where a query made on the vnode counts results in a
3139          * false negative. The inquirer goes away believing the file is
3140          * not open when there is an open on the file already under way.
3141          *
3142          * The counts are meant to prevent NFS from granting a delegation
3143          * when it would be dangerous to do so.
3144          *
3145          * The vnode counts are only kept on regular files
3146          */
3147         if ((*vpp)->v_type == VREG) {
3148                 if (mode & FREAD)
3149                         atomic_add_32(&((*vpp)->v_rdcnt), 1);
3150                 if (mode & FWRITE)
3151                         atomic_add_32(&((*vpp)->v_wrcnt), 1);
3152         }
3153 
3154         VOPXID_MAP_CR(vp, cr);
3155 
3156         ret = (*(*(vpp))->v_op->vop_open)(vpp, mode, cr, ct);
3157 
3158         if (ret) {
3159                 /*
3160                  * Use the saved vp just in case the vnode ptr got trashed
3161                  * by the error.
3162                  */
3163                 VOPSTATS_UPDATE(vp, open);
3164                 if ((vp->v_type == VREG) && (mode & FREAD))
3165                         atomic_add_32(&(vp->v_rdcnt), -1);
3166                 if ((vp->v_type == VREG) && (mode & FWRITE))
3167                         atomic_add_32(&(vp->v_wrcnt), -1);
3168         } else {
3169                 /*
3170                  * Some filesystems will return a different vnode,
3171                  * but the same path was still used to open it.
3172                  * So if we do change the vnode and need to
3173                  * copy over the path, do so here, rather than special
3174                  * casing each filesystem. Adjust the vnode counts to
3175                  * reflect the vnode switch.
3176                  */
3177                 VOPSTATS_UPDATE(*vpp, open);
3178                 if (*vpp != vp && *vpp != NULL) {
3179                         vn_copypath(vp, *vpp);
3180                         if (((*vpp)->v_type == VREG) && (mode & FREAD))
3181                                 atomic_add_32(&((*vpp)->v_rdcnt), 1);
3182                         if ((vp->v_type == VREG) && (mode & FREAD))
3183                                 atomic_add_32(&(vp->v_rdcnt), -1);
3184                         if (((*vpp)->v_type == VREG) && (mode & FWRITE))
3185                                 atomic_add_32(&((*vpp)->v_wrcnt), 1);
3186                         if ((vp->v_type == VREG) && (mode & FWRITE))
3187                                 atomic_add_32(&(vp->v_wrcnt), -1);
3188                 }
3189         }
3190         VN_RELE(vp);
3191         return (ret);
3192 }
3193 
3194 int
3195 fop_close(
3196         vnode_t *vp,
3197         int flag,
3198         int count,
3199         offset_t offset,
3200         cred_t *cr,
3201         caller_context_t *ct)
3202 {
3203         int err;
3204 
3205         VOPXID_MAP_CR(vp, cr);
3206 
3207         err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr, ct);
3208         VOPSTATS_UPDATE(vp, close);
3209         /*
3210          * Check passed in count to handle possible dups. Vnode counts are only
3211          * kept on regular files
3212          */
3213         if ((vp->v_type == VREG) && (count == 1))  {
3214                 if (flag & FREAD) {
3215                         ASSERT(vp->v_rdcnt > 0);
3216                         atomic_add_32(&(vp->v_rdcnt), -1);
3217                 }
3218                 if (flag & FWRITE) {
3219                         ASSERT(vp->v_wrcnt > 0);
3220                         atomic_add_32(&(vp->v_wrcnt), -1);
3221                 }
3222         }
3223         return (err);
3224 }
3225 
3226 int
3227 fop_read(
3228         vnode_t *vp,
3229         uio_t *uiop,
3230         int ioflag,
3231         cred_t *cr,
3232         caller_context_t *ct)
3233 {
3234         int     err;
3235         ssize_t resid_start = uiop->uio_resid;
3236 
3237         VOPXID_MAP_CR(vp, cr);
3238 
3239         err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct);
3240         VOPSTATS_UPDATE_IO(vp, read,




1227 
1228 /*
1229  * The following two accessor functions are for the NFSv4 server.  Since there
1230  * is no VOP_OPEN_UP/DOWNGRADE we need a way for the NFS server to keep the
1231  * vnode open counts correct when a client "upgrades" an open or does an
1232  * open_downgrade.  In NFS, an upgrade or downgrade can not only change the
1233  * open mode (add or subtract read or write), but also change the share/deny
1234  * modes.  However, share reservations are not integrated with OPEN, yet, so
1235  * we need to handle each separately.  These functions are cleaner than having
1236  * the NFS server manipulate the counts directly, however, nobody else should
1237  * use these functions.
1238  */
1239 void
1240 vn_open_upgrade(
1241         vnode_t *vp,
1242         int filemode)
1243 {
1244         ASSERT(vp->v_type == VREG);
1245 
1246         if (filemode & FREAD)
1247                 atomic_inc_32(&vp->v_rdcnt);
1248         if (filemode & FWRITE)
1249                 atomic_inc_32(&vp->v_wrcnt);
1250 
1251 }
1252 
1253 void
1254 vn_open_downgrade(
1255         vnode_t *vp,
1256         int filemode)
1257 {
1258         ASSERT(vp->v_type == VREG);
1259 
1260         if (filemode & FREAD) {
1261                 ASSERT(vp->v_rdcnt > 0);
1262                 atomic_dec_32(&vp->v_rdcnt);
1263         }
1264         if (filemode & FWRITE) {
1265                 ASSERT(vp->v_wrcnt > 0);
1266                 atomic_dec_32(&vp->v_wrcnt);
1267         }
1268 
1269 }
1270 
1271 int
1272 vn_create(
1273         char *pnamep,
1274         enum uio_seg seg,
1275         struct vattr *vap,
1276         enum vcexcl excl,
1277         int mode,
1278         struct vnode **vpp,
1279         enum create why,
1280         int flag,
1281         mode_t umask)
1282 {
1283         return (vn_createat(pnamep, seg, vap, excl, mode, vpp, why, flag,
1284             umask, NULL));
1285 }
1286 


2901                         loc = (fs_generic_func_p *)
2902                             ((char *)(vop) + otdp->offset);
2903                         break;
2904                 }
2905         }
2906 
2907         return ((loc != NULL) && (*loc == funcp));
2908 }
2909 
2910 /*
2911  * fs_new_caller_id() needs to return a unique ID on a given local system.
2912  * The IDs do not need to survive across reboots.  These are primarily
2913  * used so that (FEM) monitors can detect particular callers (such as
2914  * the NFS server) to a given vnode/vfs operation.
2915  */
2916 u_longlong_t
2917 fs_new_caller_id()
2918 {
2919         static uint64_t next_caller_id = 0LL; /* First call returns 1 */
2920 
2921         return ((u_longlong_t)atomic_inc_64_nv(&next_caller_id));
2922 }
2923 
2924 /*
2925  * Given a starting vnode and a path, updates the path in the target vnode in
2926  * a safe manner.  If the vnode already has path information embedded, then the
2927  * cached path is left untouched.
2928  */
2929 
2930 size_t max_vnode_path = 4 * MAXPATHLEN;
2931 
2932 void
2933 vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp,
2934     const char *path, size_t plen)
2935 {
2936         char    *rpath;
2937         vnode_t *base;
2938         size_t  rpathlen, rpathalloc;
2939         int     doslash = 1;
2940 
2941         if (*path == '/') {


3129         caller_context_t *ct)
3130 {
3131         int ret;
3132         vnode_t *vp = *vpp;
3133 
3134         VN_HOLD(vp);
3135         /*
3136          * Adding to the vnode counts before calling open
3137          * avoids the need for a mutex. It circumvents a race
3138          * condition where a query made on the vnode counts results in a
3139          * false negative. The inquirer goes away believing the file is
3140          * not open when there is an open on the file already under way.
3141          *
3142          * The counts are meant to prevent NFS from granting a delegation
3143          * when it would be dangerous to do so.
3144          *
3145          * The vnode counts are only kept on regular files
3146          */
3147         if ((*vpp)->v_type == VREG) {
3148                 if (mode & FREAD)
3149                         atomic_inc_32(&(*vpp)->v_rdcnt);
3150                 if (mode & FWRITE)
3151                         atomic_inc_32(&(*vpp)->v_wrcnt);
3152         }
3153 
3154         VOPXID_MAP_CR(vp, cr);
3155 
3156         ret = (*(*(vpp))->v_op->vop_open)(vpp, mode, cr, ct);
3157 
3158         if (ret) {
3159                 /*
3160                  * Use the saved vp just in case the vnode ptr got trashed
3161                  * by the error.
3162                  */
3163                 VOPSTATS_UPDATE(vp, open);
3164                 if ((vp->v_type == VREG) && (mode & FREAD))
3165                         atomic_dec_32(&vp->v_rdcnt);
3166                 if ((vp->v_type == VREG) && (mode & FWRITE))
3167                         atomic_dec_32(&vp->v_wrcnt);
3168         } else {
3169                 /*
3170                  * Some filesystems will return a different vnode,
3171                  * but the same path was still used to open it.
3172                  * So if we do change the vnode and need to
3173                  * copy over the path, do so here, rather than special
3174                  * casing each filesystem. Adjust the vnode counts to
3175                  * reflect the vnode switch.
3176                  */
3177                 VOPSTATS_UPDATE(*vpp, open);
3178                 if (*vpp != vp && *vpp != NULL) {
3179                         vn_copypath(vp, *vpp);
3180                         if (((*vpp)->v_type == VREG) && (mode & FREAD))
3181                                 atomic_inc_32(&(*vpp)->v_rdcnt);
3182                         if ((vp->v_type == VREG) && (mode & FREAD))
3183                                 atomic_dec_32(&vp->v_rdcnt);
3184                         if (((*vpp)->v_type == VREG) && (mode & FWRITE))
3185                                 atomic_inc_32(&(*vpp)->v_wrcnt);
3186                         if ((vp->v_type == VREG) && (mode & FWRITE))
3187                                 atomic_dec_32(&vp->v_wrcnt);
3188                 }
3189         }
3190         VN_RELE(vp);
3191         return (ret);
3192 }
3193 
3194 int
3195 fop_close(
3196         vnode_t *vp,
3197         int flag,
3198         int count,
3199         offset_t offset,
3200         cred_t *cr,
3201         caller_context_t *ct)
3202 {
3203         int err;
3204 
3205         VOPXID_MAP_CR(vp, cr);
3206 
3207         err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr, ct);
3208         VOPSTATS_UPDATE(vp, close);
3209         /*
3210          * Check passed in count to handle possible dups. Vnode counts are only
3211          * kept on regular files
3212          */
3213         if ((vp->v_type == VREG) && (count == 1))  {
3214                 if (flag & FREAD) {
3215                         ASSERT(vp->v_rdcnt > 0);
3216                         atomic_dec_32(&vp->v_rdcnt);
3217                 }
3218                 if (flag & FWRITE) {
3219                         ASSERT(vp->v_wrcnt > 0);
3220                         atomic_dec_32(&vp->v_wrcnt);
3221                 }
3222         }
3223         return (err);
3224 }
3225 
3226 int
3227 fop_read(
3228         vnode_t *vp,
3229         uio_t *uiop,
3230         int ioflag,
3231         cred_t *cr,
3232         caller_context_t *ct)
3233 {
3234         int     err;
3235         ssize_t resid_start = uiop->uio_resid;
3236 
3237         VOPXID_MAP_CR(vp, cr);
3238 
3239         err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct);
3240         VOPSTATS_UPDATE_IO(vp, read,