All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Tinguely <tinguely@sgi.com>
To: Dave Chinner <david@fromorbit.com>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH] xfs_db: fix the setting of unaligned directory fields
Date: Fri, 07 Feb 2014 17:13:21 -0600	[thread overview]
Message-ID: <52F56891.5020305@sgi.com> (raw)
In-Reply-To: <20140207223327.GG13647@dastard>

On 02/07/14 16:33, Dave Chinner wrote:
> On Fri, Feb 07, 2014 at 04:03:42PM -0600, Mark Tinguely wrote:
>> Setting the directory startoff, startblock, and blockcount
>> bit fields is difficult on both big and little endian machines.
>> The setting of extentflag bit field was completely broken.
>>
>> big endian test:
>> xfs_db>  write u.bmx[0].startblock 12
>> u.bmx[0].startblock = 0
>> xfs_db>  write u.bmx[0].startblock 0xc0000
>> u.bmx[0].startblock = 192
>>
>> little endian test:
>> xfs_db>  write u.bmx[0].startblock 12
>> u.bmx[0].startblock = 211106232532992
>> xfs_db>  write u.bmx[0].startblock 0xc0000
>> u.bmx[0].startblock = 3221225472
>
> Can you please write an xfstest for this? The BMBT extent records
> are the only structures that have unaligned bit offsets and hence
> the only ones that exercise this specific code. Clearly no-one
> has needed to write a BMBT record in the past 10 years....

nod. I manually ran through the values valid values for the fields to 
test. A test would be nice.

>> Since these output fields and the lengths are not aligned to a byte,
>> setbitval requires them to be entered in big endian and properly
>> byte/nibble shifted. The extentflag out field is aligned to a byte
>> boundary but was not shifted correctly.
>>
>> Convert the input to big endian on little endian machines and
>> bit/byte shift on all platforms so setbitval can set the bits
>> correctly. As noted in the comment, the bit shift must be done
>> before doing the endian conversion or end result will be shifted
>> in the wrong direction..
>
> Ok, so while we are touching this code, some documentation
> explaining the bit shifting requirements, the format of the return
> buffer from convert_args, what parameter format setbitval() expects,
> etc. Some ascii art demonstrating the incoming and outgoing buffer
> contents for convert_arg would be a great help.
>

okay.

>> +	char	*in	= (char *)ibuf;
>> +	char	*out	= (char *)obuf;
>> +	int	bit;
>
> ibuf/obuf are void *, so don't need casts. Also, whitespace:
>
> 	char	*in = ibuf;
> 	char	*out = obuf;
>
>> +	/*
>> +	 * The input data is in big endian and aligned to the bit length.
>> +	 * Set the individual bits if the destination field or the source
>> +	 * end are not aligned.
>> +	 */
>> +	if (bitoff % NBBY || nbits % NBBY) {
>> +		for (bit=0; bit<nbits; bit++)
>> +			setbit(out, bit+bitoff, getbit(in, bit));
>> +	} else
>> +		memcpy(out+byteize(bitoff), in, byteize(nbits));
>
> This is also rather whitespace challenged.

Nod, did not see that.

>
>>   }
>> Index: b/db/write.c
>> ===================================================================
>> --- a/db/write.c
>> +++ b/db/write.c
>> @@ -451,6 +451,7 @@ convert_arg(
>>   	int alloc_size;
>>   	char *ostr;
>>   	int octval, ret;
>> +	int offadj;
>
> Just "offset" is sufficient here, and with the scope of use, it
> can be declared in the else branch where it is used.
>
>>
>>   	if (bit_length<= 64)
>>   		alloc_size = 8;
>> @@ -526,16 +527,20 @@ convert_arg(
>>   		 */
>>   		*value = strtoll(arg, NULL, 0);
>
> If we are touching this code, the return value here should be error
> checked.
>
> xfs_db>  write u3.bmx[0].startblock 3rgfdw
> u3.bmx[0].startblock = 52776558133248

hmm, It should stop at 3. I will take a look.

> xfs_db>  write u3.bmx[0].startblock x3rgfdw
> u3.bmx[0].startblock = 0
> xfs_db>
>
> i.e. it accepts garbage rather than erroring out.

as does all the other writes ...
xfs_db>  write core.nblocks x3rgfdw
core.nblocks = 0

Fixing convert_arg() is beyond the scope of just this patch.

>> -#if __BYTE_ORDER == BIG_ENDIAN
>> -		/* hackery for big endian */
>> -		if (bit_length<= 8) {
>> -			rbuf += 7;
>> -		} else if (bit_length<= 16) {
>> -			rbuf += 6;
>> -		} else if (bit_length<= 32) {
>> -			rbuf += 4;
>> -		}
>> -#endif
>> +		/*
>> +		 * Align the significant bits in the result length.
>> +		 * Must be done before the endian conversion.
>> +		 */
>> +		offadj = bit_length % NBBY;
>> +		if (offadj)
>> +			*value<<= (8 - offadj);
>
> So it gets shifted up by a number 1-7 bits to align the first bit of
> the range to a byte boundary. So, that magic "8" should be:
>
> 			*value<<= NBBY - offadj;
>
> Ascii art to help readers. Before (host order):
>
> 	rbuf
> 	+---+---+---+---+---+--n+nnn+nnn+
> 		               + bitlen +
> After (host order):
> 	+---+---+---+---+---+nnn+nnn+n--+
> 			    + bitlen +
> then
>
>> +
>> +		/* convert to big endian */
>> +		*value = cpu_to_be64(*value);
>> +
>> +		/* Align the signifant bytes in the result length. */
>> +		offadj = 7 - (bit_length - 1)/ 8;
>> +		rbuf += offadj;
>
> So the buffer pointer get moved forward by a certain number of bytes
> to point at the first byte of the 64 bit big endian value. IOWs, the
> magic "7" is actually (sizeof(__be64) - 1) and the "8" is
> "sizeof(__be64)" because we are talking about adjusting the offset
> within a __be64 variable. IOWs the calculation should be:
>
> 		offset = sizeof(__be64) - 1 -
> 				((bit_length - 1) / sizeof(__be64));
>
> Ascii art to help readers. Before (big endian):
>
> 	rbuf
> 	+---+---+---+---+---+nnn+nnn+n--+
> 			    + bitlen +
>
> After (big endian):
> 		            rbuf
>                              +nnn+nnn+n--+
> 			    + bitlen +
>
> And a similar diagram should be added to setbitval to describe the
> format of the bit information required in @ibuf.
>

Yep, good idea.

--Mark.

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

  reply	other threads:[~2014-02-07 23:13 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-07 22:03 [PATCH] xfs_db: fix the setting of unaligned directory fields Mark Tinguely
2014-02-07 22:33 ` Dave Chinner
2014-02-07 23:13   ` Mark Tinguely [this message]
2014-02-08  8:30     ` Dave Chinner
2014-02-08 17:30       ` Mark Tinguely
2014-02-09 23:22         ` Dave Chinner
2014-02-10 14:23           ` Mark Tinguely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52F56891.5020305@sgi.com \
    --to=tinguely@sgi.com \
    --cc=david@fromorbit.com \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.