Exemple #1
0
int
zfs_statvfs(struct dentry *dentry, struct kstatfs *statp)
{
	zfs_sb_t *zsb = dentry->d_sb->s_fs_info;
	uint64_t refdbytes, availbytes, usedobjs, availobjs;
	uint64_t fsid;
	uint32_t bshift;

	ZFS_ENTER(zsb);

	dmu_objset_space(zsb->z_os,
	    &refdbytes, &availbytes, &usedobjs, &availobjs);

	fsid = dmu_objset_fsid_guid(zsb->z_os);
	/*
	 * The underlying storage pool actually uses multiple block
	 * size.  Under Solaris frsize (fragment size) is reported as
	 * the smallest block size we support, and bsize (block size)
	 * as the filesystem's maximum block size.  Unfortunately,
	 * under Linux the fragment size and block size are often used
	 * interchangeably.  Thus we are forced to report both of them
	 * as the filesystem's maximum block size.
	 */
	statp->f_frsize = zsb->z_max_blksz;
	statp->f_bsize = zsb->z_max_blksz;
	bshift = fls(statp->f_bsize) - 1;

	/*
	 * The following report "total" blocks of various kinds in
	 * the file system, but reported in terms of f_bsize - the
	 * "preferred" size.
	 */

	statp->f_blocks = (refdbytes + availbytes) >> bshift;
	statp->f_bfree = availbytes >> bshift;
	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(availobjs, availbytes >> DNODE_SHIFT);
	statp->f_files = statp->f_ffree + usedobjs;
	statp->f_fsid.val[0] = (uint32_t)fsid;
	statp->f_fsid.val[1] = (uint32_t)(fsid >> 32);
	statp->f_type = ZFS_SUPER_MAGIC;
	statp->f_namelen = ZFS_MAXNAMELEN;

	/*
	 * We have all of 40 characters to stuff a string here.
	 * Is there anything useful we could/should provide?
	 */
	bzero(statp->f_spare, sizeof (statp->f_spare));

	ZFS_EXIT(zsb);
	return (0);
}
Exemple #2
0
/*
 * zfs_init_fs - Initialize the zfsvfs struct and the file system
 *	incore "master" object.  Verify version compatibility.
 */
int
zfs_init_fs(zfsvfs_t *zfsvfs, znode_t **zpp)
{
	objset_t	*os = zfsvfs->z_os;
	int		i, error;
	uint64_t fsid_guid;
	uint64_t zval;

	*zpp = NULL;

	error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version);
	if (error) {
		return (error);
	} else if (zfsvfs->z_version > ZPL_VERSION) {
		(void) printf("Mismatched versions:  File system "
		    "is version %llu on-disk format, which is "
		    "incompatible with this software version %lld!",
		    (u_longlong_t)zfsvfs->z_version, ZPL_VERSION);
		return (ENOTSUP);
	}

	if ((error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &zval)) != 0)
		return (error);
	zfsvfs->z_norm = (int)zval;
	if ((error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &zval)) != 0)
		return (error);
	zfsvfs->z_utf8 = (zval != 0);
	if ((error = zfs_get_zplprop(os, ZFS_PROP_CASE, &zval)) != 0)
		return (error);
	zfsvfs->z_case = (uint_t)zval;
	/*
	 * Fold case on file systems that are always or sometimes case
	 * insensitive.
	 */
	if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE ||
	    zfsvfs->z_case == ZFS_CASE_MIXED)
		zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER;

	/*
	 * The fsid is 64 bits, composed of an 8-bit fs type, which
	 * separates our fsid from any other filesystem types, and a
	 * 56-bit objset unique ID.  The objset unique ID is unique to
	 * all objsets open on this system, provided by unique_create().
	 * The 8-bit fs type must be put in the low bits of fsid[1]
	 * because that's where other Solaris filesystems put it.
	 */
	fsid_guid = dmu_objset_fsid_guid(os);
	ASSERT((fsid_guid & ~((1ULL<<56)-1)) == 0);
	zfsvfs->z_vfs->vfs_fsid.val[0] = fsid_guid;
	zfsvfs->z_vfs->vfs_fsid.val[1] = ((fsid_guid>>32) << 8) |
	    zfsvfs->z_vfs->mnt_vfc->vfc_typenum & 0xFF;

	error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1,
	    &zfsvfs->z_root);
	if (error)
		return (error);
	ASSERT(zfsvfs->z_root != 0);

	error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1,
	    &zfsvfs->z_unlinkedobj);
	if (error)
		return (error);

	/*
	 * Initialize zget mutex's
	 */
	for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
		mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);

	error = zfs_zget(zfsvfs, zfsvfs->z_root, zpp);
	if (error) {
		/*
		 * On error, we destroy the mutexes here since it's not
		 * possible for the caller to determine if the mutexes were
		 * initialized properly.
		 */
		for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
			mutex_destroy(&zfsvfs->z_hold_mtx[i]);
		return (error);
	}
	ASSERT3U((*zpp)->z_id, ==, zfsvfs->z_root);
	error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 8, 1,
	    &zfsvfs->z_fuid_obj);
	if (error == ENOENT)
		error = 0;

	return (0);
}