Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] 2TB files: st_blocks is invalid when calling stat64

This patch series fixes the following problems on 32 bits architecture.

o stat64 returns the lower 32 bits of blocks, although userland st_blocks
has 64 bits, because i_blocks has only 32 bits. The ioctl with FIOQSIZE has
the same problem.

o As Dave Kleikamp said, making >2TB file on JFS results in writing an
invalid block number to disk inode. The cause is the same as above too.

o In generic quota code dquot_transfer(), the file usage is calculated from
i_blocks via inode_get_bytes(). If the file is over 2TB, the change of
usage is less than expected. The cause is the same as above too.

o As Trond Myklebust said, statfs64's entries related to blocks are invalid
on statfs64 for a network filesystem which has more than 2^32-1 blocks with
CONFIG_LBD disabled. [PATCH 3/3]

We made patches to fix problems that occur when handling a large filesystem
and a large file. It was discussed on the mails titled "stat64 for over 2TB
file returned invalid st_blocks".

Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
Cc: Dave Kleikamp <shaggy@austin.ibm.com>
Cc: Jan Kara <jack@ucw.cz>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Takashi Sato and committed by
Linus Torvalds
abcb6c9f 93d2341c

+5 -13
+1 -2
include/asm-i386/stat.h
··· 58 58 long long st_size; 59 59 unsigned long st_blksize; 60 60 61 - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ 62 - unsigned long __pad4; /* future possible st_blocks high bits */ 61 + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ 63 62 64 63 unsigned long st_atime; 65 64 unsigned long st_atime_nsec;
+1 -2
include/asm-m68k/stat.h
··· 60 60 long long st_size; 61 61 unsigned long st_blksize; 62 62 63 - unsigned long __pad4; /* future possible st_blocks high bits */ 64 - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ 63 + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ 65 64 66 65 unsigned long st_atime; 67 66 unsigned long st_atime_nsec;
+1 -7
include/asm-sh/stat.h
··· 60 60 long long st_size; 61 61 unsigned long st_blksize; 62 62 63 - #if defined(__BIG_ENDIAN__) 64 - unsigned long __pad4; /* Future possible st_blocks hi bits */ 65 - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ 66 - #else /* Must be little */ 67 - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ 68 - unsigned long __pad4; /* Future possible st_blocks hi bits */ 69 - #endif 63 + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ 70 64 71 65 unsigned long st_atime; 72 66 unsigned long st_atime_nsec;
+1 -1
include/linux/fs.h
··· 490 490 unsigned int i_blkbits; 491 491 unsigned long i_blksize; 492 492 unsigned long i_version; 493 - unsigned long i_blocks; 493 + sector_t i_blocks; 494 494 unsigned short i_bytes; 495 495 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ 496 496 struct mutex i_mutex;
+1 -1
include/linux/stat.h
··· 69 69 struct timespec mtime; 70 70 struct timespec ctime; 71 71 unsigned long blksize; 72 - unsigned long blocks; 72 + unsigned long long blocks; 73 73 }; 74 74 75 75 #endif