Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Mar 2013 16:29:44 +0700 (NOVT)
From:      Eugene Grosbein <egrosbein@rdtc.ru>
To:        FreeBSD-gnats-submit@freebsd.org
Cc:        harti@freebsd.org
Subject:   bin/177183: [bsnmpd] [patch] snmp_hostres modules does not support FS over 1TB
Message-ID:  <201303210929.r2L9TihL040946@eg.sd.rdtc.ru>
Resent-Message-ID: <201303210940.r2L9e1la037725@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         177183
>Category:       bin
>Synopsis:       [bsnmpd] [patch] snmp_hostres modules does not support FS over 1TB
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Mar 21 09:40:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Eugene Grosbein
>Release:        FreeBSD 8.3-STABLE i386
>Organization:
RDTC JSC
>Environment:
System: FreeBSD eg.sd.rdtc.ru 8.3-STABLE FreeBSD 8.3-STABLE #53: Wed Feb 13 18:22:34 NOVT 2013 root@eg.sd.rdtc.ru:/usr/local/obj/usr/local/src/sys/EG i386

>Description:
	bsnmp(1) has snmp_hostres module to support HOSTRES MIB.
	This SNMP MIB's hrStorageTable limits hrStorageSize and hrStorageUsed
	parameters to 32 bit integer values, so file systems having more
	than 2^31 allocation units cannot be shown correctly.

	Let us follow net-snmp behaviour that (since 2011) translates
	hrStorageSize/hrStorageUsed/hrStorageAllocationUnits triples
	so that hrStorageAllocationUnits get bigger and other fit
	under INT_MAX by default.

>How-To-Repeat:

	This demonstrates the problem using holey file to mimic
	3TB file system (this needs 18GB free in real fs):

# truncate -s 3T f
# mdconfig -af f
md0
# newfs -O2 -b 4096 -f 512 -i $((1024*1024*1024)) /dev/md0 >/dev/null
# mount /dev/md0 /mnt/tmp
# rmdir /mnt/tmp/.snap; dd if=/dev/zero bs=2048 count=1000 of=/mnt/tmp/f2
# df -k /mnt/tmp
Filesystem 1024-blocks Used      Avail Capacity  Mounted on
/dev/md0    3217454200 2004 2960055860     0%    /mnt/tmp

	Then look at snmpwalk's output and see hrStorageAllocationUnits
	equals to 512 (fsize) and hrStorageSize is truncated to 2^31-1.

	With the following patch you get result consistent with net-snmp:

HOST-RESOURCES-MIB::hrStorageType.393 = OID: HOST-RESOURCES-TYPES::hrFSBerkeleyFFS
HOST-RESOURCES-MIB::hrStorageDescr.393 = STRING: /mnt/tmp, type: ufs, dev: /dev/md0
HOST-RESOURCES-MIB::hrStorageAllocationUnits.393 = INTEGER: 2048 Bytes
HOST-RESOURCES-MIB::hrStorageSize.393 = INTEGER: 1608727100
HOST-RESOURCES-MIB::hrStorageUsed.393 = INTEGER: 1002

	SNMP's data 2048*1608727100=3294673100800 equals to df's data:
	1024*3217454200=3294673100800
	
>Fix:

--- usr.sbin/bsnmpd/modules/snmp_hostres/hostres_storage_tbl.c.orig	2013-03-21 13:42:16.000000000 +0700
+++ usr.sbin/bsnmpd/modules/snmp_hostres/hostres_storage_tbl.c	2013-03-21 14:15:51.000000000 +0700
@@ -442,7 +442,9 @@
 storage_OS_get_fs(void)
 {
 	struct storage_entry *entry;
-	uint64_t used_blocks_count = 0;
+	uint64_t block_size = 0;
+	uint64_t free_blocks_count = 0;
+	uint64_t total_blocks_count = 0;
 	char fs_string[SE_DESC_MLEN];
 	int mounted_fs_count;
 	int i = 0;
@@ -473,6 +475,8 @@
 	fs_tbl_pre_refresh();
 
 	for (i = 0; i < mounted_fs_count; i++) {
+		int shift = 0;
+
 		snprintf(fs_string, sizeof(fs_string),
 		    "%s, type: %s, dev: %s", fs_buf[i].f_mntonname,
 		    fs_buf[i].f_fstypename, fs_buf[i].f_mntfromname);
@@ -488,23 +492,22 @@
 		entry->flags |= HR_STORAGE_FOUND;
 		entry->type = fs_get_type(&fs_buf[i]); /*XXX - This is wrong*/
 
-		if (fs_buf[i].f_bsize > INT_MAX)
-			entry->allocationUnits = INT_MAX;
-		else
-			entry->allocationUnits = fs_buf[i].f_bsize;
-
-		if (fs_buf[i].f_blocks > INT_MAX)
-			entry->size = INT_MAX;
-		else
-			entry->size = fs_buf[i].f_blocks;
-
-		used_blocks_count = fs_buf[i].f_blocks - fs_buf[i].f_bfree;
-
-		if (used_blocks_count > INT_MAX)
-			entry->used = INT_MAX;
-		else
-			entry->used = used_blocks_count;
 
+		total_blocks_count = fs_buf[i].f_blocks;
+		block_size = fs_buf[i].f_bsize;
+		free_blocks_count = fs_buf[i].f_bfree;
+
+		while (total_blocks_count > INT_MAX) {
+			total_blocks_count >>= 1;
+			shift++;
+		}
+		if (shift) {
+			block_size <<= shift;
+			free_blocks_count >>= shift;
+		}
+		entry->size = total_blocks_count;
+		entry->allocationUnits = block_size;
+		entry->used = total_blocks_count - free_blocks_count;
 		entry->allocationFailures = 0;
 
 		/* take care of hrFSTable */
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303210929.r2L9TihL040946>