linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: stat64 for over 2TB file returned invalid st_blocks
@ 2005-12-06 12:42 Takashi Sato
  2005-12-06 14:30 ` Dave Kleikamp
  0 siblings, 1 reply; 31+ messages in thread
From: Takashi Sato @ 2005-12-06 12:42 UTC (permalink / raw)
  To: shaggy; +Cc: linux-kernel, linux-fsdevel

Hi,

> > >> 2. Change the type of architecture dependent stat64.st_blocks in
> > >>    include/asm/asm-*/stat.h from unsigned long to unsigned long long.
> > >>    I tried modifying only stat64 of 32bit architecture
> > >>    (include/asm-i386/stat.h).
> > >
> > >This changes the API, but the structure does suggest that the 4-byte pad
> > >should be used for the high-order bytes of st_blocks, so that's not
> > >really a problem.  A correct fix would replace __pad4 with
> > >st_blocks_high (or something like that) and ensure that the high-order
> > >word was stored there.  Your proposed fix would only be correct on
> > >little-endian hardware, as Jörn pointed out.
> >
> > Thank you for your advice.  I'll research for glibc and consider
> > how to implement.
> > By the way I think, as Avi Kivity said, it's always little-endian on i386,
> > is it correct?
>
> That's true.  The patch does fix i386 without any bad side-effects.  A
> generic fix that would fix all architectures would be a little more
> complicated, since the size of st_blocks varies.  32-bit big-endian
> would have to explicitly copy the high and low words.  (The first time I
> looked at this, I ignored the fact that the change was in asm-i386.)

I realized some 32-bit big-endian architectures such as sh and m68k
have a padding before 32-bit st_blocks, though mips and ppc have
64-bit st_blocks.

- asm-sh
#if defined(__BIG_ENDIAN__)
        unsigned long   __pad4;         /* Future possible st_blocks hi bits */
        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
#else /* Must be little */
        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
        unsigned long   __pad4;         /* Future possible st_blocks hi bits */
#endif

- asm-m68k
        unsigned long   __pad4;         /* future possible st_blocks high bits */
        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */

So I updated the patch.  Any feedback and comments are welcome.

Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
Signed-off-by: ASANO Masahiro <masano@tnes.nec.co.jp>

diff -uprN -X linux-2.6.15-rc5.org/Documentation/dontdiff linux-2.6.15-rc5.org/include/asm-i386/stat.h
linux-2.6.15-rc5-blocks/include/asm-i386/stat.h
--- linux-2.6.15-rc5.org/include/asm-i386/stat.h	2005-10-28 09:02:08.000000000 +0900
+++ linux-2.6.15-rc5-blocks/include/asm-i386/stat.h	2005-12-06 16:24:31.000000000 +0900
@@ -58,8 +58,7 @@ struct stat64 {
 	long long	st_size;
 	unsigned long	st_blksize;

-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-	unsigned long	__pad4;		/* future possible st_blocks high bits */
+	unsigned long long	st_blocks;	/* Number 512-byte blocks allocated. */

 	unsigned long	st_atime;
 	unsigned long	st_atime_nsec;
diff -uprN -X linux-2.6.15-rc5.org/Documentation/dontdiff linux-2.6.15-rc5.org/include/asm-m68k/stat.h
linux-2.6.15-rc5-blocks/include/asm-m68k/stat.h
--- linux-2.6.15-rc5.org/include/asm-m68k/stat.h	2005-10-28 09:02:08.000000000 +0900
+++ linux-2.6.15-rc5-blocks/include/asm-m68k/stat.h	2005-12-06 16:29:50.000000000 +0900
@@ -60,8 +60,7 @@ struct stat64 {
 	long long	st_size;
 	unsigned long	st_blksize;

-	unsigned long	__pad4;		/* future possible st_blocks high bits */
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long long	st_blocks;	/* Number 512-byte blocks allocated. */

 	unsigned long	st_atime;
 	unsigned long	st_atime_nsec;
diff -uprN -X linux-2.6.15-rc5.org/Documentation/dontdiff linux-2.6.15-rc5.org/include/asm-sh/stat.h
linux-2.6.15-rc5-blocks/include/asm-sh/stat.h
--- linux-2.6.15-rc5.org/include/asm-sh/stat.h	2005-10-28 09:02:08.000000000 +0900
+++ linux-2.6.15-rc5-blocks/include/asm-sh/stat.h	2005-12-06 16:28:37.000000000 +0900
@@ -60,13 +60,7 @@ struct stat64 {
 	long long	st_size;
 	unsigned long	st_blksize;

-#if defined(__BIG_ENDIAN__)
-	unsigned long	__pad4;		/* Future possible st_blocks hi bits */
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-#else /* Must be little */
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-	unsigned long	__pad4;		/* Future possible st_blocks hi bits */
-#endif
+	unsigned long long	st_blocks;	/* Number 512-byte blocks allocated. */

 	unsigned long	st_atime;
 	unsigned long	st_atime_nsec;
diff -uprN -X linux-2.6.15-rc5.org/Documentation/dontdiff linux-2.6.15-rc5.org/include/linux/fs.h
linux-2.6.15-rc5-blocks/include/linux/fs.h
--- linux-2.6.15-rc5.org/include/linux/fs.h	2005-12-06 16:20:21.000000000 +0900
+++ linux-2.6.15-rc5-blocks/include/linux/fs.h	2005-12-06 16:26:01.000000000 +0900
@@ -450,7 +450,7 @@ struct inode {
 	unsigned int		i_blkbits;
 	unsigned long		i_blksize;
 	unsigned long		i_version;
-	unsigned long		i_blocks;
+	unsigned long long	i_blocks;
 	unsigned short          i_bytes;
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct semaphore	i_sem;
diff -uprN -X linux-2.6.15-rc5.org/Documentation/dontdiff linux-2.6.15-rc5.org/include/linux/stat.h
linux-2.6.15-rc5-blocks/include/linux/stat.h
--- linux-2.6.15-rc5.org/include/linux/stat.h	2005-10-28 09:02:08.000000000 +0900
+++ linux-2.6.15-rc5-blocks/include/linux/stat.h	2005-12-06 16:26:26.000000000 +0900
@@ -69,7 +69,7 @@ struct kstat {
 	struct timespec	mtime;
 	struct timespec	ctime;
 	unsigned long	blksize;
-	unsigned long	blocks;
+	unsigned long long	blocks;
 };

 #endif

-- Takashi Sato


-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 31+ messages in thread
[parent not found: <5eVqw-2ug-61@gated-at.bofh.it>]
* stat64 for over 2TB file returned invalid st_blocks
@ 2005-12-01 12:00 Takashi Sato
  2005-12-01 12:39 ` Jörn Engel
                   ` (3 more replies)
  0 siblings, 4 replies; 31+ messages in thread
From: Takashi Sato @ 2005-12-01 12:00 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel

Hi all,

I found a problem at stat64 on 32bit architecture.

When I called stat64 for a file which is larger than 2TB, stat64
returned an invalid number of blocks at st_blocks on 32bit
architecture, although it returned a valid number of blocks on 64bit
architecture(ia64).

The following describes the cause of this issue:
i_blocks in inode is 4bytes on 32bit architecture.  If it receives
more than 2^32 number of blocks, it would overflow and set an
invalid number to st_blocks.

Below describes a sequence of setting overflowed inode.i_blocks
to st_blocks through stat64.

1. generic_fillattr(struct inode *inode, struct kstat *stat)
  - Copy data from overflowed inode.i_blocks to kstat.blocks.

2. vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        struct kstat *stat)
  - Return invalid kstat.blocks to sys_stat64().

3. sys_stat64(char __user * filename, struct stat64 __user * statbuf)
  - Copy data from invalid kstat.blocks to stat64.st_blocks.

I also found the following problem.

- ioctl with FIOQSIZE command returns the size of file's data which
  has written to disk.  The size of file's data is calculated as
  follows in inode_get_bytes().
   
   (((loff_t)inode->i_blocks) << 9) + inode->i_bytes

   On the file which is larger than 2TB, the ioctl will return an
   invalid size because i_blocks can't express the right number of
   blocks.

I think the following modification is essential to fix these
problems.

1. Change the type of inode.i_blocks and kstat.blocks from unsigned
   long to unsigned long long.

2. Change the type of architecture dependent stat64.st_blocks in
   include/asm/asm-*/stat.h from unsigned long to unsigned long long.
   I tried modifying only stat64 of 32bit architecture
   (include/asm-i386/stat.h).

I have some tested for a file whose size is 3TB on JFS filesystem.
The following is the patch.

Signed-off-by: Takashi Sato <sho@bsd.tnes.nec.co.jp>

diff -uprN -X linux-2.6.14.org/Documentation/dontdiff linux-2.6.14.or
g/include/asm-i386/stat.h linux-2.6.14-blocks/include/asm-i386/stat.h
--- linux-2.6.14.org/include/asm-i386/stat.h 2005-10-28 09:02:08.000000000 +0900
+++ linux-2.6.14-blocks/include/asm-i386/stat.h 2005-11-18 22:42:37.000000000 +0900
@@ -58,8 +58,7 @@ struct stat64 {
  long long st_size;
  unsigned long st_blksize;
 
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long __pad4;  /* future possible st_blocks high bits */
+ unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
 
  unsigned long st_atime;
  unsigned long st_atime_nsec;
diff -uprN -X linux-2.6.14.org/Documentation/dontdiff linux-2.6.14.or
g/include/linux/fs.h linux-2.6.14-blocks/include/linux/fs.h
--- linux-2.6.14.org/include/linux/fs.h 2005-10-28 09:02:08.000000000 +0900
+++ linux-2.6.14-blocks/include/linux/fs.h 2005-11-18 17:08:03.000000000 +0900
@@ -438,7 +438,7 @@ struct inode {
  unsigned int  i_blkbits;
  unsigned long  i_blksize;
  unsigned long  i_version;
- unsigned long  i_blocks;
+ unsigned long long i_blocks;
  unsigned short          i_bytes;
  spinlock_t  i_lock; /* i_blocks, i_bytes, maybe i_size */
  struct semaphore i_sem;
diff -uprN -X linux-2.6.14.org/Documentation/dontdiff linux-2.6.14.or
g/include/linux/stat.h linux-2.6.14-blocks/include/linux/stat.h
--- linux-2.6.14.org/include/linux/stat.h 2005-10-28 09:02:08.000000000 +0900
+++ linux-2.6.14-blocks/include/linux/stat.h 2005-11-18 17:08:56.000000000 +0900
@@ -69,7 +69,7 @@ struct kstat {
  struct timespec mtime;
  struct timespec ctime;
  unsigned long blksize;
- unsigned long blocks;
+ unsigned long long blocks;
 };
 
 #endif

Any feedback and comments are welcome.

Best regards, Takashi Sato

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2005-12-10 11:23 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-12-06 12:42 stat64 for over 2TB file returned invalid st_blocks Takashi Sato
2005-12-06 14:30 ` Dave Kleikamp
2005-12-06 14:48   ` Trond Myklebust
2005-12-06 14:51     ` Dave Kleikamp
2005-12-06 21:24     ` Andreas Dilger
2005-12-07  0:59       ` Trond Myklebust
2005-12-07 10:57       ` Takashi Sato
2005-12-07 13:52         ` Trond Myklebust
2005-12-07 15:01           ` Dave Kleikamp
2005-12-07 15:34             ` Trond Myklebust
2005-12-07 16:34               ` Dave Kleikamp
2005-12-07 18:55                 ` Trond Myklebust
2005-12-08 11:38                 ` Takashi Sato
2005-12-08 14:27                   ` Trond Myklebust
2005-12-08 14:50                     ` Anton Altaparmakov
2005-12-08 15:03                       ` Trond Myklebust
2005-12-10 11:22                     ` Takashi Sato
     [not found] <5eVqw-2ug-61@gated-at.bofh.it>
2005-12-03  2:19 ` Bodo Eggert
  -- strict thread matches above, loose matches on Subject: below --
2005-12-01 12:00 Takashi Sato
2005-12-01 12:39 ` Jörn Engel
2005-12-01 12:52 ` Jörn Engel
2005-12-01 13:52   ` Avi Kivity
2005-12-01 14:32 ` Dave Kleikamp
2005-12-02 13:18   ` Takashi Sato
2005-12-02 14:11     ` Dave Kleikamp
2005-12-02 18:58     ` Andreas Dilger
2005-12-03 13:00       ` Takashi Sato
2005-12-05  8:11         ` Andreas Dilger
2005-12-05 12:35           ` Takashi Sato
2005-12-05 13:34           ` Trond Myklebust
2005-12-01 14:53 ` Al Viro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).