9
static inline void ext4_ext_store_pblock(struct ext4_extent *ex,
                     ext4_fsblk_t pb)
{
    ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
    ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) &
                      0xffff);
}

このコードはLinuxカーネルからのものです。最後の行を参照してください。それはpb>>31そして>>1をしますこれはpb>>32と同じですか?なぜそれをしないのですか?

ありがとうございました

編集:ありがとうございました。ext4メーリングリストにパッチを送信しました

4

2 に答える 2

8

基になるデータ型によっては、2つのアプローチはまったく同じではありません。標準(C11、6.5.7ビット単位のシフト演算子)は次のように述べています。

右のオペランドの値が負であるか、プロモートされた左のオペランドの幅以上の場合、動作は定義されていません。

したがって、32ビット幅の整数型を32ビット右にシフトすると、未定義の動作が発生します。ただし、31ビットシフトしてから、別のビットをシフトすること明確に定義されています。

その特定の点は、誰かがこれを行う可能性がある理由ですが、この特定のケースではおそらく議論の余地があります。タイプが(64ビット幅を保証)である場合、との間にunsigned long long違いはありません。(x >> 31) >> 1x >> 32

ただし、一部のプラットフォームが実際に32ビットタイプとして定義ext4_fsblk_tされている場合(または、32ビットタイプを許可した以前の実装から引き継がれている場合(a))、保証するために2段階シフトに頼る必要があります。定義された動作。


(a)ext3 :との間に中間段階があり、エクステントを使用して48ビットに移動ext4できました。これは、64ビットデータ型を使用するext3ための足がかりになります。ext4それ以前は、8TBがファイルシステムの実際的な制限でした。

確認はしていませんが、基になるデータ型が最大64ビット幅になる前に、このコードスニペットがその遷移からの二日酔いである可能性があります。

使用されるようになったタイプは、条件付きでまたはのいずれかとsector_tして定義されました。これは、コードが最初に存在する理由を説明している可能性があります。後者として定義された状況では、2段階のシフトが必要だった可能性があります。u64unsigned long

しかし、それext4がこの中間段階を残していることを考えると、2段階のシフトがもう必要かどうかはわかりません。最善の策は、変更要求を出し、それが開発者によって撃墜されるかどうかを確認することです:-)

于 2013-01-30T06:42:24.157 に答える
4

ext3_fsblk_tunsigned longが(32ビット)として定義されているext3からコードがコピーされたと想像できます。この場合、paxdiabloの主張は正しかった:

標準(C11、6.5.7ビット単位のシフト演算子)は次のように述べています。

右のオペランドの値が負であるか、プロモートされた左のオペランドの幅以上の場合、動作は未定義です。

したがって、32ビット整数を32ビット右にシフトすると、未定義になります。ただし、31ビットシフトしてから別のビットを定義します。

ext4_fsblk_tは、64ビットとして定義されunsigned long long、 64ビットであるlong longことが保証されているため、このコードはもはや意味がありません。

于 2013-01-30T07:00:04.890 に答える