diff options
Diffstat (limited to 'usr/src/uts/common/fs/vnode.c')
| -rw-r--r-- | usr/src/uts/common/fs/vnode.c | 646 |
1 files changed, 598 insertions, 48 deletions
diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index 4d562852af..66be3f73b9 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -76,6 +75,70 @@ int nfs_global_client_only; /* + * Array of vopstats_t for per-FS-type vopstats. This array has the same + * number of entries as and parallel to the vfssw table. (Arguably, it could + * be part of the vfssw table.) Once it's initialized, it's accessed using + * the same fstype index that is used to index into the vfssw table. + */ +vopstats_t **vopstats_fstype; + +/* vopstats initialization template used for fast initialization via bcopy() */ +static vopstats_t *vs_templatep; + +/* Kmem cache handle for vsk_anchor_t allocations */ +kmem_cache_t *vsk_anchor_cache; + +/* + * Root of AVL tree for the kstats associated with vopstats. Lock protects + * updates to vsktat_tree. + */ +avl_tree_t vskstat_tree; +kmutex_t vskstat_tree_lock; + +/* Global variable which enables/disables the vopstats collection */ +int vopstats_enabled = 1; + +/* + * The following is the common set of actions needed to update the + * vopstats structure from a vnode op. Both VOPSTATS_UPDATE() and + * VOPSTATS_UPDATE_IO() do almost the same thing, except for the + * recording of the bytes transferred. Since the code is similar + * but small, it is nearly a duplicate. Consequently any changes + * to one may need to be reflected in the other. + * Rundown of the variables: + * vp - Pointer to the vnode + * counter - Partial name structure member to update in vopstats for counts + * bytecounter - Partial name structure member to update in vopstats for bytes + * bytesval - Value to update in vopstats for bytes + * fstype - Index into vsanchor_fstype[], same as index into vfssw[] + * vsp - Pointer to vopstats structure (either in vfs or vsanchor_fstype[i]) + */ + +#define VOPSTATS_UPDATE(vp, counter) { \ + vfs_t *vfsp = (vp)->v_vfsp; \ + if (vfsp && (vfsp->vfs_flag & VFS_STATS) && (vp)->v_type != VBAD) { \ + vopstats_t *vsp = &vfsp->vfs_vopstats; \ + vsp->counter.value.ui64++; \ + if ((vsp = vfsp->vfs_fstypevsp) != NULL) { \ + vsp->counter.value.ui64++; \ + } \ + } \ +} + +#define VOPSTATS_UPDATE_IO(vp, counter, bytecounter, bytesval) { \ + vfs_t *vfsp = (vp)->v_vfsp; \ + if (vfsp && (vfsp->vfs_flag & VFS_STATS) && (vp)->v_type != VBAD) { \ + vopstats_t *vsp = &vfsp->vfs_vopstats; \ + vsp->counter.value.ui64++; \ + vsp->bytecounter.value.ui64 += bytesval; \ + if ((vsp = vfsp->vfs_fstypevsp) != NULL) { \ + vsp->counter.value.ui64++; \ + vsp->bytecounter.value.ui64 += bytesval; \ + } \ + } \ +} + +/* * Convert stat(2) formats to vnode types and vice versa. (Knows about * numerical order of S_IFMT and vnode types.) */ @@ -241,6 +304,329 @@ static const fs_operation_trans_def_t vn_ops_table[] = { NULL, 0, NULL, NULL }; +/* + * Used by the AVL routines to compare two vsk_anchor_t structures in the tree. + * We use the f_fsid reported by VFS_STATVFS() since we use that for the + * kstat name. + */ +static int +vska_compar(const void *n1, const void *n2) +{ + int ret; + ulong_t p1 = ((vsk_anchor_t *)n1)->vsk_fsid; + ulong_t p2 = ((vsk_anchor_t *)n2)->vsk_fsid; + + if (p1 < p2) { + ret = -1; + } else if (p1 > p2) { + ret = 1; + } else { + ret = 0; + } + + return (ret); +} + +/* + * Used to create a single template which will be bcopy()ed to a newly + * allocated vsanchor_combo_t structure in new_vsanchor(), below. + */ +static vopstats_t * +create_vopstats_template() +{ + vopstats_t *vsp; + + vsp = kmem_alloc(sizeof (vopstats_t), KM_SLEEP); + bzero(vsp, sizeof (*vsp)); /* Start fresh */ + + /* VOP_OPEN */ + kstat_named_init(&vsp->nopen, "nopen", KSTAT_DATA_UINT64); + /* VOP_CLOSE */ + kstat_named_init(&vsp->nclose, "nclose", KSTAT_DATA_UINT64); + /* VOP_READ I/O */ + kstat_named_init(&vsp->nread, "nread", KSTAT_DATA_UINT64); + kstat_named_init(&vsp->read_bytes, "read_bytes", KSTAT_DATA_UINT64); + /* VOP_WRITE I/O */ + kstat_named_init(&vsp->nwrite, "nwrite", KSTAT_DATA_UINT64); + kstat_named_init(&vsp->write_bytes, "write_bytes", KSTAT_DATA_UINT64); + /* VOP_IOCTL */ + kstat_named_init(&vsp->nioctl, "nioctl", KSTAT_DATA_UINT64); + /* VOP_SETFL */ + kstat_named_init(&vsp->nsetfl, "nsetfl", KSTAT_DATA_UINT64); + /* VOP_GETATTR */ + kstat_named_init(&vsp->ngetattr, "ngetattr", KSTAT_DATA_UINT64); + /* VOP_SETATTR */ + kstat_named_init(&vsp->nsetattr, "nsetattr", KSTAT_DATA_UINT64); + /* VOP_ACCESS */ + kstat_named_init(&vsp->naccess, "naccess", KSTAT_DATA_UINT64); + /* VOP_LOOKUP */ + kstat_named_init(&vsp->nlookup, "nlookup", KSTAT_DATA_UINT64); + /* VOP_CREATE */ + kstat_named_init(&vsp->ncreate, "ncreate", KSTAT_DATA_UINT64); + /* VOP_REMOVE */ + kstat_named_init(&vsp->nremove, "nremove", KSTAT_DATA_UINT64); + /* VOP_LINK */ + kstat_named_init(&vsp->nlink, "nlink", KSTAT_DATA_UINT64); + /* VOP_RENAME */ + kstat_named_init(&vsp->nrename, "nrename", KSTAT_DATA_UINT64); + /* VOP_MKDIR */ + kstat_named_init(&vsp->nmkdir, "nmkdir", KSTAT_DATA_UINT64); + /* VOP_RMDIR */ + kstat_named_init(&vsp->nrmdir, "nrmdir", KSTAT_DATA_UINT64); + /* VOP_READDIR I/O */ + kstat_named_init(&vsp->nreaddir, "nreaddir", KSTAT_DATA_UINT64); + kstat_named_init(&vsp->readdir_bytes, "readdir_bytes", + KSTAT_DATA_UINT64); + /* VOP_SYMLINK */ + kstat_named_init(&vsp->nsymlink, "nsymlink", KSTAT_DATA_UINT64); + /* VOP_READLINK */ + kstat_named_init(&vsp->nreadlink, "nreadlink", KSTAT_DATA_UINT64); + /* VOP_FSYNC */ + kstat_named_init(&vsp->nfsync, "nfsync", KSTAT_DATA_UINT64); + /* VOP_INACTIVE */ + kstat_named_init(&vsp->ninactive, "ninactive", KSTAT_DATA_UINT64); + /* VOP_FID */ + kstat_named_init(&vsp->nfid, "nfid", KSTAT_DATA_UINT64); + /* VOP_RWLOCK */ + kstat_named_init(&vsp->nrwlock, "nrwlock", KSTAT_DATA_UINT64); + /* VOP_RWUNLOCK */ + kstat_named_init(&vsp->nrwunlock, "nrwunlock", KSTAT_DATA_UINT64); + /* VOP_SEEK */ + kstat_named_init(&vsp->nseek, "nseek", KSTAT_DATA_UINT64); + /* VOP_CMP */ + kstat_named_init(&vsp->ncmp, "ncmp", KSTAT_DATA_UINT64); + /* VOP_FRLOCK */ + kstat_named_init(&vsp->nfrlock, "nfrlock", KSTAT_DATA_UINT64); + /* VOP_SPACE */ + kstat_named_init(&vsp->nspace, "nspace", KSTAT_DATA_UINT64); + /* VOP_REALVP */ + kstat_named_init(&vsp->nrealvp, "nrealvp", KSTAT_DATA_UINT64); + /* VOP_GETPAGE */ + kstat_named_init(&vsp->ngetpage, "ngetpage", KSTAT_DATA_UINT64); + /* VOP_PUTPAGE */ + kstat_named_init(&vsp->nputpage, "nputpage", KSTAT_DATA_UINT64); + /* VOP_MAP */ + kstat_named_init(&vsp->nmap, "nmap", KSTAT_DATA_UINT64); + /* VOP_ADDMAP */ + kstat_named_init(&vsp->naddmap, "naddmap", KSTAT_DATA_UINT64); + /* VOP_DELMAP */ + kstat_named_init(&vsp->ndelmap, "ndelmap", KSTAT_DATA_UINT64); + /* VOP_POLL */ + kstat_named_init(&vsp->npoll, "npoll", KSTAT_DATA_UINT64); + /* VOP_DUMP */ + kstat_named_init(&vsp->ndump, "ndump", KSTAT_DATA_UINT64); + /* VOP_PATHCONF */ + kstat_named_init(&vsp->npathconf, "npathconf", KSTAT_DATA_UINT64); + /* VOP_PAGEIO */ + kstat_named_init(&vsp->npageio, "npageio", KSTAT_DATA_UINT64); + /* VOP_DUMPCTL */ + kstat_named_init(&vsp->ndumpctl, "ndumpctl", KSTAT_DATA_UINT64); + /* VOP_DISPOSE */ + kstat_named_init(&vsp->ndispose, "ndispose", KSTAT_DATA_UINT64); + /* VOP_SETSECATTR */ + kstat_named_init(&vsp->nsetsecattr, "nsetsecattr", KSTAT_DATA_UINT64); + /* VOP_GETSECATTR */ + kstat_named_init(&vsp->ngetsecattr, "ngetsecattr", KSTAT_DATA_UINT64); + /* VOP_SHRLOCK */ + kstat_named_init(&vsp->nshrlock, "nshrlock", KSTAT_DATA_UINT64); + /* VOP_VNEVENT */ + kstat_named_init(&vsp->nvnevent, "nvnevent", KSTAT_DATA_UINT64); + + return (vsp); +} + +/* + * Creates a kstat structure associated with a vopstats structure. + */ +kstat_t * +new_vskstat(char *ksname, vopstats_t *vsp) +{ + kstat_t *ksp; + + if (!vopstats_enabled) { + return (NULL); + } + + ksp = kstat_create("unix", 0, ksname, "misc", KSTAT_TYPE_NAMED, + sizeof (vopstats_t)/sizeof (kstat_named_t), + KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_WRITABLE); + if (ksp) { + ksp->ks_data = vsp; + kstat_install(ksp); + } + + return (ksp); +} + +/* + * Called from vfsinit() to initialize the support mechanisms for vopstats + */ +void +vopstats_startup() +{ + if (!vopstats_enabled) + return; + + /* + * Creates the AVL tree which holds per-vfs vopstat anchors. This + * is necessary since we need to check if a kstat exists before we + * attempt to create it. Also, initialize its lock. + */ + avl_create(&vskstat_tree, vska_compar, sizeof (vsk_anchor_t), + offsetof(vsk_anchor_t, vsk_node)); + mutex_init(&vskstat_tree_lock, NULL, MUTEX_DEFAULT, NULL); + + vsk_anchor_cache = kmem_cache_create("vsk_anchor_cache", + sizeof (vsk_anchor_t), sizeof (uintptr_t), NULL, NULL, NULL, + NULL, NULL, 0); + + /* + * Set up the array of pointers for the vopstats-by-FS-type. + * The entries will be allocated/initialized as each file system + * goes through modload/mod_installfs. + */ + vopstats_fstype = (vopstats_t **)kmem_zalloc( + (sizeof (vopstats_t *) * nfstype), KM_SLEEP); + + /* Set up the global vopstats initialization template */ + vs_templatep = create_vopstats_template(); +} + +/* + * We need to have the all of the counters zeroed. + * The initialization of the vopstats_t includes on the order of + * 50 calls to kstat_named_init(). Rather that do that on every call, + * we do it once in a template (vs_templatep) then bcopy it over. + */ +void +initialize_vopstats(vopstats_t *vsp) +{ + if (vsp == NULL) + return; + + bcopy(vs_templatep, vsp, sizeof (vopstats_t)); +} + +/* + * Create and initialize the vopstat structure for a vfs. Also, generate + * a kstat name, create the kstat structure, and associate it with the + * vfs' vopstats. This must only be called from mount. + */ +void +setup_vopstats(vfs_t *vfsp) +{ + int fstype = 0; /* Index into vfssw[] */ + char kstatstr[KSTAT_STRLEN]; /* kstat name for vopstats */ + statvfs64_t statvfsbuf; /* Needed to find f_fsid */ + vsk_anchor_t *vskp; /* vfs <--> kstat anchor */ + vfsops_t *vfsops; /* vfs operations vector */ + vfssw_t *vswp; /* Ptr into vfssw[] table */ + kstat_t *ksp; /* Ptr to new kstat */ + avl_index_t where; /* Location in the AVL tree */ + + if (vfsp == NULL || (vfsp->vfs_flag & VFS_STATS) == 0 || + !vopstats_enabled) + return; + + initialize_vopstats(&vfsp->vfs_vopstats); + + /* + * Set up the fstype. We go to so much trouble because all versions + * of NFS use the same fstype in their vfs even though they have + * distinct entries in the vfssw[] table. + */ + if (vfsp && (vfsops = vfs_getops(vfsp)) != NULL) { + vswp = vfs_getvfsswbyvfsops(vfsops); + /* A special vfs (e.g., EIO_vfs) may not have an entry */ + if (vswp) { + fstype = vswp - vfssw; /* Gets us the index */ + vfs_unrefvfssw(vswp); /* Must release reference */ + } + } else { + fstype = vfsp->vfs_fstype; + } + + /* + * Point to the per-fstype vopstats. The only valid values are + * non-zero positive values less than the number of vfssw[] table + * entries. + */ + if (fstype > 0 && fstype < nfstype) { + vfsp->vfs_fstypevsp = vopstats_fstype[fstype]; + } else { + /* Otherwise, never attempt to update stats by fstype */ + vfsp->vfs_fstypevsp = NULL; + } + + /* Need to get the fsid to build a kstat name */ + if (VFS_STATVFS(vfsp, &statvfsbuf) == 0) { + /* Create a name for our kstats based on fsid */ + (void) snprintf(kstatstr, KSTAT_STRLEN, "%s%lx", + VOPSTATS_STR, statvfsbuf.f_fsid); + + /* Allocate and initialize the vsk_anchor_t */ + vskp = kmem_cache_alloc(vsk_anchor_cache, KM_SLEEP); + bzero(vskp, sizeof (*vskp)); + vskp->vsk_fsid = statvfsbuf.f_fsid; + vfsp->vfs_vskap = vskp; + + mutex_enter(&vskstat_tree_lock); + if (avl_find(&vskstat_tree, vskp, &where) == NULL) { + avl_insert(&vskstat_tree, vskp, where); + mutex_exit(&vskstat_tree_lock); + + /* + * Now that we've got the anchor in the AVL + * tree, we can create the kstat. + */ + ksp = new_vskstat(kstatstr, &vfsp->vfs_vopstats); + if (ksp) { + vskp->vsk_ksp = ksp; + } + } else { + /* Oops, found one! Release memory and lock. */ + mutex_exit(&vskstat_tree_lock); + vfsp->vfs_vskap = NULL; + kmem_cache_free(vsk_anchor_cache, vskp); + } + } +} + +/* + * We're in the process of tearing down the vfs and need to cleanup + * the data structures associated with the vopstats. Must only be called + * from dounmount(). + */ +void +teardown_vopstats(vfs_t *vfsp) +{ + vsk_anchor_t *vskap; + avl_index_t where; + + if (vfsp == NULL || (vfsp->vfs_flag & VFS_STATS) == 0 || + !vopstats_enabled) + return; + + /* This is a safe check since VFS_STATS must be set (see above) */ + if ((vskap = vfsp->vfs_vskap) == NULL) + return; + + /* Whack the pointer right away */ + vfsp->vfs_vskap = NULL; + + /* Lock the tree, remove the node, and delete the kstat */ + mutex_enter(&vskstat_tree_lock); + if (avl_find(&vskstat_tree, vskap, &where)) { + avl_remove(&vskstat_tree, vskap); + } + + if (vskap->vsk_ksp) { + kstat_delete(vskap->vsk_ksp); + } + mutex_exit(&vskstat_tree_lock); + + kmem_cache_free(vsk_anchor_cache, vskap); +} /* * Read or write a vnode. Called from kernel code. @@ -2307,6 +2693,7 @@ fop_open( * Use the saved vp just in case the vnode ptr got trashed * by the error. */ + VOPSTATS_UPDATE(vp, nopen); if ((vp->v_type == VREG) && (mode & FREAD)) atomic_add_32(&(vp->v_rdcnt), -1); if ((vp->v_type == VREG) && (mode & FWRITE)) @@ -2320,7 +2707,7 @@ fop_open( * casing each filesystem. Adjust the vnode counts to * reflect the vnode switch. */ - + VOPSTATS_UPDATE(*vpp, nopen); if (*vpp != vp && *vpp != NULL) { vn_copypath(vp, *vpp); if (((*vpp)->v_type == VREG) && (mode & FREAD)) @@ -2345,8 +2732,10 @@ fop_close( offset_t offset, cred_t *cr) { - int error; - error = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr); + int err; + + err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr); + VOPSTATS_UPDATE(vp, nclose); /* * Check passed in count to handle possible dups. Vnode counts are only * kept on regular files @@ -2361,7 +2750,7 @@ fop_close( atomic_add_32(&(vp->v_wrcnt), -1); } } - return (error); + return (err); } int @@ -2372,7 +2761,13 @@ fop_read( cred_t *cr, struct caller_context *ct) { - return (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct); + int err; + ssize_t resid_start = uiop->uio_resid; + + err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct); + VOPSTATS_UPDATE_IO(vp, nread, + read_bytes, (resid_start - uiop->uio_resid)); + return (err); } int @@ -2383,7 +2778,13 @@ fop_write( cred_t *cr, struct caller_context *ct) { - return (*(vp)->v_op->vop_write)(vp, uiop, ioflag, cr, ct); + int err; + ssize_t resid_start = uiop->uio_resid; + + err = (*(vp)->v_op->vop_write)(vp, uiop, ioflag, cr, ct); + VOPSTATS_UPDATE_IO(vp, nwrite, + write_bytes, (resid_start - uiop->uio_resid)); + return (err); } int @@ -2395,7 +2796,11 @@ fop_ioctl( cred_t *cr, int *rvalp) { - return (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp); + int err; + + err = (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp); + VOPSTATS_UPDATE(vp, nioctl); + return (err); } int @@ -2405,7 +2810,11 @@ fop_setfl( int nflags, cred_t *cr) { - return (*(vp)->v_op->vop_setfl)(vp, oflags, nflags, cr); + int err; + + err = (*(vp)->v_op->vop_setfl)(vp, oflags, nflags, cr); + VOPSTATS_UPDATE(vp, nsetfl); + return (err); } int @@ -2415,7 +2824,11 @@ fop_getattr( int flags, cred_t *cr) { - return (*(vp)->v_op->vop_getattr)(vp, vap, flags, cr); + int err; + + err = (*(vp)->v_op->vop_getattr)(vp, vap, flags, cr); + VOPSTATS_UPDATE(vp, ngetattr); + return (err); } int @@ -2426,7 +2839,11 @@ fop_setattr( cred_t *cr, caller_context_t *ct) { - return (*(vp)->v_op->vop_setattr)(vp, vap, flags, cr, ct); + int err; + + err = (*(vp)->v_op->vop_setattr)(vp, vap, flags, cr, ct); + VOPSTATS_UPDATE(vp, nsetattr); + return (err); } int @@ -2436,7 +2853,11 @@ fop_access( int flags, cred_t *cr) { - return (*(vp)->v_op->vop_access)(vp, mode, flags, cr); + int err; + + err = (*(vp)->v_op->vop_access)(vp, mode, flags, cr); + VOPSTATS_UPDATE(vp, naccess); + return (err); } int @@ -2452,8 +2873,12 @@ fop_lookup( int ret; ret = (*(dvp)->v_op->vop_lookup)(dvp, nm, vpp, pnp, flags, rdir, cr); - if (ret == 0 && *vpp && (*vpp)->v_path == NULL) - vn_setpath(rootdir, dvp, *vpp, nm, strlen(nm)); + if (ret == 0 && *vpp) { + VOPSTATS_UPDATE(*vpp, nlookup); + if ((*vpp)->v_path == NULL) { + vn_setpath(rootdir, dvp, *vpp, nm, strlen(nm)); + } + } return (ret); } @@ -2473,8 +2898,12 @@ fop_create( ret = (*(dvp)->v_op->vop_create) (dvp, name, vap, excl, mode, vpp, cr, flag); - if (ret == 0 && *vpp && (*vpp)->v_path == NULL) - vn_setpath(rootdir, dvp, *vpp, name, strlen(name)); + if (ret == 0 && *vpp) { + VOPSTATS_UPDATE(*vpp, ncreate); + if ((*vpp)->v_path == NULL) { + vn_setpath(rootdir, dvp, *vpp, name, strlen(name)); + } + } return (ret); } @@ -2485,7 +2914,11 @@ fop_remove( char *nm, cred_t *cr) { - return (*(dvp)->v_op->vop_remove)(dvp, nm, cr); + int err; + + err = (*(dvp)->v_op->vop_remove)(dvp, nm, cr); + VOPSTATS_UPDATE(dvp, nremove); + return (err); } int @@ -2495,7 +2928,11 @@ fop_link( char *tnm, cred_t *cr) { - return (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr); + int err; + + err = (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr); + VOPSTATS_UPDATE(tdvp, nlink); + return (err); } int @@ -2506,7 +2943,11 @@ fop_rename( char *tnm, cred_t *cr) { - return (*(sdvp)->v_op->vop_rename)(sdvp, snm, tdvp, tnm, cr); + int err; + + err = (*(sdvp)->v_op->vop_rename)(sdvp, snm, tdvp, tnm, cr); + VOPSTATS_UPDATE(sdvp, nrename); + return (err); } int @@ -2520,8 +2961,13 @@ fop_mkdir( int ret; ret = (*(dvp)->v_op->vop_mkdir)(dvp, dirname, vap, vpp, cr); - if (ret == 0 && *vpp && (*vpp)->v_path == NULL) - vn_setpath(rootdir, dvp, *vpp, dirname, strlen(dirname)); + if (ret == 0 && *vpp) { + VOPSTATS_UPDATE(*vpp, nmkdir); + if ((*vpp)->v_path == NULL) { + vn_setpath(rootdir, dvp, *vpp, dirname, + strlen(dirname)); + } + } return (ret); } @@ -2533,7 +2979,11 @@ fop_rmdir( vnode_t *cdir, cred_t *cr) { - return (*(dvp)->v_op->vop_rmdir)(dvp, nm, cdir, cr); + int err; + + err = (*(dvp)->v_op->vop_rmdir)(dvp, nm, cdir, cr); + VOPSTATS_UPDATE(dvp, nrmdir); + return (err); } int @@ -2543,7 +2993,13 @@ fop_readdir( cred_t *cr, int *eofp) { - return (*(vp)->v_op->vop_readdir)(vp, uiop, cr, eofp); + int err; + ssize_t resid_start = uiop->uio_resid; + + err = (*(vp)->v_op->vop_readdir)(vp, uiop, cr, eofp); + VOPSTATS_UPDATE_IO(vp, nreaddir, + readdir_bytes, (resid_start - uiop->uio_resid)); + return (err); } int @@ -2554,7 +3010,11 @@ fop_symlink( char *target, cred_t *cr) { - return (*(dvp)->v_op->vop_symlink) (dvp, linkname, vap, target, cr); + int err; + + err = (*(dvp)->v_op->vop_symlink) (dvp, linkname, vap, target, cr); + VOPSTATS_UPDATE(dvp, nsymlink); + return (err); } int @@ -2563,7 +3023,11 @@ fop_readlink( uio_t *uiop, cred_t *cr) { - return (*(vp)->v_op->vop_readlink)(vp, uiop, cr); + int err; + + err = (*(vp)->v_op->vop_readlink)(vp, uiop, cr); + VOPSTATS_UPDATE(vp, nreadlink); + return (err); } int @@ -2572,7 +3036,11 @@ fop_fsync( int syncflag, cred_t *cr) { - return (*(vp)->v_op->vop_fsync)(vp, syncflag, cr); + int err; + + err = (*(vp)->v_op->vop_fsync)(vp, syncflag, cr); + VOPSTATS_UPDATE(vp, nfsync); + return (err); } void @@ -2580,6 +3048,8 @@ fop_inactive( vnode_t *vp, cred_t *cr) { + /* Need to update stats before vop call since we may lose the vnode */ + VOPSTATS_UPDATE(vp, ninactive); (*(vp)->v_op->vop_inactive)(vp, cr); } @@ -2588,7 +3058,11 @@ fop_fid( vnode_t *vp, fid_t *fidp) { - return (*(vp)->v_op->vop_fid)(vp, fidp); + int err; + + err = (*(vp)->v_op->vop_fid)(vp, fidp); + VOPSTATS_UPDATE(vp, nfid); + return (err); } int @@ -2597,7 +3071,11 @@ fop_rwlock( int write_lock, caller_context_t *ct) { - return ((*(vp)->v_op->vop_rwlock)(vp, write_lock, ct)); + int ret; + + ret = ((*(vp)->v_op->vop_rwlock)(vp, write_lock, ct)); + VOPSTATS_UPDATE(vp, nrwlock); + return (ret); } void @@ -2607,6 +3085,7 @@ fop_rwunlock( caller_context_t *ct) { (*(vp)->v_op->vop_rwunlock)(vp, write_lock, ct); + VOPSTATS_UPDATE(vp, nrwunlock); } int @@ -2615,7 +3094,11 @@ fop_seek( offset_t ooff, offset_t *noffp) { - return (*(vp)->v_op->vop_seek)(vp, ooff, noffp); + int err; + + err = (*(vp)->v_op->vop_seek)(vp, ooff, noffp); + VOPSTATS_UPDATE(vp, nseek); + return (err); } int @@ -2623,7 +3106,11 @@ fop_cmp( vnode_t *vp1, vnode_t *vp2) { - return (*(vp1)->v_op->vop_cmp)(vp1, vp2); + int err; + + err = (*(vp1)->v_op->vop_cmp)(vp1, vp2); + VOPSTATS_UPDATE(vp1, ncmp); + return (err); } int @@ -2636,8 +3123,12 @@ fop_frlock( struct flk_callback *flk_cbp, cred_t *cr) { - return (*(vp)->v_op->vop_frlock) + int err; + + err = (*(vp)->v_op->vop_frlock) (vp, cmd, bfp, flag, offset, flk_cbp, cr); + VOPSTATS_UPDATE(vp, nfrlock); + return (err); } int @@ -2650,7 +3141,11 @@ fop_space( cred_t *cr, caller_context_t *ct) { - return (*(vp)->v_op->vop_space)(vp, cmd, bfp, flag, offset, cr, ct); + int err; + + err = (*(vp)->v_op->vop_space)(vp, cmd, bfp, flag, offset, cr, ct); + VOPSTATS_UPDATE(vp, nspace); + return (err); } int @@ -2658,7 +3153,11 @@ fop_realvp( vnode_t *vp, vnode_t **vpp) { - return (*(vp)->v_op->vop_realvp)(vp, vpp); + int err; + + err = (*(vp)->v_op->vop_realvp)(vp, vpp); + VOPSTATS_UPDATE(vp, nrealvp); + return (err); } int @@ -2674,8 +3173,12 @@ fop_getpage( enum seg_rw rw, cred_t *cr) { - return (*(vp)->v_op->vop_getpage) + int err; + + err = (*(vp)->v_op->vop_getpage) (vp, off, len, protp, plarr, plsz, seg, addr, rw, cr); + VOPSTATS_UPDATE(vp, ngetpage); + return (err); } int @@ -2686,7 +3189,11 @@ fop_putpage( int flags, cred_t *cr) { - return (*(vp)->v_op->vop_putpage)(vp, off, len, flags, cr); + int err; + + err = (*(vp)->v_op->vop_putpage)(vp, off, len, flags, cr); + VOPSTATS_UPDATE(vp, nputpage); + return (err); } int @@ -2701,8 +3208,12 @@ fop_map( uint_t flags, cred_t *cr) { - return (*(vp)->v_op->vop_map) + int err; + + err = (*(vp)->v_op->vop_map) (vp, off, as, addrp, len, prot, maxprot, flags, cr); + VOPSTATS_UPDATE(vp, nmap); + return (err); } int @@ -2748,6 +3259,7 @@ fop_addmap( (int64_t)delta); } } + VOPSTATS_UPDATE(vp, naddmap); return (error); } @@ -2798,6 +3310,7 @@ fop_delmap( (int64_t)(-delta)); } } + VOPSTATS_UPDATE(vp, ndelmap); return (error); } @@ -2810,7 +3323,11 @@ fop_poll( short *reventsp, struct pollhead **phpp) { - return (*(vp)->v_op->vop_poll)(vp, events, anyyet, reventsp, phpp); + int err; + + err = (*(vp)->v_op->vop_poll)(vp, events, anyyet, reventsp, phpp); + VOPSTATS_UPDATE(vp, npoll); + return (err); } int @@ -2820,7 +3337,11 @@ fop_dump( int lbdn, int dblks) { - return (*(vp)->v_op->vop_dump)(vp, addr, lbdn, dblks); + int err; + + err = (*(vp)->v_op->vop_dump)(vp, addr, lbdn, dblks); + VOPSTATS_UPDATE(vp, ndump); + return (err); } int @@ -2830,7 +3351,11 @@ fop_pathconf( ulong_t *valp, cred_t *cr) { - return (*(vp)->v_op->vop_pathconf)(vp, cmd, valp, cr); + int err; + + err = (*(vp)->v_op->vop_pathconf)(vp, cmd, valp, cr); + VOPSTATS_UPDATE(vp, npathconf); + return (err); } int @@ -2842,7 +3367,11 @@ fop_pageio( int flags, cred_t *cr) { - return (*(vp)->v_op->vop_pageio)(vp, pp, io_off, io_len, flags, cr); + int err; + + err = (*(vp)->v_op->vop_pageio)(vp, pp, io_off, io_len, flags, cr); + VOPSTATS_UPDATE(vp, npageio); + return (err); } int @@ -2851,7 +3380,10 @@ fop_dumpctl( int action, int *blkp) { - return (*(vp)->v_op->vop_dumpctl)(vp, action, blkp); + int err; + err = (*(vp)->v_op->vop_dumpctl)(vp, action, blkp); + VOPSTATS_UPDATE(vp, ndumpctl); + return (err); } void @@ -2862,6 +3394,8 @@ fop_dispose( int dn, cred_t *cr) { + /* Must do stats first since it's possible to lose the vnode */ + VOPSTATS_UPDATE(vp, ndispose); (*(vp)->v_op->vop_dispose)(vp, pp, flag, dn, cr); } @@ -2872,7 +3406,11 @@ fop_setsecattr( int flag, cred_t *cr) { - return (*(vp)->v_op->vop_setsecattr) (vp, vsap, flag, cr); + int err; + + err = (*(vp)->v_op->vop_setsecattr) (vp, vsap, flag, cr); + VOPSTATS_UPDATE(vp, nsetsecattr); + return (err); } int @@ -2882,7 +3420,11 @@ fop_getsecattr( int flag, cred_t *cr) { - return (*(vp)->v_op->vop_getsecattr) (vp, vsap, flag, cr); + int err; + + err = (*(vp)->v_op->vop_getsecattr) (vp, vsap, flag, cr); + VOPSTATS_UPDATE(vp, ngetsecattr); + return (err); } int @@ -2893,11 +3435,19 @@ fop_shrlock( int flag, cred_t *cr) { - return (*(vp)->v_op->vop_shrlock)(vp, cmd, shr, flag, cr); + int err; + + err = (*(vp)->v_op->vop_shrlock)(vp, cmd, shr, flag, cr); + VOPSTATS_UPDATE(vp, nshrlock); + return (err); } int fop_vnevent(vnode_t *vp, vnevent_t vnevent) { - return (*(vp)->v_op->vop_vnevent)(vp, vnevent); + int err; + + err = (*(vp)->v_op->vop_vnevent)(vp, vnevent); + VOPSTATS_UPDATE(vp, nvnevent); + return (err); } |
