All of lore.kernel.org
 help / color / mirror / Atom feed
* Reading page from given block device
@ 2002-05-08 20:48 Pavel Machek
  2002-05-08 21:21 ` Andrew Morton
  0 siblings, 1 reply; 10+ messages in thread
From: Pavel Machek @ 2002-05-08 20:48 UTC (permalink / raw)
  To: kernel list

Hi!

For swsusp, I kind of need to read 4K from given block device.

Here's my attempt:

static int bdev_read_page(kdev_t dev, long pos, void *buf)
{
        struct buffer_head *bh;
        struct block_device *bdev;

        if (pos%PAGE_SIZE) panic("Sorry, dave, I can't let you do
that!\n");
        bdev = bdget(kdev_t_to_nr(dev));
        if (!bdev) {
                printk("No block device for %s\n", __bdevname(dev));
                BUG();
        }
        printk("C");
        bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
        printk("D");
        bdput(bdev);
        if (!bh || (!bh->b_data)) {
                return -1;
        }
        memcpy(buf, bh->b_data, PAGE_SIZE);
        bforget(bh);                    /* FIXME: maybe bforget should
be here */
        return 0;
}

It works *once*, second time it deadlocks in __bread(). I tried both
bforget() and brelse(). Kernel is 2.5.13. What am I doing wrong/what's
wrong?

									Pavel
-- 
(about SSSCA) "I don't say this lightly.  However, I really think that the U.S.
no longer is classifiable as a democracy, but rather as a plutocracy." --hpa

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

* Re: Reading page from given block device
  2002-05-08 20:48 Reading page from given block device Pavel Machek
@ 2002-05-08 21:21 ` Andrew Morton
  2002-05-08 21:30   ` Andrew Morton
                     ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Andrew Morton @ 2002-05-08 21:21 UTC (permalink / raw)
  To: Pavel Machek; +Cc: kernel list

Pavel Machek wrote:
> 
> Hi!
> 
> For swsusp, I kind of need to read 4K from given block device.
> 
> Here's my attempt:
> 
> static int bdev_read_page(kdev_t dev, long pos, void *buf)
> {
>         struct buffer_head *bh;
>         struct block_device *bdev;
> 
>         if (pos%PAGE_SIZE) panic("Sorry, dave, I can't let you do
> that!\n");

It's possible I guess that someone has a pinned buffer against
the same page which has a different block size.  See the "lock up"
comment over __getblk().

>         bdev = bdget(kdev_t_to_nr(dev));
>         if (!bdev) {
>                 printk("No block device for %s\n", __bdevname(dev));
>                 BUG();
>         }
>         printk("C");
>         bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
>         printk("D");
>         bdput(bdev);
>         if (!bh || (!bh->b_data)) {
>                 return -1;
>         }
>         memcpy(buf, bh->b_data, PAGE_SIZE);

You'll need to kmap bh->b_page before copying the data.

> 
> It works *once*, second time it deadlocks in __bread(). I tried both
> bforget() and brelse(). Kernel is 2.5.13. What am I doing wrong/what's
> wrong?

brelse is safer.

Please try 2.5.14.  2.5.13 had a few leaky problems which
could perhaps result in a pinned buffer which will cause
try_to_free_buffers() to fail, which triggers the __getblk()
nastiness.

Generally, if you're reading from a swap partition then
it may be better to use brw_page().  bread() is backed
by bdev->bd_inode->i_mapping, and there may be coherency
problems if the target blocks are currently in swapper_space. 
Although probably your bdget() here will create a new inode
with no pagecache, so it'll work OK.

It really depends on what you're trying to do.  It may
be best to just cook up a local buffer_head and submit
the darn thing.

-

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

* Re: Reading page from given block device
  2002-05-08 21:21 ` Andrew Morton
@ 2002-05-08 21:30   ` Andrew Morton
  2002-05-08 22:56   ` Pavel Machek
  2002-05-08 22:59   ` Pavel Machek
  2 siblings, 0 replies; 10+ messages in thread
From: Andrew Morton @ 2002-05-08 21:30 UTC (permalink / raw)
  To: Pavel Machek, kernel list

Andrew Morton wrote:
> 
> ..
> >         memcpy(buf, bh->b_data, PAGE_SIZE);
> 
> You'll need to kmap bh->b_page before copying the data.

No you won't.  blockdev mappings don't use highmem.

-

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

* Re: Reading page from given block device
  2002-05-08 21:21 ` Andrew Morton
  2002-05-08 21:30   ` Andrew Morton
@ 2002-05-08 22:56   ` Pavel Machek
       [not found]     ` <3CD9AE15.114D13E3@zip.com.au>
  2002-05-09  4:42     ` Alexander Viro
  2002-05-08 22:59   ` Pavel Machek
  2 siblings, 2 replies; 10+ messages in thread
From: Pavel Machek @ 2002-05-08 22:56 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Pavel Machek, kernel list

Hi!

> > For swsusp, I kind of need to read 4K from given block device.
> > 
> > Here's my attempt:
> > 
> > static int bdev_read_page(kdev_t dev, long pos, void *buf)
> > {
> >         struct buffer_head *bh;
> >         struct block_device *bdev;
> > 
> >         if (pos%PAGE_SIZE) panic("Sorry, dave, I can't let you do
> > that!\n");
> 
> It's possible I guess that someone has a pinned buffer against
> the same page which has a different block size.  See the "lock up"
> comment over __getblk().

Well, I'm doing it during boot, and this is swap partition; it should
not have been accessed previously.

> >         bdev = bdget(kdev_t_to_nr(dev));
> >         if (!bdev) {
> >                 printk("No block device for %s\n", __bdevname(dev));
> >                 BUG();
> >         }
> >         printk("C");
> >         bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
> >         printk("D");
> >         bdput(bdev);
> >         if (!bh || (!bh->b_data)) {
> >                 return -1;
> >         }
> >         memcpy(buf, bh->b_data, PAGE_SIZE);
> 
> You'll need to kmap bh->b_page before copying the data.

This machine does not have himem.

> > It works *once*, second time it deadlocks in __bread(). I tried both
> > bforget() and brelse(). Kernel is 2.5.13. What am I doing wrong/what's
> > wrong?
> 
> brelse is safer.
> 
> Please try 2.5.14.  2.5.13 had a few leaky problems which
> could perhaps result in a pinned buffer which will cause
> try_to_free_buffers() to fail, which triggers the __getblk()
> nastiness.
> 
> Generally, if you're reading from a swap partition then
> it may be better to use brw_page().  bread() is backed

It is swap partition, but system does not yet know its swap at that
point. This is next boot, that partition was not yet accessed.
								Pavel
-- 
Casualities in World Trade Center: ~3k dead inside the building,
cryptography in U.S.A. and free speech in Czech Republic.

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

* Re: Reading page from given block device
  2002-05-08 21:21 ` Andrew Morton
  2002-05-08 21:30   ` Andrew Morton
  2002-05-08 22:56   ` Pavel Machek
@ 2002-05-08 22:59   ` Pavel Machek
  2 siblings, 0 replies; 10+ messages in thread
From: Pavel Machek @ 2002-05-08 22:59 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Pavel Machek, kernel list

Hi!

> > Hi!
> > 
> > For swsusp, I kind of need to read 4K from given block device.
> > 
> > Here's my attempt:
> > 
> > static int bdev_read_page(kdev_t dev, long pos, void *buf)
> > {
> >         struct buffer_head *bh;
> >         struct block_device *bdev;
> > 
> >         if (pos%PAGE_SIZE) panic("Sorry, dave, I can't let you do
> > that!\n");
> 
> It's possible I guess that someone has a pinned buffer against
> the same page which has a different block size.  See the "lock up"
> comment over __getblk().
> 
> >         bdev = bdget(kdev_t_to_nr(dev));
> >         if (!bdev) {
> >                 printk("No block device for %s\n", __bdevname(dev));
> >                 BUG();
> >         }
> >         printk("C");
> >         bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
> >         printk("D");
> >         bdput(bdev);
> >         if (!bh || (!bh->b_data)) {
> >                 return -1;
> >         }
> >         memcpy(buf, bh->b_data, PAGE_SIZE);
> 
> You'll need to kmap bh->b_page before copying the data.
> 
> > 
> > It works *once*, second time it deadlocks in __bread(). I tried both
> > bforget() and brelse(). Kernel is 2.5.13. What am I doing wrong/what's
> > wrong?
> 
> brelse is safer.
> 
> Please try 2.5.14.  2.5.13 had a few leaky problems which
> could perhaps result in a pinned buffer which will cause
> try_to_free_buffers() to fail, which triggers the __getblk()
> nastiness.

Went with brelse(), and switched to 2.5.14; still deadlocks on second
read.
								Pavel
-- 
Casualities in World Trade Center: ~3k dead inside the building,
cryptography in U.S.A. and free speech in Czech Republic.

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

* Re: Reading page from given block device
       [not found]     ` <3CD9AE15.114D13E3@zip.com.au>
@ 2002-05-08 23:15       ` Pavel Machek
  2002-05-09  0:07         ` Andrew Morton
  0 siblings, 1 reply; 10+ messages in thread
From: Pavel Machek @ 2002-05-08 23:15 UTC (permalink / raw)
  To: Andrew Morton; +Cc: kernel list

Hi!
> > It is swap partition, but system does not yet know its swap at that
> > point. This is next boot, that partition was not yet accessed.
> >                                                                 Pavel
> 
> In that case, I don't know.  Sorry.  sysrq-T is your
> friend (and kgdb is your god).  Let me know...

Call trace is 

c01229ed -- bdev_read_page
c0134b5b -- __bread

That's stable (as expected). Under that, it was seen in

c0134a57 -- __getblk
	    blk_get_queue
	    ata_get_queue

Second try:

c0134a28 -- __getblk
	    __get_hash_table

Third try:

c0134a28 -- __getblk
c01343cc -- __get_hash_table

Fourth try:

c0134abd -- __getblk

... I should get some sleep I guess...
								Pavel
-- 
Casualities in World Trade Center: ~3k dead inside the building,
cryptography in U.S.A. and free speech in Czech Republic.

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

* Re: Reading page from given block device
  2002-05-08 23:15       ` Pavel Machek
@ 2002-05-09  0:07         ` Andrew Morton
  0 siblings, 0 replies; 10+ messages in thread
From: Andrew Morton @ 2002-05-09  0:07 UTC (permalink / raw)
  To: Pavel Machek; +Cc: kernel list

Pavel Machek wrote:
> 
> ...
> Second try:
> 
> c0134a28 -- __getblk
>             __get_hash_table

hmm.  It looks like your blockdev may have the wrong
blocksize in bd_inode->i_blkbits, and __get_hash_table
cannot find the 4k block against the 1k blocksize device.
It keeps returning zero.

The new pagecache-based __get_hash_table uses bd_inode->i_blkbits
to go from a block number to a pagecache index.  That works
fine when called via the official `bread()' function, but 
probably your __bread() approach has confused it.

Try running set_blocksize(bdev, PAGE_SIZE) before calling
__bread().  


-

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

* Re: Reading page from given block device
  2002-05-08 22:56   ` Pavel Machek
       [not found]     ` <3CD9AE15.114D13E3@zip.com.au>
@ 2002-05-09  4:42     ` Alexander Viro
  2002-05-09 21:36       ` Pavel Machek
  1 sibling, 1 reply; 10+ messages in thread
From: Alexander Viro @ 2002-05-09  4:42 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Andrew Morton, kernel list



On Thu, 9 May 2002, Pavel Machek wrote:

> Well, I'm doing it during boot, and this is swap partition; it should
> not have been accessed previously.
> 
> > >         bdev = bdget(kdev_t_to_nr(dev));
> > >         if (!bdev) {
> > >                 printk("No block device for %s\n", __bdevname(dev));
> > >                 BUG();
> > >         }
> > >         printk("C");

blkdev_open(bdev, FMODE_READ, O_RDONLY, BDEV_RAW)

> > >         bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
> > >         printk("D");
> > >         bdput(bdev);

nope - blkdev_put(bdev), and do it _after_ you are done with buffers.
Oh, and you need to do brelse().

> > >         if (!bh || (!bh->b_data)) {
> > >                 return -1;

However, I would really suggest to open the bugger once, do all IO and
then close it.  See how raw.c and friends deal with these problems.


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

* Re: Reading page from given block device
  2002-05-09  4:42     ` Alexander Viro
@ 2002-05-09 21:36       ` Pavel Machek
  2002-05-09 21:45         ` Alexander Viro
  0 siblings, 1 reply; 10+ messages in thread
From: Pavel Machek @ 2002-05-09 21:36 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Andrew Morton, kernel list

Hi!

> > Well, I'm doing it during boot, and this is swap partition; it should
> > not have been accessed previously.
> > 
> > > >         bdev = bdget(kdev_t_to_nr(dev));
> > > >         if (!bdev) {
> > > >                 printk("No block device for %s\n", __bdevname(dev));
> > > >                 BUG();
> > > >         }
> > > >         printk("C");
> 
> blkdev_open(bdev, FMODE_READ, O_RDONLY, BDEV_RAW)

blkdev_open is 

fs.h:extern int blkdev_open(struct inode *, struct file *);

... I can't see how to use it in this context.

> > > >         if (!bh || (!bh->b_data)) {
> > > >                 return -1;
> 
> However, I would really suggest to open the bugger once, do all IO and
> then close it.  See how raw.c and friends deal with these problems.

Performance should not matter here.
								Pavel

-- 
Casualities in World Trade Center: ~3k dead inside the building,
cryptography in U.S.A. and free speech in Czech Republic.

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

* Re: Reading page from given block device
  2002-05-09 21:36       ` Pavel Machek
@ 2002-05-09 21:45         ` Alexander Viro
  0 siblings, 0 replies; 10+ messages in thread
From: Alexander Viro @ 2002-05-09 21:45 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Andrew Morton, kernel list



On Thu, 9 May 2002, Pavel Machek wrote:

> Hi!
> 
> > > Well, I'm doing it during boot, and this is swap partition; it should
> > > not have been accessed previously.
> > > 
> > > > >         bdev = bdget(kdev_t_to_nr(dev));
> > > > >         if (!bdev) {
> > > > >                 printk("No block device for %s\n", __bdevname(dev));
> > > > >                 BUG();
> > > > >         }
> > > > >         printk("C");
> > 
> > blkdev_open(bdev, FMODE_READ, O_RDONLY, BDEV_RAW)
> 
> blkdev_open is 

grr...  s/open/get/ - sorry.

> fs.h:extern int blkdev_open(struct inode *, struct file *);
> 
> ... I can't see how to use it in this context.
> 
> > > > >         if (!bh || (!bh->b_data)) {
> > > > >                 return -1;
> > 
> > However, I would really suggest to open the bugger once, do all IO and
> > then close it.  See how raw.c and friends deal with these problems.
> 
> Performance should not matter here.

Yeah, but amount of places that mess with kdev_t should.


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

end of thread, other threads:[~2002-05-09 21:46 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-05-08 20:48 Reading page from given block device Pavel Machek
2002-05-08 21:21 ` Andrew Morton
2002-05-08 21:30   ` Andrew Morton
2002-05-08 22:56   ` Pavel Machek
     [not found]     ` <3CD9AE15.114D13E3@zip.com.au>
2002-05-08 23:15       ` Pavel Machek
2002-05-09  0:07         ` Andrew Morton
2002-05-09  4:42     ` Alexander Viro
2002-05-09 21:36       ` Pavel Machek
2002-05-09 21:45         ` Alexander Viro
2002-05-08 22:59   ` Pavel Machek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.