Skip to content
  • Wengang Wang's avatar
    ocfs2: pass "new" parameter to ocfs2_init_xattr_bucket · 9c339255
    Wengang Wang authored
    
    
    This patch fixes the following crash:
    
      kernel BUG at fs/ocfs2/uptodate.c:530!
      Modules linked in: ocfs2(F) ocfs2_dlmfs ocfs2_stack_o2cb ocfs2_dlm ocfs2_nodemanager ocfs2_stackglue configfs bridge xen_pciback xen_netback xen_blkback xen_gntalloc xen_gntdev xen_evtchn xenfs xen_privcmd sunrpc 8021q garp stp llc bonding be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i libcxgbi cxgb3 mdio ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr ipv6 iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi iTCO_wdt iTCO_vendor_support dcdbas coretemp freq_table mperf microcode pcspkr serio_raw bnx2 lpc_ich mfd_core i5k_amb i5000_edac edac_core e1000e sg shpchp ext4(F) jbd2(F) mbcache(F) dm_round_robin(F) sr_mod(F) cdrom(F) usb_storage(F) sd_mod(F) crc_t10dif(F) pata_acpi(F) ata_generic(F) ata_piix(F) mptsas(F) mptscsih(F) mptbase(F) scsi_transport_sas(F) radeon(F)
       ttm(F) drm_kms_helper(F) drm(F) hwmon(F) i2c_algo_bit(F) i2c_core(F) dm_multipath(F) dm_mirror(F) dm_region_hash(F) dm_log(F) dm_mod(F)
      CPU 5
      Pid: 21303, comm: xattr-test Tainted: GF       W    3.8.13-30.el6uek.x86_64 #2 Dell Inc. PowerEdge 1950/0M788G
      RIP: ocfs2_set_new_buffer_uptodate+0x51/0x60 [ocfs2]
      Process xattr-test (pid: 21303, threadinfo ffff880017aca000, task ffff880016a2c480)
      Call Trace:
        ocfs2_init_xattr_bucket+0x8a/0x120 [ocfs2]
        ocfs2_cp_xattr_bucket+0xbb/0x1b0 [ocfs2]
        ocfs2_extend_xattr_bucket+0x20a/0x2f0 [ocfs2]
        ocfs2_add_new_xattr_bucket+0x23e/0x4b0 [ocfs2]
        ocfs2_xattr_set_entry_index_block+0x13c/0x3d0 [ocfs2]
        ocfs2_xattr_block_set+0xf9/0x220 [ocfs2]
        __ocfs2_xattr_set_handle+0x118/0x710 [ocfs2]
        ocfs2_xattr_set+0x691/0x880 [ocfs2]
        ocfs2_xattr_user_set+0x46/0x50 [ocfs2]
        generic_setxattr+0x96/0xa0
        __vfs_setxattr_noperm+0x7b/0x170
        vfs_setxattr+0xbc/0xc0
        setxattr+0xde/0x230
        sys_fsetxattr+0xc6/0xf0
        system_call_fastpath+0x16/0x1b
      Code: 41 80 0c 24 01 48 89 df e8 7d f0 ff ff 4c 89 e6 48 89 df e8 a2 fe ff ff 48 89 df e8 3a f0 ff ff 48 8b 1c 24 4c 8b 64 24 08 c9 c3 <0f> 0b eb fe 90 90 90 90 90 90 90 90 90 90 90 55 48 89 e5 66 66
      RIP  ocfs2_set_new_buffer_uptodate+0x51/0x60 [ocfs2]
    
    It hit the BUG_ON() in ocfs2_set_new_buffer_uptodate():
    
        void ocfs2_set_new_buffer_uptodate(struct ocfs2_caching_info *ci,
                                           struct buffer_head *bh)
        {
              /* This should definitely *not* exist in our cache */
              if (ocfs2_buffer_cached(ci, bh))
                      printk(KERN_ERR "bh->b_blocknr: %lu @ %p\n", bh->b_blocknr, bh);
              BUG_ON(ocfs2_buffer_cached(ci, bh));
    
              set_buffer_uptodate(bh);
    
              ocfs2_metadata_cache_io_lock(ci);
              ocfs2_set_buffer_uptodate(ci, bh);
              ocfs2_metadata_cache_io_unlock(ci);
        }
    
    The problem here is:
    
    We cached a block, but the buffer_head got reused.  When we are to pick
    up this block again, a new buffer_head created with UPTODATE flag
    cleared.  ocfs2_buffer_uptodate() returned false since no UPTODATE is
    set on the buffer_head.  so we set this block to cache as a NEW block,
    then it failed at asserting block is not in cache.
    
    The fix is to add a new parameter indicating the bucket is a new
    allocated or not to ocfs2_init_xattr_bucket().
    ocfs2_init_xattr_bucket() assert block not cached accordingly.
    
    Signed-off-by: default avatarWengang Wang <wen.gang.wang@oracle.com>
    Cc: Joel Becker <jlbec@evilplan.org>
    Reviewed-by: default avatarMark Fasheh <mfasheh@suse.de>
    Cc: Joe Jin <joe.jin@oracle.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    9c339255