>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 r...@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:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to