Re: Quota file format [2.3 issue]

Riley Williams (rhw@BigFoot.Com)
Tue, 13 Apr 1999 14:11:21 +0100 (GMT)


Hi Jakub.

I've just checked the format of the records in the quota files, and
there's NO way we could add a header to it that would reliably work
with both old and new tools - the format's incredibly stupid in that
respect.

If we wish to make ANY changes to the quota file format, we need to
define a NEW quota file with a new name, and get the file format
correct to start with...

However, assuming we're thinking of doing that, the following comments
apply...

>> Can I suggest the following header format for the quota file:

>> Q> struct quota_header {
>> Q> char id[5];
>> Q> unsigned char vsn;
>> Q> unsigned short endian;
>> Q> };
>> Q>
>> Q> struct quota_header qh = { "QUOTA", 0, 0x1234 };

>> This should occupy exactly eight bytes, and deal with all of the
>> problems mentioned. It has the following properties:

>> 1. A 'magic number' that identifies the file format and can be
>> added to the database for the `file` program. This can also
>> be used to determine whether the quota file has the header
>> present or not.

>> 2. A 'version number' that can be incremented to specify changes
>> to the format of the quota file.

>> 3. A multi-byte word with known value that can be used to decide
>> whether values in the quota file are stored in little-endian
>> or big-endian format. The code can then adjust itself to deal
>> with whatever is found.

>> OK, the use of "unsigned char" to specify an 8-bit field, and the
>> use of "unsigned short" to specify a 16-bit field is probably not
>> what Linux uses, but that can easily be changed to use whatever
>> names Linux uses for suchlike fields.

> Such a header is a valid old format quota.user as well, 2.2.0
> kernel would happily assume it is the old format and do bad
> things with that.

Not if we do that right.

Basically, we need to ensure that the USERID field in the record or
records occupied by the header contain an invalid user ID for that
system, then the details in the header record will never be modified,
which is the important property.

> I was trying to explain that the only way I'm aware of how to
> force old kernel not to touch new format file is to make its
> size not be divisible by sizeof(struct dqblk).

Are you sure that strategy will work? I would expect it to result in
both old kernels and the old quota tools happily reading records that
consist of the end of one record and the start of the next, and really
mangling the file as a result.

To guarantee that the records in the file are read and handled OK, we
basically need to guarantee that any header we add occupies an EXACT
number of records, and also that the USERID or GROUPID field therein
holds a value that corresponds to an invalid user ID or group ID on
the system in question. Anything else is a non-starter in my opinion.

> On the other side, it does not make much sense to me to have the
> file format in both endian versions.

I'd agree, but we need to be able to DETECT whether the file is in the
format we expect it to be in, even if it should never be in any other
format.

> Then kernel would have to swap it if it plays with other format
> type, but not swap it if it is the same endian.

Alternatively, and probably a much more sensible solution here, the
quota enabling tools could refuse to enable quotas on that partition
if the file is in the wrong endian format, and a separate tool could
be provided that runs through the quota file and rewrites it in the
correct endian format for that system.

> Look at UFS code how it sucks because UFS is both little and big
> endian.

I've never used UFS as I've had no reason to, so can't comment on
that...

> On the other side, doing cpu_to_le32() does not hurt anybody,
> especially on quota code.

Does the existing quota code do that? If not, then the situation still
needs to be dealt with...

> So I'd more think in terms of

> quota_header: id 8 bytes (some magic number)
> version 2 bytes

> and after it n times
> bhard 4 bytes
> bsoft 4 bytes
> bcur 4 bytes
> ihard 4 bytes
> isoft 4 bytes
> icur 4 bytes
> btime 8 bytes
> itime 8 bytes

> as it is always read by read(2) or written by write(2), it does
> not matter much that the structures in the file are not aligned
> on 8 bytes boundary.

In fact, the current format results in a file which is always a
multiple of 40 bytes, so any size of header that isn't a multiple of
40 bytes would do the job if your theory is correct...

**********************************************************************

A related problem occurs with NFS mounts, and I'd be interested to
know how the following situation is handled:

1. User JohnDoa has user ID 1234 on the system exporting the
NFS mounted file system, but has user ID 2345 on the system
it's exported to.

2. Both JohnDoa and the user with user ID 2345 on the exporting
system have private files on that file system.

As far as I can tell, that would result in JohnDoa being able to
access files belonging to user 2345 on the exporting system, but NOT
being able to access his own files thereon...

Best wishes from Riley.

+----------------------------------------------------------------------+
| There is something frustrating about the quality and speed of Linux |
| development, ie., the quality is too high and the speed is too high, |
| in other words, I can implement this XXXX feature, but I bet someone |
| else has already done so and is just about to release their patch. |
+----------------------------------------------------------------------+
* ftp://ftp.MemAlpha.cx/pub/rhw/Linux
* http://www.MemAlpha.cx/kernel.versions.html

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/