/* * No locking required because I held the root vnode before calling this * function so the vfs won't disappear on me. To be more explicit: * fdvrootp->v_count will be greater than 1 so fdunmount will just return. */ static int fdstatvfs(struct vfs *vfsp, struct statvfs64 *sp) { dev32_t d32; rctl_qty_t fdno_ctl; mutex_enter(&curproc->p_lock); fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE], curproc->p_rctls, curproc); mutex_exit(&curproc->p_lock); bzero(sp, sizeof (*sp)); sp->f_bsize = 1024; sp->f_frsize = 1024; sp->f_blocks = (fsblkcnt64_t)0; sp->f_bfree = (fsblkcnt64_t)0; sp->f_bavail = (fsblkcnt64_t)0; sp->f_files = (fsfilcnt64_t) (MIN(P_FINFO(curproc)->fi_nfiles, fdno_ctl + 2)); sp->f_ffree = (fsfilcnt64_t)0; sp->f_favail = (fsfilcnt64_t)0; (void) cmpldev(&d32, vfsp->vfs_dev); sp->f_fsid = d32; (void) strcpy(sp->f_basetype, vfssw[fdfstype].vsw_name); sp->f_flag = vf_to_stf(vfsp->vfs_flag); sp->f_namemax = FDNSIZE; (void) strcpy(sp->f_fstr, "/dev/fd"); (void) strcpy(&sp->f_fstr[8], "/dev/fd"); return (0); }
/* * Return in sp the status of this file system. */ static int nm_statvfs(vfs_t *vfsp, struct statvfs64 *sp) { dev32_t d32; bzero(sp, sizeof (*sp)); sp->f_bsize = 1024; sp->f_frsize = 1024; (void) cmpldev(&d32, vfsp->vfs_dev); sp->f_fsid = d32; (void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); sp->f_flag = vf_to_stf(vfsp->vfs_flag); return (0); }
static int objfs_statvfs(vfs_t *vfsp, statvfs64_t *sp) { dev32_t d32; int total = objfs_nobjs(); bzero(sp, sizeof (*sp)); sp->f_bsize = DEV_BSIZE; sp->f_frsize = DEV_BSIZE; sp->f_files = total; sp->f_ffree = sp->f_favail = INT_MAX - total; (void) cmpldev(&d32, vfsp->vfs_dev); sp->f_fsid = d32; (void) strlcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name, sizeof (sp->f_basetype)); sp->f_flag = vf_to_stf(vfsp->vfs_flag); sp->f_namemax = OBJFS_NAME_MAX; (void) strlcpy(sp->f_fstr, "object", sizeof (sp->f_fstr)); return (0); }
/* * ctfs_statvfs - the VFS_STATVFS entry point */ static int ctfs_statvfs(vfs_t *vfsp, statvfs64_t *sp) { dev32_t d32; int total, i; bzero(sp, sizeof (*sp)); sp->f_bsize = DEV_BSIZE; sp->f_frsize = DEV_BSIZE; for (i = 0, total = 0; i < ct_ntypes; i++) total += contract_type_count(ct_types[i]); sp->f_files = total; sp->f_favail = sp->f_ffree = INT_MAX - total; (void) cmpldev(&d32, vfsp->vfs_dev); sp->f_fsid = d32; (void) strlcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name, sizeof (sp->f_basetype)); sp->f_flag = vf_to_stf(vfsp->vfs_flag); sp->f_namemax = CTFS_NAME_MAX; (void) strlcpy(sp->f_fstr, "contract", sizeof (sp->f_fstr)); return (0); }
static int zfs_vfs_getattr(struct mount *mp, struct vfs_attr *fsap, __unused vfs_context_t context) { zfsvfs_t *zfsvfs = vfs_fsprivate(mp); uint64_t refdbytes, availbytes, usedobjs, availobjs; ZFS_ENTER(zfsvfs); dmu_objset_space(zfsvfs->z_os, &refdbytes, &availbytes, &usedobjs, &availobjs); VFSATTR_RETURN(fsap, f_objcount, usedobjs); VFSATTR_RETURN(fsap, f_maxobjcount, 0x7fffffffffffffff); /* * Carbon depends on f_filecount and f_dircount so * make up some values based on total objects. */ VFSATTR_RETURN(fsap, f_filecount, usedobjs - (usedobjs / 4)); VFSATTR_RETURN(fsap, f_dircount, usedobjs / 4); /* * The underlying storage pool actually uses multiple block sizes. * We report the fragsize as the smallest block size we support, * and we report our blocksize as the filesystem's maximum blocksize. */ VFSATTR_RETURN(fsap, f_bsize, 1UL << SPA_MINBLOCKSHIFT); VFSATTR_RETURN(fsap, f_iosize, zfsvfs->z_max_blksz); /* * The following report "total" blocks of various kinds in the * file system, but reported in terms of f_frsize - the * "fragment" size. */ VFSATTR_RETURN(fsap, f_blocks, (u_int64_t)((refdbytes + availbytes) >> SPA_MINBLOCKSHIFT)); VFSATTR_RETURN(fsap, f_bfree, (u_int64_t)(availbytes >> SPA_MINBLOCKSHIFT)); VFSATTR_RETURN(fsap, f_bavail, fsap->f_bfree); /* no root reservation */ VFSATTR_RETURN(fsap, f_bused, fsap->f_blocks - fsap->f_bfree); /* * statvfs() should really be called statufs(), because it assumes * static metadata. ZFS doesn't preallocate files, so the best * we can do is report the max that could possibly fit in f_files, * and that minus the number actually used in f_ffree. * For f_ffree, report the smaller of the number of object available * and the number of blocks (each object will take at least a block). */ VFSATTR_RETURN(fsap, f_ffree, (u_int64_t)MIN(availobjs, fsap->f_bfree)); VFSATTR_RETURN(fsap, f_files, fsap->f_ffree + usedobjs); #if 0 statp->f_flag = vf_to_stf(vfsp->vfs_flag); #endif if (VFSATTR_IS_ACTIVE(fsap, f_fsid)) { VFSATTR_RETURN(fsap, f_fsid, vfs_statfs(mp)->f_fsid); } if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) { bcopy(&zfs_capabilities, &fsap->f_capabilities, sizeof (zfs_capabilities)); VFSATTR_SET_SUPPORTED(fsap, f_capabilities); } if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) { bcopy(&zfs_attributes, &fsap->f_attributes.validattr, sizeof (zfs_attributes)); bcopy(&zfs_attributes, &fsap->f_attributes.nativeattr, sizeof (zfs_attributes)); VFSATTR_SET_SUPPORTED(fsap, f_attributes); } if (VFSATTR_IS_ACTIVE(fsap, f_create_time)) { dmu_objset_stats_t dmu_stat; dmu_objset_fast_stat(zfsvfs->z_os, &dmu_stat); fsap->f_create_time.tv_sec = dmu_stat.dds_creation_time; fsap->f_create_time.tv_nsec = 0; VFSATTR_SET_SUPPORTED(fsap, f_create_time); } if (VFSATTR_IS_ACTIVE(fsap, f_modify_time)) { if (zfsvfs->z_mtime_vp != NULL) { znode_t *mzp; mzp = VTOZ(zfsvfs->z_mtime_vp); ZFS_TIME_DECODE(&fsap->f_modify_time, mzp->z_phys->zp_mtime); } else { fsap->f_modify_time.tv_sec = 0; fsap->f_modify_time.tv_nsec = 0; } VFSATTR_SET_SUPPORTED(fsap, f_modify_time); } /* * For Carbon compatibility, pretend to support this legacy/unused * attribute */ if (VFSATTR_IS_ACTIVE(fsap, f_backup_time)) { fsap->f_backup_time.tv_sec = 0; fsap->f_backup_time.tv_nsec = 0; VFSATTR_SET_SUPPORTED(fsap, f_backup_time); } if (VFSATTR_IS_ACTIVE(fsap, f_vol_name)) { spa_t *spa = dmu_objset_spa(zfsvfs->z_os); spa_config_enter(spa, RW_READER, FTAG); strlcpy(fsap->f_vol_name, spa_name(spa), MAXPATHLEN); spa_config_exit(spa, FTAG); VFSATTR_SET_SUPPORTED(fsap, f_vol_name); } VFSATTR_RETURN(fsap, f_fssubtype, 0); VFSATTR_RETURN(fsap, f_signature, 0x5a21); /* 'Z!' */ VFSATTR_RETURN(fsap, f_carbon_fsid, 0); ZFS_EXIT(zfsvfs); return (0); }
static int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp) { zfsvfs_t *zfsvfs = vfsp->vfs_data; dmu_objset_stats_t dstats; dev32_t d32; ZFS_ENTER(zfsvfs); dmu_objset_stats(zfsvfs->z_os, &dstats); /* * The underlying storage pool actually uses multiple block sizes. * We report the fragsize as the smallest block size we support, * and we report our blocksize as the filesystem's maximum blocksize. */ statp->f_frsize = 1UL << SPA_MINBLOCKSHIFT; statp->f_bsize = zfsvfs->z_max_blksz; /* * The following report "total" blocks of various kinds in the * file system, but reported in terms of f_frsize - the * "fragment" size. */ statp->f_blocks = (dstats.dds_space_refd + dstats.dds_available) >> SPA_MINBLOCKSHIFT; statp->f_bfree = dstats.dds_available >> SPA_MINBLOCKSHIFT; statp->f_bavail = statp->f_bfree; /* no root reservation */ /* * statvfs() should really be called statufs(), because it assumes * static metadata. ZFS doesn't preallocate files, so the best * we can do is report the max that could possibly fit in f_files, * and that minus the number actually used in f_ffree. * For f_ffree, report the smaller of the number of object available * and the number of blocks (each object will take at least a block). */ statp->f_ffree = MIN(dstats.dds_objects_avail, statp->f_bfree); statp->f_favail = statp->f_ffree; /* no "root reservation" */ statp->f_files = statp->f_ffree + dstats.dds_objects_used; (void) cmpldev(&d32, vfsp->vfs_dev); statp->f_fsid = d32; /* * We're a zfs filesystem. */ (void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); statp->f_flag = vf_to_stf(vfsp->vfs_flag); statp->f_namemax = ZFS_MAXNAMELEN; /* * We have all of 32 characters to stuff a string here. * Is there anything useful we could/should provide? */ bzero(statp->f_fstr, sizeof (statp->f_fstr)); ZFS_EXIT(zfsvfs); return (0); }
/* * Get file system statistics. */ static int smbfs_statvfs(vfs_t *vfsp, statvfs64_t *sbp) { int error; smbmntinfo_t *smi = VFTOSMI(vfsp); smb_share_t *ssp = smi->smi_share; statvfs64_t stvfs; hrtime_t now; smb_cred_t scred; if (curproc->p_zone != smi->smi_zone_ref.zref_zone) return (EPERM); if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) return (EIO); mutex_enter(&smi->smi_lock); /* * Use cached result if still valid. */ recheck: now = gethrtime(); if (now < smi->smi_statfstime) { error = 0; goto cache_hit; } /* * FS attributes are stale, so someone * needs to do an OTW call to get them. * Serialize here so only one thread * does the OTW call. */ if (smi->smi_status & SM_STATUS_STATFS_BUSY) { smi->smi_status |= SM_STATUS_STATFS_WANT; if (!cv_wait_sig(&smi->smi_statvfs_cv, &smi->smi_lock)) { mutex_exit(&smi->smi_lock); return (EINTR); } /* Hope status is valid now. */ goto recheck; } smi->smi_status |= SM_STATUS_STATFS_BUSY; mutex_exit(&smi->smi_lock); /* * Do the OTW call. Note: lock NOT held. */ smb_credinit(&scred, NULL); bzero(&stvfs, sizeof (stvfs)); error = smbfs_smb_statfs(ssp, &stvfs, &scred); smb_credrele(&scred); if (error) { SMBVDEBUG("statfs error=%d\n", error); } else { /* * Set a few things the OTW call didn't get. */ stvfs.f_frsize = stvfs.f_bsize; stvfs.f_favail = stvfs.f_ffree; stvfs.f_fsid = (unsigned long)vfsp->vfs_fsid.val[0]; bcopy(fs_type_name, stvfs.f_basetype, FSTYPSZ); stvfs.f_flag = vf_to_stf(vfsp->vfs_flag); stvfs.f_namemax = smi->smi_fsa.fsa_maxname; /* * Save the result, update lifetime */ now = gethrtime(); smi->smi_statfstime = now + (SM_MAX_STATFSTIME * (hrtime_t)NANOSEC); smi->smi_statvfsbuf = stvfs; /* struct assign! */ } mutex_enter(&smi->smi_lock); if (smi->smi_status & SM_STATUS_STATFS_WANT) cv_broadcast(&smi->smi_statvfs_cv); smi->smi_status &= ~(SM_STATUS_STATFS_BUSY | SM_STATUS_STATFS_WANT); /* * Copy the statvfs data to caller's buf. * Note: struct assignment */ cache_hit: if (error == 0) *sbp = smi->smi_statvfsbuf; mutex_exit(&smi->smi_lock); return (error); }