savecore: fix space calculation with respect to minfree in check_space(..)

- Use strtoll(3) instead of atoi(3), because atoi(3) limits the
  representable data to INT_MAX. Check the values received from
  strtoll(3), trimming trailing whitespace off the end to maintain
  POLA.
- Use `KiB` instead of `kB` when describing free space, total space,
  etc. I am now fully aware of `KiB` being the IEC standard for 1024
  bytes and `kB` being the IEC standard for 1000 bytes.
- Store available number of KiB in `available` so it can be more
  easily queried and compared to ensure that there are enough KiB to
  store the dump image on disk.
- Print out the reserved space on disk, per `minfree`, so end-users
  can troubleshoot why check_space(..) is reporting that there isn't
  enough free space.

MFC after:	7 weeks
Reviewed by:	Anton Rang <rang@acm.com> (earlier diff), cem (earlier diff)
Tested with:	positive/negative cases (see review); make tinderbox
Sponsored by:	Dell EMC Isilon
Differential Revision:	D10379
This commit is contained in:
Enji Cooper 2017-04-14 19:41:48 +00:00
parent 7f77a37048
commit f09cb4f208
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=316938

View File

@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kerneldump.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
@ -278,7 +279,7 @@ static int
check_space(const char *savedir, off_t dumpsize, int bounds)
{
FILE *fp;
off_t minfree, spacefree, totfree, needed;
off_t available, minfree, spacefree, totfree, needed;
struct statfs fsbuf;
char buf[100];
@ -294,19 +295,37 @@ check_space(const char *savedir, off_t dumpsize, int bounds)
else {
if (fgets(buf, sizeof(buf), fp) == NULL)
minfree = 0;
else
minfree = atoi(buf);
else {
char *endp;
errno = 0;
minfree = strtoll(buf, &endp, 10);
if (minfree == 0 && errno != 0)
minfree = -1;
else {
while (*endp != '\0' && isspace(*endp))
endp++;
if (*endp != '\0' || minfree < 0)
minfree = -1;
}
if (minfree < 0)
syslog(LOG_WARNING,
"`minfree` didn't contain a valid size "
"(`%s`). Defaulting to 0", buf);
}
(void)fclose(fp);
}
available = minfree > 0 ? spacefree - minfree : totfree;
needed = dumpsize / 1024 + 2; /* 2 for info file */
needed -= saved_dump_size(bounds);
if ((minfree > 0 ? spacefree : totfree) - needed < minfree) {
if (available < needed) {
syslog(LOG_WARNING,
"no dump: not enough free space on device (%lldkB "
"available; need at least %lldkB)",
(long long)(minfree > 0 ? spacefree : totfree),
(long long)needed);
"no dump: not enough free space on device (need at least "
"%jdKiB for dump; %jdKiB available; %jdKiB reserved)",
(intmax_t)needed,
(intmax_t)available + minfree,
(intmax_t)minfree);
return (0);
}
if (spacefree - needed < 0)