[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] stat() and blocks



I have made further investigation about stat() and friends, and it turns that I said wrong things in my previous messages. It seems that there are several bugs in our various components, so let's restart from the beginning with some facts, then we will progress step by step to get good values from the different tools.

The following can be found in the MiNTLib.

In include/sys/stat.h:
#define S_BLKSIZE              512     /* Block size for `st_blocks'.  */

In include/bits/stat.h:
/* This is what Fstat wants and what we use in the library.  */
struct stat {
...
  __off_t st_blocks;            /* Number of 512-bytes blocks allocated.  */
  unsigned long int st_blksize; /* Optimal blocksize for I/O.  */

I found some documentation about this block stuff on other OS, this is perfectly valid.

Actually, each OS define a constant named S_BLKSIZE. Its value is the number of bytes inside what the OS will refer later as "a block". This block size has no physical reality, it is just a constant value chosen by the OS, for all filesystems. The common value of S_BLKSIZE is 512 (as it is in MiNT), however some exotic OSes has different values. For example, Cygwin has 1024, and HP-UX and AIX have other values.

Then we use the stat() function on a file, this will fill a "struct stat".
The member st_blocks is the number of blocks of size S_BLKSIZE used by the file on the filesystem. If the underlying filesystem use physical blocks with another size, it doesn't matter: the unit of st_blocks is always S_BLKSIZE.

Then the member st_blksize: as the comment says, this is the preferred buffer size for optimal performance when reading or writing into the file. The important thing to understand is that st_blksize and st_blocks are totally unrelated ! Each filesystem driver can provide some clever physical value in st_blksize, as a hint for applications in order to choose an adequate buffer size.

I made experiments in Linux and Cygwin and these facts have been verified.

Now let's speak about the FreeMiNT kernel. I wrote a little to program to see what happens. I tested it on a file of size being exactly 8 kilobyte, stored on an ext2 partition. Here is the output.

OS block size: S_BLKSIZE = 512
stat(): st_blocks = 16, st_blksize = 1024
Fstat64(): st_blocks = 16, st_blksize = 1024
Fxattr(): st_blocks = 8, st_blksize = 1024

We can see that MiNT chooses S_BLKSIZE = 512. This is a good choice, since it is the most common value, the same as Linux.

The first function is stat(). Its behaviour is well defined in in the UNIX documentation. We can see the MiNTLib implementation is correct. My 8K file occupies 16 512-byte blocks. The ext2 filesystem chooses an optimal buffer size of 1024 bytes, this is a good value.

The following 2 "functions" are direct MiNT system calls, so the results comes directly from the FreeMiNT kernel, they have not been modified by the MiNTLib.

The Fstat64() system call has an interface similar to the UNIX stat() function, it fills a "struct stat". The results are exactly the same as the stat() function.

Question 1: Are the semantics of st_blocks and st_blksize of the "struct stat" returned by Fstat64() the same as the one returned by stat() ? I believe the answer is yes, but it has to be confirmed.

The Fxattr() system call is similar, but it returns a "struct xattr", which is similar, but not same, as "struct stat". Surprisingly, the st_blocks value is half the value stat's one.

Question 2: What is the unit used by the st_blocks member of "struct xattr"? We can see that on ext2, the unit is 1024 (to match the file size). So where does this 1024 come from ?

We can find an answer in sys/xfs/ext2fs/ext2sys.c:
	ptr->blksize	= EXT2_BLOCK_SIZE (s);
	/* nblocks is measured in blksize */
	ptr->nblocks	= le2cpu32 (c->in.i_blocks) / (ptr->blksize >> 9);

As the structure definition is not the same in the kernel, the members don't have the exact same names, but it is actually a "struct xattr". The comment clearly says that blksize is the block size, and nblocks is the block count. So the definition of these 2 fields is radically different than in "struct stat".

Here are the facts.

Hey, FreeMiNT gurus, could you please confirm the behaviours described here are correct ?

Anyway, when anyone agrees with the answers to these questions, we will have to comment the members of "struct xattr" in mintlib/lib.h and freemint/sys/mint/stat.h to avoid new interrogations like this in the future.

--
Vincent Riviere