[Bugme-new] [Bug 9171] New: __bread and 2TiB problem
bugme-daemon at bugzilla.kernel.org
bugme-daemon at bugzilla.kernel.org
Tue Oct 16 08:47:03 PDT 2007
http://bugzilla.kernel.org/show_bug.cgi?id=9171
Summary: __bread and 2TiB problem
Product: IO/Storage
Version: 2.5
KernelVersion: 2.6.22
Platform: All
OS/Version: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: Block Layer
AssignedTo: axboe at kernel.dk
ReportedBy: shura_mam at mail.ru
Most recent kernel where this bug did not occur:
Distribution: SUSE 10.1 (2.6.18) and Debian (2.6.22)
Hardware Environment:
Software Environment:
Problem Description:
Steps to reproduce:
Compile the following module and try to mount any device of size > 2TiB.
and you will see the infinite loop
"__find_get_block_slow() failed"
///////////////////////////////////////////////////////////
// This example shows __bread error if block >= 2^32
//
//
///////////////////////////////////////////////////////////
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/vermagic.h>
#define USE_BREAD "Activate this macros to get the __bread error"
#ifndef USE_BREAD
///////////////////////////////////////////////////////////
// end_bio_io_page
//
//
///////////////////////////////////////////////////////////
static int
end_bio_io_page(
struct bio *bio,
unsigned int bytes_done,
int error
)
{
struct page *page = bio->bi_private;
if (bio->bi_size)
return 1;
if (!error)
SetPageUptodate(page);
else
printk(KERN_WARNING "t2tb: error %d reading page\n", error);
unlock_page(page);
bio_put(bio);
return 0;
}
///////////////////////////////////////////////////////////
// t2tb_read_page
//
//
///////////////////////////////////////////////////////////
struct page*
t2tb_read_page(
struct super_block *sb,
sector_t sector
)
{
struct page *page;
struct bio *bio;
page = alloc_page(GFP_KERNEL);
if ( unlikely(!page) )
return NULL;
ClearPageUptodate(page);
ClearPageDirty(page);
lock_page(page);
bio = bio_alloc(GFP_KERNEL, 1);
if (unlikely(!bio)) {
__free_page(page);
return NULL;
}
bio->bi_sector = sector;
bio->bi_bdev = sb->s_bdev;
bio_add_page(bio, page, PAGE_SIZE, 0);
bio->bi_end_io = end_bio_io_page;
bio->bi_private = page;
bio_get(bio);
submit_bio( READ_SYNC, bio);
wait_on_page_locked(page);
bio_put(bio);
if (!PageUptodate(page)) {
__free_page(page);
return NULL;
}
return page;
}
///////////////////////////////////////////////////////////
// t2tb_read
//
//
///////////////////////////////////////////////////////////
static int
t2tb_read(
struct super_block *sb,
sector_t sector
)
{
struct page* page;
printk(KERN_NOTICE ": read(0x%llx)\n", sector );
page = t2tb_read_page( sb, sector );
if ( NULL == page )
return -1;
__free_page( page );
return 0;
}
#else
///////////////////////////////////////////////////////////
// t2tb_read
//
//
///////////////////////////////////////////////////////////
static int
t2tb_read(
struct super_block *sb,
sector_t sector
)
{
struct buffer_head* bh;
printk(KERN_NOTICE ": read(0x%llx)\n", sector );
bh = __bread( sb->s_bdev, sector, 512 );
if ( NULL == bh )
return -1;
__brelse(bh);
return 0;
}
#endif
///////////////////////////////////////////////////////////
// t2tb_read_super
//
//
///////////////////////////////////////////////////////////
static int
t2tb_read_super(
struct super_block * sb,
void * data,
int silent
)
{
set_blocksize( sb->s_bdev, 512 );
sb->s_blocksize = 512;
sb->s_blocksize_bits = 9;
printk(KERN_NOTICE "t2tb_read_super: enter\n" );
t2tb_read( sb, 0 );
t2tb_read( sb, 0x100000000ull-1 );
//
// If 't2tb_read' uses __bread then the next function will never return.
// Infinite loop at "__find_get_block_slow() failed" occurs
//
t2tb_read( sb, 0x100000000ull );
printk(KERN_NOTICE "t2tb_read_super: exit\n" );
return -EINVAL;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
static int
t2tb_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,
void *data, struct vfsmount* mnt)
{
return get_sb_bdev(fs_type, flags, dev_name, data, t2tb_read_super, mnt );
}
#else
static struct super_block *
t2tb_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,
void *data)
{
return get_sb_bdev(fs_type, flags, dev_name, data, t2tb_read_super );
}
#endif
static struct file_system_type t2tb_fs_type = {
.owner = THIS_MODULE,
.name = "t2tb",
.get_sb = t2tb_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
MODULE_INFO(vermagic, VERMAGIC_STRING);
struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = "t2tb",
.init = init_module,
.exit = cleanup_module,
};
///////////////////////////////////////////////////////////
// t2tb_init
//
// module init function
///////////////////////////////////////////////////////////
static int
__init t2tb_init(void)
{
int ret = register_filesystem(&t2tb_fs_type);
if ( 0 != ret )
return ret;
printk(KERN_NOTICE ": t2tb driver loaded\n");
return 0;
}
///////////////////////////////////////////////////////////
// t2tb_exit
//
// module exit function
///////////////////////////////////////////////////////////
static void
__exit t2tb_exit(void)
{
unregister_filesystem(&t2tb_fs_type);
printk(KERN_NOTICE ": t2tb driver unloaded\n");
}
module_init(t2tb_init)
module_exit(t2tb_exit)
--
Configure bugmail: http://bugzilla.kernel.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
More information about the Bugme-new
mailing list