[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