Re: [PATCH 2/5] cachefiles: drop direct usage of ->bmap method.

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

 



On Wed, Apr 8, 2020 at 8:32 PM NeilBrown <neilb@xxxxxxx> wrote:
>
> On Thu, Jan 09 2020, Carlos Maiolino wrote:
>
> > Replace the direct usage of ->bmap method by a bmap() call.
> >
> > Reviewed-by: Christoph Hellwig <hch@xxxxxx>
> > Signed-off-by: Carlos Maiolino <cmaiolino@xxxxxxxxxx>
> > ---
> >  fs/cachefiles/rdwr.c | 27 ++++++++++++++-------------
> >  1 file changed, 14 insertions(+), 13 deletions(-)
> >
> > diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
> > index 44a3ce1e4ce4..1dc97f2d6201 100644
> > --- a/fs/cachefiles/rdwr.c
> > +++ b/fs/cachefiles/rdwr.c
> > @@ -396,7 +396,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
> >       struct cachefiles_object *object;
> >       struct cachefiles_cache *cache;
> >       struct inode *inode;
> > -     sector_t block0, block;
> > +     sector_t block;
> >       unsigned shift;
> >       int ret;
> >
> > @@ -412,7 +412,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
> >
> >       inode = d_backing_inode(object->backer);
> >       ASSERT(S_ISREG(inode->i_mode));
> > -     ASSERT(inode->i_mapping->a_ops->bmap);
> >       ASSERT(inode->i_mapping->a_ops->readpages);
> >
> >       /* calculate the shift required to use bmap */
> > @@ -428,12 +427,14 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
> >        *   enough for this as it doesn't indicate errors, but it's all we've
> >        *   got for the moment
> >        */
> > -     block0 = page->index;
> > -     block0 <<= shift;
> > +     block = page->index;
> > +     block <<= shift;
> > +
> > +     ret = bmap(inode, &block);
> > +     ASSERT(ret < 0);
> >

I too am hitting this assert with a very simple test (see below) and I
saw ret == *block == 0
This used to fall through and be handled in 'else if / else'

        if (block) {
                /* submit the apparently valid page to the backing fs to be
                 * read from disk */
                ret = cachefiles_read_backing_file_one(object, op, page);
        } else if (cachefiles_has_space(cache, 0, 1) == 0) {
                /* there's space in the cache we can use */
                fscache_mark_page_cached(op, page);
                fscache_retrieval_complete(op, 1);
                ret = -ENODATA;
        } else {
                goto enobufs;
        }


Test:
systemctl start cachefilesd
mount -o vers=3,fsc 127.0.0.1:/export /mnt
dd if=/dev/zero of=/mnt/file1.bin bs=1M count=1
echo 3 > /proc/sys/vm/drop_caches
dd if=/mnt/file1.bin of=/dev/null
echo 3 > /proc/sys/vm/drop_caches
dd if=/mnt/file1.bin of=/dev/null

FWIW, the below is 5.7-rc1 kernel plus the 3 patches I posted to linux-nfs

[ 1613.017827] readahead_oops. (8973): drop_caches: 3
[ 1613.100768] readahead_oops. (8973): drop_caches: 3
[ 1613.126040] CacheFiles:
[ 1613.127317] CacheFiles: Assertion failed
[ 1613.129130] ------------[ cut here ]------------
[ 1613.130901] kernel BUG at fs/cachefiles/rdwr.c:434!
[ 1613.132856] invalid opcode: 0000 [#1] SMP PTI
[ 1613.134590] CPU: 3 PID: 9010 Comm: dd Kdump: loaded Not tainted
5.7.0-rc1-bz1790933-bz1793560-fix3+ #13
[ 1613.138250] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
[ 1613.140544] RIP:
0010:cachefiles_read_or_alloc_page.cold+0x25c/0x361 [cachefiles]
[ 1613.143466] Code: 4c 89 c1 e8 05 05 97 c0 4c 8b 44 24 08 e9 b0 bb
ff ff 48 c7 c7 09 57 7d c0 e8 ef 04 97 c0 48 c7 c7 60 6c 7d c0 e8 e3
04 97 c0 <0f> 0b 48 c7 c7 09 57 7d c0 e8 d5 04 97 c0 48 c7 c7 60 6c 7d
c0 e8
[ 1613.188264] RSP: 0018:ffffa13d00527c40 EFLAGS: 00010246
[ 1613.190334] RAX: 000000000000001c RBX: ffff8e8533290600 RCX: 0000000000000000
[ 1613.193104] RDX: 0000000000000000 RSI: ffff8e8537cd9c28 RDI: ffff8e8537cd9c28
[ 1613.195875] RBP: ffff8e852c42ea80 R08: 000000000000028c R09: 000000000000002b
[ 1613.198698] R10: ffffa13d00527af0 R11: 0000000000000000 R12: 0000000000000000
[ 1613.201513] R13: ffffdc5b05673700 R14: ffff8e8526636c00 R15: ffff8e8533290668
[ 1613.204311] FS:  00007f45a30c7580(0000) GS:ffff8e8537cc0000(0000)
knlGS:0000000000000000
[ 1613.207470] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1613.209724] CR2: 000055c636d58000 CR3: 00000002331d2000 CR4: 00000000000406e0
[ 1613.212513] Call Trace:
[ 1613.213624]  __fscache_read_or_alloc_page+0x2a5/0x320 [fscache]
[ 1613.215999]  __nfs_readpage_from_fscache+0x49/0xf0 [nfs]
[ 1613.218128]  nfs_readpage+0xf8/0x260 [nfs]
[ 1613.219805]  generic_file_read_iter+0x6f3/0xe40
[ 1613.221639]  ? nfs3_proc_commit_setup+0x10/0x10 [nfsv3]
[ 1613.223726]  ? nfs_check_cache_invalid+0x33/0x90 [nfs]
[ 1613.225784]  nfs_file_read+0x6d/0xa0 [nfs]
[ 1613.227464]  new_sync_read+0x12a/0x1c0
[ 1613.228981]  vfs_read+0x9d/0x150
[ 1613.230295]  ksys_read+0x5f/0xe0
[ 1613.231624]  do_syscall_64+0x5b/0x1c0
[ 1613.233180]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 1613.235191] RIP: 0033:0x7f45a2fef3e2





> > -     block = inode->i_mapping->a_ops->bmap(inode->i_mapping, block0);
> >       _debug("%llx -> %llx",
> > -            (unsigned long long) block0,
> > +            (unsigned long long) (page->index << shift),
> >              (unsigned long long) block);
> >
> >       if (block) {
> > @@ -711,7 +712,6 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
> >
> >       inode = d_backing_inode(object->backer);
> >       ASSERT(S_ISREG(inode->i_mode));
> > -     ASSERT(inode->i_mapping->a_ops->bmap);
> >       ASSERT(inode->i_mapping->a_ops->readpages);
> >
> >       /* calculate the shift required to use bmap */
> > @@ -728,7 +728,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
> >
> >       ret = space ? -ENODATA : -ENOBUFS;
> >       list_for_each_entry_safe(page, _n, pages, lru) {
> > -             sector_t block0, block;
> > +             sector_t block;
> >
> >               /* we assume the absence or presence of the first block is a
> >                * good enough indication for the page as a whole
> > @@ -736,13 +736,14 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
> >                *   good enough for this as it doesn't indicate errors, but
> >                *   it's all we've got for the moment
> >                */
> > -             block0 = page->index;
> > -             block0 <<= shift;
> > +             block = page->index;
> > +             block <<= shift;
> > +
> > +             ret = bmap(inode, &block);
> > +             ASSERT(!ret);
>
> Hi,
>  this change corrupts 'ret'.
>  Some paths from here down change ret, but some paths to do not.
>  So it is possible that this function would previously return -ENODATA
>  or -ENOBUFS, but now it returns 0.
>
>  This gets caught by a BUG_ON in __nfs_readpages_from_fscache().
>
>  Maybe a new variable should be introduced?
>  or maybe ASSERT(!bmap(..));
>  Or maybe if (bmap() != 0) ASSET(0);
>
> ??
>
> https://bugzilla.opensuse.org/show_bug.cgi?id=1168841
>
> NeilBrown
>
>
> >
> > -             block = inode->i_mapping->a_ops->bmap(inode->i_mapping,
> > -                                                   block0);
> >               _debug("%llx -> %llx",
> > -                    (unsigned long long) block0,
> > +                    (unsigned long long) (page->index << shift),
> >                      (unsigned long long) block);
> >
> >               if (block) {
> > --
> > 2.23.0




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux