Bug 71898

Summary: rpm doesn't handle large file systems gracefully
Product: [Retired] Red Hat Linux Reporter: Ben Woodard <woodard>
Component: rpmAssignee: Jeff Johnson <jbj>
Status: CLOSED DEFERRED QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 7.3   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2002-08-20 02:44:53 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Ben Woodard 2002-08-20 02:44:49 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020606

Description of problem:
When you have a file system with about 1TB available RPM doesn't compute the
amount of space available correctly. No matter how much disk space you have
available it aborts with the warning:

installing package "any_package" needs 3125Mb on the /p/ba1 filesystem



Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1.Mount up a file system with huge amounts of available disk space i.e. 1 TB or
greater.
2.Try to install an RPM without the --ignoresize option

	

Actual Results:  installing package "any_package" needs 3125Mb on the /p/ba1
filesystem

Expected Results:  the package installs.

Additional info:

This appears to be a problem with RPM's diskspaceInfo structure. The
diskspaceInfo structure uses signed longs to represent the available blocks but
fsstat returns either unsigned longs or unsigned long longs.

if you look in lib/transaction.c:

    52  struct diskspaceInfo {
    53      dev_t dev;                  /*!< file system device number. */
    54      signed long bneeded;        /*!< no. of blocks needed. */
    55      signed long ineeded;        /*!< no. of inodes needed. */
    56      int bsize;                  /*!< file system block size. */
    57      signed long bavail;         /*!< no. of blocks available. */
    58      signed long iavail;         /*!< no. of inodes available. */
    59  };

and then compare it with what you see in /usr/include/bits/statfs.h:

    25  struct statfs
    26    {
    27      int f_type;
    28      int f_bsize;
    29  #ifndef __USE_FILE_OFFSET64
    30      __fsblkcnt_t f_blocks;
    31      __fsblkcnt_t f_bfree;
    32      __fsblkcnt_t f_bavail;
    33      __fsfilcnt_t f_files;
    34      __fsfilcnt_t f_ffree;
    35  #else
    36      __fsblkcnt64_t f_blocks;
    37      __fsblkcnt64_t f_bfree;
    38      __fsblkcnt64_t f_bavail;
    39      __fsfilcnt64_t f_files;
    40      __fsfilcnt64_t f_ffree;
    41  #endif
    42      __fsid_t f_fsid;
    43      int f_namelen;
    44      int f_spare[6];
    45    };

and in /usr/include/bits/types.h:

   116  /* Type to count file system blocks.  */
   117  typedef __u_long __fsblkcnt_t;
   118  typedef __u_quad_t __fsblkcnt64_t;

a confounding problem is that the statfs man page is wrong:

NAME
       statfs, fstatfs - get file system statistics

SYNOPSIS
       #include <sys/vfs.h>

       int statfs(const char *path, struct statfs *buf);
       int fstatfs(int fd, struct statfs *buf);

DESCRIPTION
       statfs  returns  information  about a mounted file system.
       path is the path name  of  any  file  within  the  mounted
       filesystem.   buf  is  a  pointer  to  a  statfs structure
       defined as follows:

              struct statfs {
                 long    f_type;     /* type of filesystem (see below) */
                 long    f_bsize;    /* optimal transfer block size */
                 long    f_blocks;   /* total data blocks in file system */
                 long    f_bfree;    /* free blocks in fs */
                 long    f_bavail;   /* free blocks avail to non-superuser */
                 long    f_files;    /* total file nodes in file system */
                 long    f_ffree;    /* free file nodes in fs */
                 fsid_t  f_fsid;     /* file system id */
                 long    f_namelen;  /* maximum length of filenames */
                 long    f_spare[6]; /* spare for later */
              };

...

Comment 1 Jeff Johnson 2002-08-20 16:17:33 UTC
Yup, struct diskspaceInfo was written from the man page.

Deferred until I see my 1st TB file system :-)