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

[fol] Re: linux で扱える最大ファイルサイズは?


佐野@浜松です。

In article <m27lc8fxpx.fsf_-_ _at_ eco.toyama-u.ac.jp>,
  at "02 Jun 2000 14:39:22 +0900',
   with "Re: linux で扱える最大ファイルサイズは?",
 Takeyasu Wakabayashi <twakaba _at_ eco.toyama-u.ac.jp> さん writes:

> Taketoshi Sano <kgh12351 _at_ nifty.ne.jp> writes:
> 
> >  2.0 系でもまだそんな感じで、2.2 系になって Alpha など 64bit な CPU で
> > システムコールの read/write が 64bit なファイルサイズに対応したレベル
> > だったと思います。2.4 系では IA32 でも 64bit で read/write できるように
> > なる (2.3.xxx で実現してる) とかいう解説を読んだような気がしますが、
> > 詳細は確認してません。

> read/write の 64bit の読み書き、というのは size_t や ssize_t の大きさ
> が IA32 でも64bit になるということでしょうか? off_t の大きさも変わる
> のかな? カーネルの中では loff_t という型もつかっていますよね。

手元にあるのは 2.3.99-pre5 なのですが、これで見ると off_t や size_t は
 IA32 では 32bit のようですね。 include には

  asm-{alpha,arm,i386,ia64,m68k,mips,mips64,ppc,sh,sparc,sparc64}

などがありますが、 それぞれに posix_types.h があって

  typedef long              __kernel_off_t;

についてはすべて共通となっているようです。

 __kernel_size_t については、alpha, ia64, mips64, ppc 
および gcc 2.8 以降の sparc 64 で

  typedef unsigned long   __kernel_size_t;

 gcc 2.8 未満の sparc64 では

  typedef unsigned long int      __kernel_size_t;

また arm, i386, m68k, mips, sh, sparc では

  typedef unsigned int     __kernel_size_t;

となっています。 __kernel_ssize_t についても signed である
 (unsigned でない) こと以外は _kernel_size_t と同様です。

いっぽう __kernel_loff_t については alpha だけが long で
それ以外はすべて

  typedef long long         __kernel_loff_t;

となっています。

あと、 sparc64 の posix_types.h には

/* Now 32bit compatibility types */
typedef unsigned int           __kernel_size_t32;
typedef int                    __kernel_ssize_t32;
...
typedef int                    __kernel_off_t32;
...
typedef long                   __kernel_loff_t32;

などがあったりしますね。 ia64 にも ia32.h というのがあって

#ifdef CONFIG_IA32_SUPPORT

/*
 * 32 bit structures for IA32 support.
 */

/* 32bit compatibility types */
typedef unsigned int           __kernel_size_t32;
typedef int                    __kernel_ssize_t32;
...
typedef int                    __kernel_off_t32;
...
typedef long                   __kernel_loff_t32;

と書いてあったりします。

ところで、 2.4.x で IA32 のシステムを使って ext2fs に 2GB 以上の
ファイルにアクセスする場合は open(2) で O_LARGEFILE を指定する、と
なってるみたいですね。

 fs/ext2/file.c には

/*
 * Called when an inode is about to be open.
 * We use this to disallow opening RW large files on 32bit systems if
 * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
 * on this flag in sys_open.
 */
static int ext2_open_file (struct inode * inode, struct file * filp)
{
        if (inode->u.ext2_i.i_high_size && !(filp->f_flags & O_LARGEFILE))
                return -EFBIG;
        return 0;
}

なんて書いてあります。あ、でもこれは既に保存したファイルを読む場合の
話かな。

そういえば 2.2.15 でもまだ存在していた ext2_file_write() は
きれいさっぱりと無くなったようです。

 fs/ext2/file.c には

/*
 * We have mostly NULL's here: the current defaults are ok for
 * the ext2 filesystem.
 */
struct file_operations ext2_file_operations = {
        llseek:         ext2_file_lseek,
        read:           generic_file_read,
        write:          generic_file_write,
        ioctl:          ext2_ioctl,
        mmap:           generic_file_mmap,
        open:           ext2_open_file,
        release:        ext2_release_file,
        fsync:          ext2_sync_file,
};

と書かれています。

 generic_file_write() ってどこにあるのかな、と思って検索したら、
 mm/filemap.c にあるんですね。これには特にサイズの制限は無さそう。

結局 2.4.x 系カーネルの ext2 fs の制限としては

/*
 * Make sure the offset never goes beyond the 32-bit mark..
 */
static loff_t ext2_file_lseek(
...
        if (offset<0)
                return -EINVAL;
        if (((unsigned long long) offset >> 32) != 0) {
                if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
                        return -EINVAL;
        } 

だけのような感じ。

で、この ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)] は
どうも filesystem の block サイズ (1024k - 8192k) によって
決まり、

#define EXT2_MAX_SIZE(bits)                                                     
\
        (((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) +                             
\
           (1LL << (bits - 2)) * (1LL << (bits - 2)) +                          
\
           (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) *   
\
          (1LL << bits)) - 1)

static long long ext2_max_sizes[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13)
};

から計算される数値になるんじゃないかと思います。

 1024k block (10bit) なら 2^33 程度、8192k block (13bit) なら 2^45 程度、
という感じなのかな。

-- 
     # (わたしのおうちは浜松市、「夜のお菓子」で有名さ。)
    <kgh12351 _at_ nifty.ne.jp> : Taketoshi Sano (佐野 武俊)

この情報があなたの探していたものかどうか選択してください。
yes/まさにこれだ!   no/違うなぁ   part/一部見つかった   try/これで試してみる

あなたが探していた情報はどのようなことか、ご自由に記入下さい。特に「まさにこれだ!」と言う場合は記入をお願いします。
例:「複数のマシンからCATV経由でipmasqueradeを利用してWebを参照したい場合の設定について」
Follow-Ups: References: