Filesystem statistics

The most important command that your filesystem should implement is the DCMD_FSYS_STATVFS. In our io_devctl() handler, this ends up calling the utility function cfs_block_fill_statvfs() (in lib/block.c):

void
cfs_block_fill_statvfs (cfs_attr_t *attr, struct statvfs *r)
{
  uint32_t      nalloc, nfree;
  size_t        nbytes;

  mpool_info (mpool_block, &nbytes, &r -> f_blocks, &nalloc,
              &nfree, NULL, NULL);

  // INVARIANT SECTION

  // file system block size
  r -> f_bsize = nbytes;

  // fundamental filesystem block size
  r -> f_frsize = nbytes;

  // total number of file serial numbers
  r -> f_files = INT_MAX;

  // file system id
  r -> f_fsid = 0x12345678;

  // bit mask of f_flag values
  r -> f_flag = 0;

  // maximum filename length
  r -> f_namemax = NAME_MAX;

  // null terminated name of target file system
  strcpy (r -> f_basetype, "cfs");

  // CALCULATED SECTION

  if (optm) {        // for system-allocated mem with a max

    // tot number of blocks on file system in units of f_frsize
    r -> f_blocks = optm / nbytes;

    // total number of free blocks
    r -> f_bfree = r -> f_blocks - nalloc;

    // total number of free file serial numbers (approximation)
    r -> f_ffree = r -> f_files - nalloc;

  } else if (optM) { // for statically-allocated mem with a max

    // total #blocks on file system in units of f_frsize
    r -> f_blocks = optM / nbytes;

    // total number of free blocks
    r -> f_bfree = nfree;

    // total number of free file serial numbers (approximation)
    r -> f_ffree = nfree;

  } else {           // for unbounded system-allocated memory

    // total #blocks on file system in units of f_frsize
    r -> f_blocks = nalloc + 1;

    // total number of free blocks
    r -> f_bfree = r -> f_blocks - nalloc;

    // total #free file serial numbers (an approximation)
    r -> f_ffree = r -> f_files - nalloc;

  }

  // MIRROR

  // number of free blocks available to non-priv. proc
  r -> f_bavail = r -> f_bfree;

  // number of file serial numbers available to non-priv. proc
  r -> f_favail = r -> f_ffree;
}

The reason for the additional complexity (as opposed to just stuffing the fields directly) is due to the command-line options for the RAM disk. The -m option lets the RAM disk slowly allocate memory for itself as it requires it from the operating system, up to a maximum limit. If you use the -M option instead, the RAM disk allocates the specified memory right up front. Using neither option causes the RAM disk to allocate memory as required, with no limit.

Some of the numbers are outright lies — for example, the f_files value, which is supposed to indicate the total number of file serial numbers, is simply set to INT_MAX. There is no possible way that we would ever use that many file serial numbers (INT_MAX is 9 × 1018)!

So, the job of cfs_block_fill_statvfs() is to gather the information from the block allocator, and stuff the numbers (perhaps calculating some of them) into the struct statvfs structure.