All of lore.kernel.org
 help / color / mirror / Atom feed
* [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
@ 2017-01-18  9:11 Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 01/18] kref: Add KREF_INIT() Elena Reshetova
                   ` (19 more replies)
  0 siblings, 20 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova

Changes since v1:
 - kref INIT fixes are moved to a proper separate commit
 - Peter's commits are now properly integrated into series 
 - various small fixes are incorporated based on testing
   results and feedback

This patch series is build on top of Peter's Zijlstra patches
that provide refcount_t type and API definition.
The rest of patches convert various places of kernel subsystems
where atomic_t was used for reference counting to new refcount_t type and API.
By doing this, we make sure that underflows and overflows
cannot occur in these places and therefore no use-after-free situation
can be created and misused by an attacker.

The patches still have a number of rough places, where we especially
would need a feedback. The patches also do not cover absolutely all
cases where atomic_t is used as refcounter. The more complex places
are left for the future patch series and their occurences are documented in
https://docs.google.com/document/d/1Gw-SQoxJ3RAofGrkEm7qEyTC48mst3svVjxnVKXyGPs/edit?usp=sharing

The automatic finding of atomic_t variables used as refcounters
was done using Coccinelle (http://coccinelle.lip6.fr/).
We thank Julia Lawall for helping us to get started on this!

Testing and compilation status:
 - Compiles on x86, boots to GUI, no warns in the log
 - Compiles for arm (defconfig, imx_v6_v7_defconfig), but cannot test

The patches are on top of linux-4.10-rc2. Patches
would greatly benefit from compile proof test and runtime tests
on all arches because of extensive changes.

Elena Reshetova (11):
  kernel, mm: convert from atomic_t to refcount_t
  net: convert from atomic_t to refcount_t
  fs: convert from atomic_t to refcount_t
  security: convert from atomic_t to refcount_t
  sound: convert from atomic_t to refcount_t
  ipc: covert from atomic_t to refcount_t
  tools: convert from atomic_t to refcount_t
  block: convert from atomic_t to refcount_t
  drivers: net convert from atomic_t to refcount_t
  drivers: misc drivers convert from atomic_t to refcount_t
  drivers: infiniband convert from atomic_t to refcount_t

Peter Zijlstra (7):
  kref: Add KREF_INIT()
  kref: Add kref_read()
  kref: Kill kref_sub()
  kref: Use kref_get_unless_zero() more
  kref: Implement kref_put_lock()
  kref: Avoid more abuse
  kref: Implement using refcount_t

 arch/alpha/kernel/smp.c                            |   6 +-
 arch/arc/kernel/smp.c                              |   2 +-
 arch/arc/mm/tlb.c                                  |   2 +-
 arch/arm/kernel/smp.c                              |   2 +-
 arch/arm64/kernel/smp.c                            |   2 +-
 arch/blackfin/mach-common/smp.c                    |   4 +-
 arch/frv/mm/mmu-context.c                          |   2 +-
 arch/ia64/include/asm/tlbflush.h                   |   2 +-
 arch/ia64/kernel/smp.c                             |   2 +-
 arch/ia64/sn/kernel/sn2/sn2_smp.c                  |   4 +-
 arch/metag/kernel/smp.c                            |   2 +-
 arch/mips/kernel/process.c                         |   2 +-
 arch/mips/kernel/smp.c                             |   6 +-
 arch/parisc/include/asm/mmu_context.h              |   2 +-
 arch/powerpc/mm/hugetlbpage.c                      |   2 +-
 arch/powerpc/mm/icswx.c                            |   4 +-
 arch/powerpc/platforms/cell/spufs/file.c           |   2 +-
 arch/s390/include/asm/debug.h                      |   3 +-
 arch/s390/kernel/debug.c                           |   6 +-
 arch/sh/kernel/smp.c                               |   8 +-
 arch/sparc/kernel/mdesc.c                          |  17 +-
 arch/sparc/kernel/smp_64.c                         |   6 +-
 arch/sparc/mm/srmmu.c                              |   2 +-
 arch/um/kernel/tlb.c                               |   2 +-
 arch/x86/include/asm/amd_nb.h                      |   3 +-
 arch/x86/kernel/cpu/common.c                       |   4 +-
 arch/x86/kernel/cpu/mcheck/mce_amd.c               |   6 +-
 arch/x86/kernel/tboot.c                            |   4 +-
 arch/xtensa/kernel/smp.c                           |   2 +-
 block/bio.c                                        |   6 +-
 block/blk-cgroup.c                                 |   2 +-
 block/blk-ioc.c                                    |   4 +-
 block/blk-tag.c                                    |   8 +-
 block/bsg.c                                        |   9 +-
 block/cfq-iosched.c                                |   4 +-
 crypto/algif_aead.c                                |   2 +-
 drivers/atm/fore200e.c                             |  13 +-
 drivers/atm/he.c                                   |   2 +-
 drivers/atm/idt77252.c                             |   4 +-
 drivers/block/drbd/drbd_bitmap.c                   |   2 +-
 drivers/block/drbd/drbd_main.c                     |   7 +-
 drivers/block/drbd/drbd_req.c                      |  31 +--
 drivers/block/rbd.c                                |   8 +-
 drivers/block/virtio_blk.c                         |   2 +-
 drivers/block/xen-blkback/common.h                 |   7 +-
 drivers/block/xen-blkback/xenbus.c                 |   2 +-
 drivers/char/mspec.c                               |   9 +-
 drivers/connector/cn_queue.c                       |   4 +-
 drivers/connector/connector.c                      |   2 +-
 drivers/firewire/core-topology.c                   |   2 +-
 drivers/firewire/core.h                            |   8 +-
 drivers/firmware/efi/arm-runtime.c                 |   4 +-
 drivers/gpu/drm/amd/amdkfd/kfd_process.c           |   4 +-
 drivers/gpu/drm/drm_gem_cma_helper.c               |   2 +-
 drivers/gpu/drm/drm_info.c                         |   2 +-
 drivers/gpu/drm/drm_mode_object.c                  |   4 +-
 drivers/gpu/drm/etnaviv/etnaviv_gem.c              |   2 +-
 drivers/gpu/drm/i915/i915_gem_object.h             |   2 +-
 drivers/gpu/drm/i915/i915_gem_userptr.c            |   4 +-
 drivers/gpu/drm/msm/msm_gem.c                      |   3 +-
 drivers/gpu/drm/nouveau/nouveau_fence.c            |   2 +-
 drivers/gpu/drm/omapdrm/omap_gem.c                 |   2 +-
 drivers/gpu/drm/ttm/ttm_bo.c                       |  63 ++---
 drivers/gpu/drm/ttm/ttm_execbuf_util.c             |   4 +-
 drivers/gpu/drm/ttm/ttm_object.c                   |   2 +-
 drivers/infiniband/core/addr.c                     |   8 +-
 drivers/infiniband/core/cm.c                       |  26 +-
 drivers/infiniband/core/cma.c                      |  29 +--
 drivers/infiniband/core/cq.c                       |   4 +-
 drivers/infiniband/core/iwcm.c                     |  10 +-
 drivers/infiniband/core/iwcm.h                     |   4 +-
 drivers/infiniband/core/iwpm_util.c                |   8 +-
 drivers/infiniband/core/iwpm_util.h                |   3 +-
 drivers/infiniband/core/mad.c                      |  36 +--
 drivers/infiniband/core/mad_priv.h                 |   5 +-
 drivers/infiniband/core/mad_rmpp.c                 |  11 +-
 drivers/infiniband/core/multicast.c                |  31 +--
 drivers/infiniband/core/uverbs.h                   |   4 +-
 drivers/infiniband/core/uverbs_cmd.c               |  74 +++---
 drivers/infiniband/core/uverbs_main.c              |  14 +-
 drivers/infiniband/core/verbs.c                    | 102 ++++----
 drivers/infiniband/hw/cxgb3/iwch_cm.h              |   6 +-
 drivers/infiniband/hw/cxgb3/iwch_ev.c              |   8 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c        |  16 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.h        |   5 +-
 drivers/infiniband/hw/cxgb3/iwch_qp.c              |   6 +-
 drivers/infiniband/hw/cxgb4/cq.c                   |   6 +-
 drivers/infiniband/hw/cxgb4/ev.c                   |   8 +-
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h             |   9 +-
 drivers/infiniband/hw/cxgb4/qp.c                   |   2 +-
 drivers/infiniband/hw/hfi1/file_ops.c              |   2 +-
 drivers/infiniband/hw/hfi1/qp.c                    |   2 +-
 drivers/infiniband/hw/hfi1/user_sdma.c             |  13 +-
 drivers/infiniband/hw/hns/hns_roce_cq.c            |   8 +-
 drivers/infiniband/hw/hns/hns_roce_device.h        |   5 +-
 drivers/infiniband/hw/hns/hns_roce_qp.c            |  10 +-
 drivers/infiniband/hw/i40iw/i40iw.h                |   3 +-
 drivers/infiniband/hw/i40iw/i40iw_cm.c             |  12 +-
 drivers/infiniband/hw/i40iw/i40iw_main.c           |   2 +-
 drivers/infiniband/hw/i40iw/i40iw_puda.h           |   4 +-
 drivers/infiniband/hw/i40iw/i40iw_utils.c          |  12 +-
 drivers/infiniband/hw/i40iw/i40iw_verbs.c          |   2 +-
 drivers/infiniband/hw/i40iw/i40iw_verbs.h          |   4 +-
 drivers/infiniband/hw/mlx4/mcg.c                   |  39 +--
 drivers/infiniband/hw/mlx5/cq.c                    |   2 +-
 drivers/infiniband/hw/mlx5/main.c                  |  20 +-
 drivers/infiniband/hw/nes/nes.c                    |   8 +-
 drivers/infiniband/hw/nes/nes_cm.c                 |  32 +--
 drivers/infiniband/hw/nes/nes_cm.h                 |   6 +-
 drivers/infiniband/hw/nes/nes_hw.c                 |   8 +-
 drivers/infiniband/hw/nes/nes_hw.h                 |   4 +-
 drivers/infiniband/hw/nes/nes_mgt.c                |   6 +-
 drivers/infiniband/hw/nes/nes_utils.c              |   4 +-
 drivers/infiniband/hw/nes/nes_verbs.c              |  44 ++--
 drivers/infiniband/hw/nes/nes_verbs.h              |   6 +-
 drivers/infiniband/hw/qib/qib_keys.c               |   4 +-
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c       |   6 +-
 drivers/infiniband/hw/usnic/usnic_ib_verbs.c       |   4 +-
 drivers/infiniband/sw/rdmavt/mr.c                  |   6 +-
 drivers/infiniband/sw/rdmavt/qp.c                  |   4 +-
 drivers/infiniband/ulp/ipoib/ipoib.h               |   5 +-
 drivers/infiniband/ulp/ipoib/ipoib_main.c          |   8 +-
 drivers/iommu/intel-svm.c                          |   2 +-
 drivers/isdn/mISDN/socket.c                        |   2 +-
 drivers/md/bcache/alloc.c                          |   2 +-
 drivers/md/bcache/bcache.h                         |   9 +-
 drivers/md/bcache/btree.c                          |   8 +-
 drivers/md/bcache/super.c                          |   6 +-
 drivers/md/bcache/writeback.h                      |   2 +-
 drivers/md/dm-cache-metadata.c                     |   9 +-
 drivers/md/dm-core.h                               |   3 +-
 drivers/md/dm-table.c                              |   6 +-
 drivers/md/dm.c                                    |  19 +-
 drivers/md/dm.h                                    |   3 +-
 drivers/md/md.c                                    |   6 +-
 drivers/md/md.h                                    |   3 +-
 drivers/md/raid5-cache.c                           |   8 +-
 drivers/md/raid5.c                                 |  66 +++---
 drivers/md/raid5.h                                 |   3 +-
 drivers/media/pci/cx88/cx88-cards.c                |   2 +-
 drivers/media/pci/cx88/cx88-core.c                 |   4 +-
 drivers/media/pci/cx88/cx88.h                      |   3 +-
 drivers/media/usb/s2255/s2255drv.c                 |  21 +-
 drivers/media/usb/uvc/uvc_ctrl.c                   |   7 +-
 drivers/media/usb/uvc/uvc_driver.c                 |  12 +-
 drivers/media/usb/uvc/uvcvideo.h                   |   5 +-
 drivers/media/v4l2-core/videobuf2-dma-contig.c     |  11 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c         |  11 +-
 drivers/media/v4l2-core/videobuf2-memops.c         |   6 +-
 drivers/media/v4l2-core/videobuf2-vmalloc.c        |  11 +-
 drivers/misc/genwqe/card_dev.c                     |   2 +-
 drivers/misc/mei/debugfs.c                         |   2 +-
 drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c      |   8 +-
 drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h      |   4 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c        |   6 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h        |   4 +-
 drivers/net/ethernet/mellanox/mlx4/cq.c            |  12 +-
 drivers/net/ethernet/mellanox/mlx4/qp.c            |   8 +-
 drivers/net/ethernet/mellanox/mlx4/srq.c           |   8 +-
 drivers/net/ethernet/mellanox/mlx5/core/cq.c       |  16 +-
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  |  24 +-
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.h  |   3 +-
 drivers/net/ethernet/mellanox/mlx5/core/qp.c       |   6 +-
 drivers/net/ethernet/mellanox/mlx5/core/srq.c      |  10 +-
 drivers/net/ethernet/sun/niu.c                     |   6 +-
 drivers/net/ethernet/sun/niu.h                     |   4 +-
 drivers/net/hamradio/6pack.c                       |  12 +-
 drivers/net/macsec.c                               |  25 +-
 drivers/net/ppp/ppp_async.c                        |  10 +-
 drivers/net/ppp/ppp_generic.c                      |  17 +-
 drivers/net/ppp/ppp_synctty.c                      |  11 +-
 drivers/net/rionet.c                               |   2 +-
 drivers/net/vxlan.c                                |  10 +-
 drivers/net/wireless/intel/ipw2x00/libipw_rx.c     |   8 +-
 drivers/net/wireless/intel/ipw2x00/libipw_tx.c     |   4 +-
 .../net/wireless/intersil/hostap/hostap_80211_rx.c |   8 +-
 .../net/wireless/intersil/hostap/hostap_80211_tx.c |   4 +-
 drivers/net/wireless/intersil/hostap/hostap_hw.c   |  12 +-
 drivers/net/wireless/intersil/hostap/hostap_wlan.h |   3 +-
 .../net/wireless/intersil/orinoco/orinoco_usb.c    |  15 +-
 drivers/pci/host/pci-hyperv.c                      |   7 +-
 drivers/pci/hotplug/pnv_php.c                      |   2 +-
 drivers/pci/slot.c                                 |   2 +-
 drivers/s390/char/vmur.c                           |   8 +-
 drivers/s390/char/vmur.h                           |   4 +-
 drivers/s390/net/ctcm_main.c                       |  26 +-
 drivers/s390/net/lcs.c                             |  10 +-
 drivers/s390/net/lcs.h                             |   3 +-
 drivers/s390/net/netiucv.c                         |  10 +-
 drivers/s390/net/qeth_core.h                       |   3 +-
 drivers/s390/net/qeth_core_main.c                  |  14 +-
 drivers/scsi/bnx2fc/bnx2fc_io.c                    |   8 +-
 drivers/scsi/cxgbi/libcxgbi.h                      |   6 +-
 drivers/scsi/libfc/fc_exch.c                       |  10 +-
 drivers/scsi/libfc/fc_fcp.c                        |   6 +-
 drivers/scsi/libiscsi.c                            |   8 +-
 drivers/scsi/lpfc/lpfc_debugfs.c                   |   2 +-
 drivers/scsi/lpfc/lpfc_els.c                       |   2 +-
 drivers/scsi/lpfc/lpfc_hbadisc.c                   |  40 ++--
 drivers/scsi/lpfc/lpfc_init.c                      |   3 +-
 drivers/scsi/qedi/qedi_iscsi.c                     |   2 +-
 drivers/scsi/qla2xxx/tcm_qla2xxx.c                 |   4 +-
 drivers/staging/android/ion/ion.c                  |   2 +-
 drivers/staging/comedi/comedi_buf.c                |   2 +-
 drivers/staging/lustre/lustre/llite/llite_lib.c    |   2 +-
 drivers/staging/rtl8192e/rtllib_rx.c               |   8 +-
 drivers/staging/rtl8192e/rtllib_tx.c               |   4 +-
 .../staging/rtl8192u/ieee80211/ieee80211_crypt.c   |   2 +-
 .../staging/rtl8192u/ieee80211/ieee80211_crypt.h   |   3 +-
 drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c  |   8 +-
 drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c  |   4 +-
 drivers/staging/vme/devices/vme_user.c             |  10 +-
 drivers/target/target_core_iblock.c                |  12 +-
 drivers/target/target_core_iblock.h                |   3 +-
 drivers/target/target_core_pr.c                    |  10 +-
 drivers/target/tcm_fc/tfc_sess.c                   |   2 +-
 drivers/tty/serial/dz.c                            |  31 +--
 drivers/tty/serial/sb1250-duart.c                  |  18 +-
 drivers/usb/gadget/function/f_fs.c                 |  10 +-
 drivers/usb/gadget/function/u_fs.h                 |   3 +-
 drivers/usb/gadget/legacy/inode.c                  |  17 +-
 drivers/usb/mon/mon_main.c                         |   2 +-
 drivers/xen/gntdev.c                               |  11 +-
 fs/afs/cell.c                                      |  20 +-
 fs/afs/internal.h                                  |  18 +-
 fs/afs/proc.c                                      |   6 +-
 fs/afs/server.c                                    |  20 +-
 fs/afs/vlocation.c                                 |  16 +-
 fs/afs/volume.c                                    |   6 +-
 fs/btrfs/backref.c                                 |   2 +-
 fs/btrfs/compression.c                             |  18 +-
 fs/btrfs/ctree.c                                   |   2 +-
 fs/btrfs/ctree.h                                   |   7 +-
 fs/btrfs/delayed-inode.c                           |  46 ++--
 fs/btrfs/delayed-inode.h                           |   5 +-
 fs/btrfs/delayed-ref.c                             |   8 +-
 fs/btrfs/delayed-ref.h                             |   8 +-
 fs/btrfs/disk-io.c                                 |  14 +-
 fs/btrfs/disk-io.h                                 |   4 +-
 fs/btrfs/extent-tree.c                             |  28 +--
 fs/btrfs/extent_io.c                               |  91 ++++---
 fs/btrfs/extent_io.h                               |   9 +-
 fs/btrfs/extent_map.c                              |  10 +-
 fs/btrfs/extent_map.h                              |   3 +-
 fs/btrfs/free-space-cache.c                        |   4 +-
 fs/btrfs/ordered-data.c                            |  20 +-
 fs/btrfs/ordered-data.h                            |   2 +-
 fs/btrfs/raid56.c                                  |  19 +-
 fs/btrfs/scrub.c                                   |  42 ++--
 fs/btrfs/transaction.c                             |  20 +-
 fs/btrfs/transaction.h                             |   3 +-
 fs/btrfs/tree-log.c                                |   2 +-
 fs/btrfs/volumes.c                                 |  12 +-
 fs/btrfs/volumes.h                                 |   2 +-
 fs/cachefiles/bind.c                               |   2 +-
 fs/cachefiles/interface.c                          |  18 +-
 fs/cachefiles/internal.h                           |   3 +-
 fs/cachefiles/namei.c                              |   2 +-
 fs/cachefiles/rdwr.c                               |   2 +-
 fs/ceph/caps.c                                     |   4 +-
 fs/ceph/file.c                                     |   7 +-
 fs/ceph/mds_client.c                               |  20 +-
 fs/ceph/mds_client.h                               |   5 +-
 fs/ceph/snap.c                                     |   2 +-
 fs/ceph/super.h                                    |   5 +-
 fs/cifs/cifsfs.c                                   |   2 +-
 fs/cifs/cifsglob.h                                 |   5 +-
 fs/cifs/connect.c                                  |   4 +-
 fs/cifs/inode.c                                    |   2 +-
 fs/coredump.c                                      |   2 +-
 fs/devpts/inode.c                                  |   2 +-
 fs/exec.c                                          |   4 +-
 fs/exofs/sys.c                                     |   2 +-
 fs/f2fs/acl.c                                      |   2 +-
 fs/fscache/cache.c                                 |   8 +-
 fs/fscache/operation.c                             |  38 +--
 fs/fscache/page.c                                  |   2 +-
 fs/fuse/dev.c                                      |  10 +-
 fs/fuse/file.c                                     |   8 +-
 fs/fuse/fuse_i.h                                   |   9 +-
 fs/fuse/inode.c                                    |   6 +-
 fs/gfs2/super.c                                    |   2 +-
 fs/hfs/bnode.c                                     |  14 +-
 fs/hfs/btree.c                                     |   4 +-
 fs/hfs/btree.h                                     |   3 +-
 fs/hfs/inode.c                                     |   4 +-
 fs/hfsplus/bnode.c                                 |  14 +-
 fs/hfsplus/btree.c                                 |   4 +-
 fs/hfsplus/dir.c                                   |   4 +-
 fs/hfsplus/hfsplus_fs.h                            |   5 +-
 fs/hfsplus/inode.c                                 |  10 +-
 fs/hfsplus/super.c                                 |   2 +-
 fs/inode.c                                         |   3 +-
 fs/kernfs/dir.c                                    |  10 +-
 fs/kernfs/mount.c                                  |   2 +-
 fs/lockd/clntproc.c                                |  14 +-
 fs/lockd/host.c                                    |  16 +-
 fs/lockd/mon.c                                     |  14 +-
 fs/lockd/svcproc.c                                 |   2 +-
 fs/mbcache.c                                       |  16 +-
 fs/mount.h                                         |   5 +-
 fs/namespace.c                                     |   8 +-
 fs/ncpfs/sock.c                                    |   9 +-
 fs/nfs/cache_lib.c                                 |   6 +-
 fs/nfs/cache_lib.h                                 |   2 +-
 fs/nfs/client.c                                    |  12 +-
 fs/nfs/dir.c                                       |   8 +-
 fs/nfs/filelayout/filelayout.c                     |  12 +-
 fs/nfs/flexfilelayout/flexfilelayout.c             |  20 +-
 fs/nfs/flexfilelayout/flexfilelayout.h             |   3 +-
 fs/nfs/inode.c                                     |  12 +-
 fs/nfs/nfs4_fs.h                                   |   7 +-
 fs/nfs/nfs4client.c                                |  16 +-
 fs/nfs/nfs4proc.c                                  |  26 +-
 fs/nfs/nfs4state.c                                 |  36 +--
 fs/nfs/pnfs.c                                      |  32 +--
 fs/nfs/pnfs.h                                      |   9 +-
 fs/nfs/pnfs_nfs.c                                  |  10 +-
 fs/nfs/super.c                                     |   4 +-
 fs/nfsd/nfs4layouts.c                              |   4 +-
 fs/nfsd/nfs4state.c                                |  72 +++---
 fs/nfsd/state.h                                    |  15 +-
 fs/nilfs2/the_nilfs.c                              |   8 +-
 fs/nilfs2/the_nilfs.h                              |   5 +-
 fs/notify/group.c                                  |   6 +-
 fs/notify/inotify/inotify_user.c                   |   4 +-
 fs/notify/mark.c                                   |   6 +-
 fs/ntfs/aops.c                                     |   2 +-
 fs/ntfs/inode.c                                    |   6 +-
 fs/ntfs/inode.h                                    |   4 +-
 fs/ntfs/mft.c                                      |  36 +--
 fs/ocfs2/cluster/netdebug.c                        |   2 +-
 fs/ocfs2/cluster/tcp.c                             |   2 +-
 fs/ocfs2/dlm/dlmdebug.c                            |  12 +-
 fs/ocfs2/dlm/dlmdomain.c                           |   2 +-
 fs/ocfs2/dlm/dlmmaster.c                           |   8 +-
 fs/ocfs2/dlm/dlmunlock.c                           |   2 +-
 fs/ocfs2/filecheck.c                               |  17 +-
 fs/posix_acl.c                                     |   6 +-
 fs/proc/base.c                                     |  10 +-
 fs/proc/generic.c                                  |   4 +-
 fs/proc/internal.h                                 |   5 +-
 fs/proc/root.c                                     |   2 +-
 fs/proc/task_mmu.c                                 |   4 +-
 fs/proc/task_nommu.c                               |   2 +-
 fs/super.c                                         |  10 +-
 fs/userfaultfd.c                                   |  11 +-
 fs/xfs/xfs_bmap_item.c                             |   4 +-
 fs/xfs/xfs_bmap_item.h                             |   4 +-
 fs/xfs/xfs_buf.c                                   |  34 +--
 fs/xfs/xfs_buf.h                                   |   7 +-
 fs/xfs/xfs_buf_item.c                              |  16 +-
 fs/xfs/xfs_buf_item.h                              |   4 +-
 fs/xfs/xfs_extfree_item.c                          |   4 +-
 fs/xfs/xfs_extfree_item.h                          |   4 +-
 fs/xfs/xfs_inode.h                                 |   2 +-
 fs/xfs/xfs_log.c                                   |  37 +--
 fs/xfs/xfs_log_priv.h                              |   6 +-
 fs/xfs/xfs_refcount_item.c                         |   4 +-
 fs/xfs/xfs_refcount_item.h                         |   4 +-
 fs/xfs/xfs_rmap_item.c                             |   4 +-
 fs/xfs/xfs_rmap_item.h                             |   4 +-
 fs/xfs/xfs_trace.h                                 |  10 +-
 fs/xfs/xfs_trans_buf.c                             |  32 +--
 include/drm/drm_framebuffer.h                      |   2 +-
 include/drm/ttm/ttm_bo_api.h                       |  15 +-
 include/drm/ttm/ttm_bo_driver.h                    |   4 +-
 include/linux/atmdev.h                             |   9 +-
 include/linux/backing-dev-defs.h                   |   3 +-
 include/linux/backing-dev.h                        |   4 +-
 include/linux/bio.h                                |   4 +-
 include/linux/blk-cgroup.h                         |  11 +-
 include/linux/blk_types.h                          |   3 +-
 include/linux/blkdev.h                             |   3 +-
 include/linux/ceph/libceph.h                       |   3 +-
 include/linux/ceph/osd_client.h                    |   3 +-
 include/linux/ceph/pagelist.h                      |   6 +-
 include/linux/cgroup-defs.h                        |   3 +-
 include/linux/cgroup.h                             |   7 +-
 include/linux/connector.h                          |   4 +-
 include/linux/cred.h                               |  13 +-
 include/linux/filter.h                             |   3 +-
 include/linux/fs.h                                 |   3 +-
 include/linux/fscache-cache.h                      |   7 +-
 include/linux/fsnotify_backend.h                   |   5 +-
 include/linux/igmp.h                               |   3 +-
 include/linux/inetdevice.h                         |  11 +-
 include/linux/init_task.h                          |   7 +-
 include/linux/iocontext.h                          |   7 +-
 include/linux/ipc_namespace.h                      |   5 +-
 include/linux/kernfs.h                             |   3 +-
 include/linux/key.h                                |   5 +-
 include/linux/kref.h                               |  73 +++---
 include/linux/kvm_host.h                           |   3 +-
 include/linux/lockd/lockd.h                        |   9 +-
 include/linux/mbcache.h                            |   6 +-
 include/linux/mlx4/device.h                        |   8 +-
 include/linux/mlx5/cq.h                            |   4 +-
 include/linux/mlx5/driver.h                        |   5 +-
 include/linux/mm_types.h                           |   5 +-
 include/linux/netpoll.h                            |   3 +-
 include/linux/nfs_fs.h                             |   3 +-
 include/linux/nfs_fs_sb.h                          |   5 +-
 include/linux/nsproxy.h                            |   6 +-
 include/linux/perf_event.h                         |   3 +-
 include/linux/posix_acl.h                          |   7 +-
 include/linux/refcount.h                           | 262 +++++++++++++++++++++
 include/linux/rmap.h                               |   7 +-
 include/linux/sched.h                              |  25 +-
 include/linux/skbuff.h                             |  23 +-
 include/linux/sunrpc/auth.h                        |   8 +-
 include/linux/sunrpc/auth_gss.h                    |   3 +-
 include/linux/sunrpc/cache.h                       |   2 +-
 include/media/videobuf2-memops.h                   |   3 +-
 include/net/addrconf.h                             |  14 +-
 include/net/af_unix.h                              |   3 +-
 include/net/arp.h                                  |   2 +-
 include/net/ax25.h                                 |  20 +-
 include/net/bluetooth/hci_core.h                   |  14 +-
 include/net/bluetooth/rfcomm.h                     |   8 +-
 include/net/calipso.h                              |   4 +-
 include/net/cipso_ipv4.h                           |   3 +-
 include/net/dn_fib.h                               |   5 +-
 include/net/fib_rules.h                            |   7 +-
 include/net/if_inet6.h                             |   9 +-
 include/net/inet_frag.h                            |   4 +-
 include/net/inet_hashtables.h                      |   4 +-
 include/net/inetpeer.h                             |   4 +-
 include/net/ip_fib.h                               |   7 +-
 include/net/ip_vs.h                                |  24 +-
 include/net/ipv6.h                                 |   7 +-
 include/net/ipx.h                                  |  13 +-
 include/net/lapb.h                                 |   3 +-
 include/net/lib80211.h                             |   2 +-
 include/net/llc.h                                  |   6 +-
 include/net/lwtunnel.h                             |   7 +-
 include/net/ndisc.h                                |   2 +-
 include/net/neighbour.h                            |  15 +-
 include/net/net_namespace.h                        |   3 +-
 include/net/netfilter/br_netfilter.h               |   2 +-
 include/net/netfilter/nf_conntrack_expect.h        |   4 +-
 include/net/netfilter/nf_conntrack_timeout.h       |   3 +-
 include/net/netlabel.h                             |   8 +-
 include/net/netrom.h                               |  13 +-
 include/net/request_sock.h                         |   9 +-
 include/net/sch_generic.h                          |   3 +-
 include/net/sctp/auth.h                            |   5 +-
 include/net/sctp/structs.h                         |   8 +-
 include/net/sock.h                                 |  25 +-
 include/net/vxlan.h                                |   2 +-
 include/net/x25.h                                  |  15 +-
 include/net/xfrm.h                                 |  21 +-
 include/rdma/ib_addr.h                             |   3 +-
 include/rdma/ib_verbs.h                            |  15 +-
 include/rdma/rdmavt_mr.h                           |   6 +-
 include/rdma/rdmavt_qp.h                           |   6 +-
 include/scsi/libfc.h                               |   5 +-
 include/scsi/libiscsi.h                            |   3 +-
 include/trace/events/bcache.h                      |   2 +-
 include/trace/events/btrfs.h                       |   6 +-
 init/version.c                                     |   4 +-
 ipc/msgutil.c                                      |   2 +-
 ipc/namespace.c                                    |   4 +-
 ipc/sem.c                                          |   8 +-
 ipc/util.c                                         |   6 +-
 ipc/util.h                                         |   3 +-
 kernel/audit_tree.c                                |  10 +-
 kernel/audit_watch.c                               |   8 +-
 kernel/cgroup.c                                    |  23 +-
 kernel/cred.c                                      |  46 ++--
 kernel/events/core.c                               |  16 +-
 kernel/events/internal.h                           |   5 +-
 kernel/events/ring_buffer.c                        |   8 +-
 kernel/events/uprobes.c                            |  13 +-
 kernel/exit.c                                      |   4 +-
 kernel/fork.c                                      |  40 ++--
 kernel/futex.c                                     |  17 +-
 kernel/groups.c                                    |   2 +-
 kernel/kcov.c                                      |   9 +-
 kernel/nsproxy.c                                   |   6 +-
 kernel/pid.c                                       |   4 +-
 kernel/sched/core.c                                |   7 +-
 kernel/sched/fair.c                                |   8 +-
 kernel/user.c                                      |   8 +-
 lib/is_single_threaded.c                           |   2 +-
 mm/backing-dev.c                                   |  11 +-
 mm/debug.c                                         |   4 +-
 mm/huge_memory.c                                   |  16 +-
 mm/init-mm.c                                       |   4 +-
 mm/khugepaged.c                                    |   4 +-
 mm/kmemleak.c                                      |  16 +-
 mm/ksm.c                                           |   4 +-
 mm/memory.c                                        |   2 +-
 mm/mmu_context.c                                   |   2 +-
 mm/mmu_notifier.c                                  |  12 +-
 mm/mprotect.c                                      |   2 +-
 mm/oom_kill.c                                      |   6 +-
 mm/rmap.c                                          |  14 +-
 mm/swapfile.c                                      |  14 +-
 mm/vmacache.c                                      |   2 +-
 mm/zpool.c                                         |   4 +-
 net/atm/br2684.c                                   |   2 +-
 net/atm/clip.c                                     |   8 +-
 net/atm/common.c                                   |  10 +-
 net/atm/lec.c                                      |  11 +-
 net/atm/lec_arpc.h                                 |   2 +-
 net/atm/mpc.c                                      |   4 +-
 net/atm/mpoa_caches.c                              |  26 +-
 net/atm/mpoa_caches.h                              |   5 +-
 net/atm/pppoatm.c                                  |   2 +-
 net/atm/proc.c                                     |   4 +-
 net/atm/raw.c                                      |   2 +-
 net/atm/resources.c                                |   2 +-
 net/atm/signaling.c                                |   2 +-
 net/ax25/af_ax25.c                                 |   2 +-
 net/ax25/ax25_route.c                              |   2 +-
 net/ax25/ax25_uid.c                                |   2 +-
 net/bluetooth/6lowpan.c                            |   2 +-
 net/bluetooth/a2mp.c                               |   4 +-
 net/bluetooth/af_bluetooth.c                       |   2 +-
 net/bluetooth/amp.c                                |   4 +-
 net/bluetooth/hci_conn.c                           |   4 +-
 net/bluetooth/l2cap_core.c                         |   4 +-
 net/bluetooth/rfcomm/core.c                        |   4 +-
 net/bluetooth/rfcomm/sock.c                        |   2 +-
 net/bridge/br_netfilter_hooks.c                    |   4 +-
 net/bridge/br_private.h                            |   3 +-
 net/bridge/br_vlan.c                               |   8 +-
 net/caif/caif_socket.c                             |   2 +-
 net/ceph/messenger.c                               |   4 +-
 net/ceph/osd_client.c                              |  26 +-
 net/ceph/pagelist.c                                |   2 +-
 net/ceph/snapshot.c                                |   6 +-
 net/core/datagram.c                                |  10 +-
 net/core/dev.c                                     |  10 +-
 net/core/dst.c                                     |   7 +-
 net/core/fib_rules.c                               |   4 +-
 net/core/filter.c                                  |   6 +-
 net/core/neighbour.c                               |  22 +-
 net/core/net-sysfs.c                               |   2 +-
 net/core/net_namespace.c                           |   4 +-
 net/core/netpoll.c                                 |  10 +-
 net/core/pktgen.c                                  |  16 +-
 net/core/rtnetlink.c                               |   2 +-
 net/core/skbuff.c                                  |  34 +--
 net/core/sock.c                                    |  30 +--
 net/dccp/ipv6.c                                    |   2 +-
 net/decnet/dn_fib.c                                |   6 +-
 net/decnet/dn_neigh.c                              |   2 +-
 net/ipv4/af_inet.c                                 |   2 +-
 net/ipv4/cipso_ipv4.c                              |  16 +-
 net/ipv4/devinet.c                                 |   2 +-
 net/ipv4/fib_semantics.c                           |   2 +-
 net/ipv4/fib_trie.c                                |   2 +-
 net/ipv4/igmp.c                                    |  10 +-
 net/ipv4/inet_connection_sock.c                    |   2 +-
 net/ipv4/inet_fragment.c                           |  14 +-
 net/ipv4/inet_hashtables.c                         |   4 +-
 net/ipv4/inet_timewait_sock.c                      |   8 +-
 net/ipv4/inetpeer.c                                |  18 +-
 net/ipv4/ip_fragment.c                             |   2 +-
 net/ipv4/ip_output.c                               |   6 +-
 net/ipv4/netfilter/ipt_CLUSTERIP.c                 |  19 +-
 net/ipv4/ping.c                                    |   4 +-
 net/ipv4/raw.c                                     |   2 +-
 net/ipv4/syncookies.c                              |   2 +-
 net/ipv4/tcp.c                                     |   4 +-
 net/ipv4/tcp_fastopen.c                            |   2 +-
 net/ipv4/tcp_ipv4.c                                |   4 +-
 net/ipv4/tcp_offload.c                             |   2 +-
 net/ipv4/tcp_output.c                              |  13 +-
 net/ipv4/udp.c                                     |   6 +-
 net/ipv4/udp_diag.c                                |   4 +-
 net/ipv6/addrconf.c                                |   4 +-
 net/ipv6/addrlabel.c                               |   9 +-
 net/ipv6/anycast.c                                 |   6 +-
 net/ipv6/calipso.c                                 |  16 +-
 net/ipv6/datagram.c                                |   2 +-
 net/ipv6/exthdrs.c                                 |   4 +-
 net/ipv6/inet6_hashtables.c                        |   4 +-
 net/ipv6/ip6_output.c                              |   4 +-
 net/ipv6/ipv6_sockglue.c                           |   2 +-
 net/ipv6/mcast.c                                   |  18 +-
 net/ipv6/syncookies.c                              |   2 +-
 net/ipv6/tcp_ipv6.c                                |   6 +-
 net/ipv6/udp.c                                     |   2 +-
 net/ipv6/xfrm6_input.c                             |   2 +-
 net/ipv6/xfrm6_tunnel.c                            |   8 +-
 net/ipx/af_ipx.c                                   |   6 +-
 net/ipx/ipx_proc.c                                 |   2 +-
 net/ipx/ipx_route.c                                |   2 +-
 net/kcm/kcmproc.c                                  |   2 +-
 net/key/af_key.c                                   |  10 +-
 net/l2tp/l2tp_core.c                               |  12 +-
 net/l2tp/l2tp_core.h                               |  13 +-
 net/l2tp/l2tp_debugfs.c                            |   6 +-
 net/l2tp/l2tp_ppp.c                                |   2 +-
 net/lapb/lapb_iface.c                              |   6 +-
 net/llc/llc_conn.c                                 |   8 +-
 net/llc/llc_core.c                                 |   2 +-
 net/llc/llc_sap.c                                  |   2 +-
 net/netfilter/ipset/ip_set_hash_gen.h              |  19 +-
 net/netfilter/ipvs/ip_vs_conn.c                    |  24 +-
 net/netfilter/ipvs/ip_vs_core.c                    |   4 +-
 net/netfilter/ipvs/ip_vs_ctl.c                     |  24 +-
 net/netfilter/ipvs/ip_vs_dh.c                      |   2 +-
 net/netfilter/ipvs/ip_vs_fo.c                      |   2 +-
 net/netfilter/ipvs/ip_vs_lblc.c                    |   4 +-
 net/netfilter/ipvs/ip_vs_lblcr.c                   |   8 +-
 net/netfilter/ipvs/ip_vs_lc.c                      |   2 +-
 net/netfilter/ipvs/ip_vs_nq.c                      |   4 +-
 net/netfilter/ipvs/ip_vs_ovf.c                     |   2 +-
 net/netfilter/ipvs/ip_vs_pe_sip.c                  |   2 +-
 net/netfilter/ipvs/ip_vs_proto_sctp.c              |   2 +-
 net/netfilter/ipvs/ip_vs_proto_tcp.c               |   2 +-
 net/netfilter/ipvs/ip_vs_rr.c                      |   4 +-
 net/netfilter/ipvs/ip_vs_sed.c                     |   4 +-
 net/netfilter/ipvs/ip_vs_sh.c                      |   2 +-
 net/netfilter/ipvs/ip_vs_wlc.c                     |   4 +-
 net/netfilter/ipvs/ip_vs_wrr.c                     |   4 +-
 net/netfilter/nf_conntrack_core.c                  |  26 +-
 net/netfilter/nf_conntrack_expect.c                |  12 +-
 net/netfilter/nf_conntrack_netlink.c               |  10 +-
 net/netfilter/nf_conntrack_standalone.c            |   4 +-
 net/netfilter/nfnetlink_acct.c                     |  15 +-
 net/netfilter/nfnetlink_cttimeout.c                |  12 +-
 net/netfilter/nfnetlink_log.c                      |  14 +-
 net/netfilter/nft_ct.c                             |   2 +-
 net/netfilter/xt_CT.c                              |   2 +-
 net/netfilter/xt_TPROXY.c                          |   4 +-
 net/netlink/af_netlink.c                           |  14 +-
 net/netrom/nr_route.c                              |   6 +-
 net/packet/af_packet.c                             |  14 +-
 net/packet/internal.h                              |   4 +-
 net/phonet/socket.c                                |   4 +-
 net/rds/ib.c                                       |  12 +-
 net/rds/ib.h                                       |   2 +-
 net/rds/ib_rdma.c                                  |   4 +-
 net/rds/message.c                                  |  12 +-
 net/rds/rdma.c                                     |  10 +-
 net/rds/rds.h                                      |   9 +-
 net/rds/recv.c                                     |  12 +-
 net/rds/tcp_send.c                                 |   2 +-
 net/rxrpc/af_rxrpc.c                               |   6 +-
 net/rxrpc/skbuff.c                                 |  12 +-
 net/sched/em_meta.c                                |   2 +-
 net/sched/sch_api.c                                |   8 +-
 net/sched/sch_atm.c                                |   2 +-
 net/sched/sch_generic.c                            |   8 +-
 net/sctp/associola.c                               |   6 +-
 net/sctp/auth.c                                    |   4 +-
 net/sctp/chunk.c                                   |   6 +-
 net/sctp/endpointola.c                             |   6 +-
 net/sctp/output.c                                  |   2 +-
 net/sctp/outqueue.c                                |   2 +-
 net/sctp/proc.c                                    |   2 +-
 net/sctp/sm_make_chunk.c                           |   6 +-
 net/sctp/socket.c                                  |   6 +-
 net/sctp/transport.c                               |   8 +-
 net/sunrpc/auth.c                                  |  12 +-
 net/sunrpc/auth_gss/auth_gss.c                     |  29 +--
 net/sunrpc/auth_null.c                             |   2 +-
 net/sunrpc/cache.c                                 |   2 +-
 net/sunrpc/svc_xprt.c                              |   6 +-
 net/sunrpc/svcauth.c                               |  15 +-
 net/sunrpc/xprtrdma/svc_rdma_transport.c           |   4 +-
 net/tipc/socket.c                                  |   2 +-
 net/unix/af_unix.c                                 |  16 +-
 net/wireless/lib80211.c                            |   2 +-
 net/x25/x25_link.c                                 |   2 +-
 net/x25/x25_route.c                                |   2 +-
 net/xfrm/xfrm_input.c                              |   4 +-
 net/xfrm/xfrm_policy.c                             |   4 +-
 net/xfrm/xfrm_state.c                              |   4 +-
 security/apparmor/include/apparmor.h               |   6 -
 security/apparmor/include/policy.h                 |   4 +-
 security/keys/gc.c                                 |   2 +-
 security/keys/internal.h                           |   3 +-
 security/keys/key.c                                |  12 +-
 security/keys/keyring.c                            |   8 +-
 security/keys/proc.c                               |   4 +-
 security/keys/process_keys.c                       |   2 +-
 security/keys/request_key_auth.c                   |   2 +-
 security/selinux/hooks.c                           |   9 +-
 security/selinux/include/xfrm.h                    |   5 +-
 security/selinux/xfrm.c                            |  11 +-
 security/tomoyo/common.c                           |  11 +-
 sound/core/seq/seq_clientmgr.c                     |   2 +-
 sound/core/seq/seq_ports.c                         |   8 +-
 sound/core/seq/seq_ports.h                         |   3 +-
 sound/usb/card.c                                   |  10 +-
 sound/usb/usbaudio.h                               |   4 +-
 tools/perf/util/cgroup.c                           |   6 +-
 tools/perf/util/cgroup.h                           |   4 +-
 tools/perf/util/comm.c                             |  10 +-
 tools/perf/util/cpumap.c                           |  16 +-
 tools/perf/util/cpumap.h                           |   4 +-
 tools/perf/util/dso.c                              |   6 +-
 tools/perf/util/dso.h                              |   4 +-
 tools/perf/util/evlist.c                           |  18 +-
 tools/perf/util/evlist.h                           |   4 +-
 tools/perf/util/map.c                              |  10 +-
 tools/perf/util/map.h                              |  10 +-
 tools/perf/util/thread.c                           |   6 +-
 tools/perf/util/thread.h                           |   4 +-
 tools/perf/util/thread_map.c                       |  20 +-
 tools/perf/util/thread_map.h                       |   4 +-
 virt/kvm/async_pf.c                                |   2 +-
 virt/kvm/kvm_main.c                                |  10 +-
 709 files changed, 3279 insertions(+), 2898 deletions(-)
 create mode 100644 include/linux/refcount.h

-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 01/18] kref: Add KREF_INIT()
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 02/18] kref: Add kref_read() Elena Reshetova
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh

From: Peter Zijlstra <peterz@infradead.org>

Since we need to change the implementation, stop exposing internals.

Provide KREF_INIT() to allow static initialization of struct kref.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/block/drbd/drbd_bitmap.c | 2 +-
 fs/fuse/fuse_i.h                 | 2 +-
 include/linux/kref.h             | 2 ++
 init/version.c                   | 4 +---
 kernel/pid.c                     | 4 +---
 5 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index ab62b81..dece26f 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -1070,7 +1070,7 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned
 		.done = 0,
 		.flags = flags,
 		.error = 0,
-		.kref = { ATOMIC_INIT(2) },
+		.kref = KREF_INIT(2),
 	};
 
 	if (!get_ldev_if_state(device, D_ATTACHING)) {  /* put is in drbd_bm_aio_ctx_destroy() */
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 9130794..052f8d3 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -256,7 +256,7 @@ struct fuse_io_priv {
 
 #define FUSE_IO_PRIV_SYNC(f) \
 {					\
-	.refcnt = { ATOMIC_INIT(1) },	\
+	.refcnt = KREF_INIT(1),		\
 	.async = 0,			\
 	.file = f,			\
 }
diff --git a/include/linux/kref.h b/include/linux/kref.h
index e15828f..9af255a 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -24,6 +24,8 @@ struct kref {
 	atomic_t refcount;
 };
 
+#define KREF_INIT(n)	{ .refcount = ATOMIC_INIT(n), }
+
 /**
  * kref_init - initialize object.
  * @kref: object in question.
diff --git a/init/version.c b/init/version.c
index fe41a63..5606341 100644
--- a/init/version.c
+++ b/init/version.c
@@ -23,9 +23,7 @@ int version_string(LINUX_VERSION_CODE);
 #endif
 
 struct uts_namespace init_uts_ns = {
-	.kref = {
-		.refcount	= ATOMIC_INIT(2),
-	},
+	.kref = KREF_INIT(2),
 	.name = {
 		.sysname	= UTS_SYSNAME,
 		.nodename	= UTS_NODENAME,
diff --git a/kernel/pid.c b/kernel/pid.c
index f66162f..0291804 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -68,9 +68,7 @@ static inline int mk_pid(struct pid_namespace *pid_ns,
  * the scheme scales to up to 4 million PIDs, runtime.
  */
 struct pid_namespace init_pid_ns = {
-	.kref = {
-		.refcount       = ATOMIC_INIT(2),
-	},
+	.kref = KREF_INIT(2),
 	.pidmap = {
 		[ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL }
 	},
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 02/18] kref: Add kref_read()
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 01/18] kref: Add KREF_INIT() Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 03/18] kref: Kill kref_sub() Elena Reshetova
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh

From: Peter Zijlstra <peterz@infradead.org>

Since we need to change the implementation, stop exposing internals.

Provide kref_read() to read the current reference count; typically used
for debug messages.

Kills two anti-patterns:

	atomic_read(&kref->refcount)
	kref->refcount.counter

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/block/drbd/drbd_req.c                |  2 +-
 drivers/block/rbd.c                          |  8 +++---
 drivers/block/virtio_blk.c                   |  2 +-
 drivers/gpu/drm/drm_gem_cma_helper.c         |  2 +-
 drivers/gpu/drm/drm_info.c                   |  2 +-
 drivers/gpu/drm/drm_mode_object.c            |  4 +--
 drivers/gpu/drm/etnaviv/etnaviv_gem.c        |  2 +-
 drivers/gpu/drm/msm/msm_gem.c                |  3 +--
 drivers/gpu/drm/nouveau/nouveau_fence.c      |  2 +-
 drivers/gpu/drm/omapdrm/omap_gem.c           |  2 +-
 drivers/gpu/drm/ttm/ttm_bo.c                 |  4 +--
 drivers/gpu/drm/ttm/ttm_object.c             |  2 +-
 drivers/infiniband/hw/cxgb3/iwch_cm.h        |  6 ++---
 drivers/infiniband/hw/cxgb3/iwch_qp.c        |  2 +-
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h       |  6 ++---
 drivers/infiniband/hw/cxgb4/qp.c             |  2 +-
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c |  6 ++---
 drivers/infiniband/hw/usnic/usnic_ib_verbs.c |  4 +--
 drivers/misc/genwqe/card_dev.c               |  2 +-
 drivers/misc/mei/debugfs.c                   |  2 +-
 drivers/pci/hotplug/pnv_php.c                |  2 +-
 drivers/pci/slot.c                           |  2 +-
 drivers/scsi/bnx2fc/bnx2fc_io.c              |  8 +++---
 drivers/scsi/cxgbi/libcxgbi.h                |  4 +--
 drivers/scsi/lpfc/lpfc_debugfs.c             |  2 +-
 drivers/scsi/lpfc/lpfc_els.c                 |  2 +-
 drivers/scsi/lpfc/lpfc_hbadisc.c             | 40 ++++++++++++++--------------
 drivers/scsi/lpfc/lpfc_init.c                |  3 +--
 drivers/scsi/qla2xxx/tcm_qla2xxx.c           |  4 +--
 drivers/staging/android/ion/ion.c            |  2 +-
 drivers/staging/comedi/comedi_buf.c          |  2 +-
 drivers/target/target_core_pr.c              | 10 +++----
 drivers/target/tcm_fc/tfc_sess.c             |  2 +-
 drivers/usb/gadget/function/f_fs.c           |  2 +-
 fs/exofs/sys.c                               |  2 +-
 fs/ocfs2/cluster/netdebug.c                  |  2 +-
 fs/ocfs2/cluster/tcp.c                       |  2 +-
 fs/ocfs2/dlm/dlmdebug.c                      | 12 ++++-----
 fs/ocfs2/dlm/dlmdomain.c                     |  2 +-
 fs/ocfs2/dlm/dlmmaster.c                     |  8 +++---
 fs/ocfs2/dlm/dlmunlock.c                     |  2 +-
 include/drm/drm_framebuffer.h                |  2 +-
 include/drm/ttm/ttm_bo_driver.h              |  4 +--
 include/linux/kref.h                         |  5 ++++
 include/linux/sunrpc/cache.h                 |  2 +-
 include/net/bluetooth/hci_core.h             |  4 +--
 net/bluetooth/6lowpan.c                      |  2 +-
 net/bluetooth/amp.c                          |  4 +--
 net/bluetooth/l2cap_core.c                   |  4 +--
 net/ceph/messenger.c                         |  4 +--
 net/ceph/osd_client.c                        | 10 +++----
 net/sunrpc/cache.c                           |  2 +-
 net/sunrpc/svc_xprt.c                        |  6 ++---
 net/sunrpc/xprtrdma/svc_rdma_transport.c     |  4 +--
 54 files changed, 118 insertions(+), 115 deletions(-)

diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index de279fe..74306c0 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -520,7 +520,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		/* Completion does it's own kref_put.  If we are going to
 		 * kref_sub below, we need req to be still around then. */
 		int at_least = k_put + !!c_put;
-		int refcount = atomic_read(&req->kref.refcount);
+		int refcount = kref_read(&req->kref);
 		if (refcount < at_least)
 			drbd_err(device,
 				"mod_rq_state: Logic BUG: %x -> %x: refcount = %d, should be >= %d\n",
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 36d2b9f..436baa6 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1535,7 +1535,7 @@ static bool obj_request_overlaps_parent(struct rbd_obj_request *obj_request)
 static void rbd_obj_request_get(struct rbd_obj_request *obj_request)
 {
 	dout("%s: obj %p (was %d)\n", __func__, obj_request,
-		atomic_read(&obj_request->kref.refcount));
+		kref_read(&obj_request->kref));
 	kref_get(&obj_request->kref);
 }
 
@@ -1544,14 +1544,14 @@ static void rbd_obj_request_put(struct rbd_obj_request *obj_request)
 {
 	rbd_assert(obj_request != NULL);
 	dout("%s: obj %p (was %d)\n", __func__, obj_request,
-		atomic_read(&obj_request->kref.refcount));
+		kref_read(&obj_request->kref));
 	kref_put(&obj_request->kref, rbd_obj_request_destroy);
 }
 
 static void rbd_img_request_get(struct rbd_img_request *img_request)
 {
 	dout("%s: img %p (was %d)\n", __func__, img_request,
-	     atomic_read(&img_request->kref.refcount));
+	     kref_read(&img_request->kref));
 	kref_get(&img_request->kref);
 }
 
@@ -1562,7 +1562,7 @@ static void rbd_img_request_put(struct rbd_img_request *img_request)
 {
 	rbd_assert(img_request != NULL);
 	dout("%s: img %p (was %d)\n", __func__, img_request,
-		atomic_read(&img_request->kref.refcount));
+		kref_read(&img_request->kref));
 	if (img_request_child_test(img_request))
 		kref_put(&img_request->kref, rbd_parent_request_destroy);
 	else
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 5545a67..79a346c 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -767,7 +767,7 @@ static void virtblk_remove(struct virtio_device *vdev)
 	/* Stop all the virtqueues. */
 	vdev->config->reset(vdev);
 
-	refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
+	refc = kref_read(&disk_to_dev(vblk->disk)->kobj.kref);
 	put_disk(vblk->disk);
 	vdev->config->del_vqs(vdev);
 	kfree(vblk->vqs);
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index 1d6c335..33cd516 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -376,7 +376,7 @@ void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj,
 	off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%2d (%2d) %08llx %pad %p %zu",
-			obj->name, obj->refcount.refcount.counter,
+			obj->name, kref_read(&obj->refcount),
 			off, &cma_obj->paddr, cma_obj->vaddr, obj->size);
 
 	seq_printf(m, "\n");
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index ffb2ab3..6b68e90 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -118,7 +118,7 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data)
 	seq_printf(m, "%6d %8zd %7d %8d\n",
 		   obj->name, obj->size,
 		   obj->handle_count,
-		   atomic_read(&obj->refcount.refcount));
+		   kref_read(&obj->refcount));
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index 9f17085..c6885a4 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -159,7 +159,7 @@ EXPORT_SYMBOL(drm_mode_object_find);
 void drm_mode_object_unreference(struct drm_mode_object *obj)
 {
 	if (obj->free_cb) {
-		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
+		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
 		kref_put(&obj->refcount, obj->free_cb);
 	}
 }
@@ -176,7 +176,7 @@ EXPORT_SYMBOL(drm_mode_object_unreference);
 void drm_mode_object_reference(struct drm_mode_object *obj)
 {
 	if (obj->free_cb) {
-		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
+		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
 		kref_get(&obj->refcount);
 	}
 }
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 114dddb..aa6e35d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -486,7 +486,7 @@ static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 
 	seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
 			etnaviv_obj->flags, is_active(etnaviv_obj) ? 'A' : 'I',
-			obj->name, obj->refcount.refcount.counter,
+			obj->name, kref_read(&obj->refcount),
 			off, etnaviv_obj->vaddr, obj->size);
 
 	rcu_read_lock();
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index d8bc59c..1228b1e 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -640,14 +640,13 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 
 	seq_printf(m, "%08x: %c %2d (%2d) %08llx %p\t",
 			msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
-			obj->name, obj->refcount.refcount.counter,
+			obj->name, kref_read(&obj->refcount),
 			off, msm_obj->vaddr);
 
 	for (id = 0; id < priv->num_aspaces; id++)
 		seq_printf(m, " %08llx", msm_obj->domain[id].iova);
 
 	seq_printf(m, " %zu%s\n", obj->size, madv);
-
 	rcu_read_lock();
 	fobj = rcu_dereference(robj->fence);
 	if (fobj) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index a6126c9..88ee60d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -527,7 +527,7 @@ static bool nouveau_fence_no_signaling(struct dma_fence *f)
 	 * caller should have a reference on the fence,
 	 * else fence could get freed here
 	 */
-	WARN_ON(atomic_read(&fence->base.refcount.refcount) <= 1);
+	WARN_ON(kref_read(&fence->base.refcount) <= 1);
 
 	/*
 	 * This needs uevents to work correctly, but dma_fence_add_callback relies on
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 4a90c69..74a9968 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -1033,7 +1033,7 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 	off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d",
-			omap_obj->flags, obj->name, obj->refcount.refcount.counter,
+			omap_obj->flags, obj->name, kref_read(&obj->refcount),
 			off, &omap_obj->paddr, omap_obj->paddr_cnt,
 			omap_obj->vaddr, omap_obj->roll);
 
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index d506361..30aefcc 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -140,8 +140,8 @@ static void ttm_bo_release_list(struct kref *list_kref)
 	struct ttm_bo_device *bdev = bo->bdev;
 	size_t acc_size = bo->acc_size;
 
-	BUG_ON(atomic_read(&bo->list_kref.refcount));
-	BUG_ON(atomic_read(&bo->kref.refcount));
+	BUG_ON(kref_read(&bo->list_kref));
+	BUG_ON(kref_read(&bo->kref));
 	BUG_ON(atomic_read(&bo->cpu_writers));
 	BUG_ON(bo->mem.mm_node != NULL);
 	BUG_ON(!list_empty(&bo->lru));
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c
index 4f5fa8d..fdb451e 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/ttm/ttm_object.c
@@ -304,7 +304,7 @@ bool ttm_ref_object_exists(struct ttm_object_file *tfile,
 	 * Verify that the ref->obj pointer was actually valid!
 	 */
 	rmb();
-	if (unlikely(atomic_read(&ref->kref.refcount) == 0))
+	if (unlikely(kref_read(&ref->kref) == 0))
 		goto out_false;
 
 	rcu_read_unlock();
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
index b9efadf..e66e759 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
@@ -55,14 +55,14 @@
 
 #define put_ep(ep) { \
 	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__,  \
-	     ep, atomic_read(&((ep)->kref.refcount))); \
-	WARN_ON(atomic_read(&((ep)->kref.refcount)) < 1); \
+	     ep, kref_read(&((ep)->kref))); \
+	WARN_ON(kref_read(&((ep)->kref)) < 1); \
 	kref_put(&((ep)->kref), __free_ep); \
 }
 
 #define get_ep(ep) { \
 	PDBG("get_ep (via %s:%u) ep %p, refcnt %d\n", __func__, __LINE__, \
-	     ep, atomic_read(&((ep)->kref.refcount))); \
+	     ep, kref_read(&((ep)->kref))); \
 	kref_get(&((ep)->kref));  \
 }
 
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index d939980..a9194db 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -961,7 +961,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
 	case IWCH_QP_STATE_RTS:
 		switch (attrs->next_state) {
 		case IWCH_QP_STATE_CLOSING:
-			BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
+			BUG_ON(kref_read(&qhp->ep->com.kref) < 2);
 			qhp->attr.state = IWCH_QP_STATE_CLOSING;
 			if (!internal) {
 				abort=0;
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 4788e1a..4dc1415 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -654,14 +654,14 @@ enum c4iw_mmid_state {
 
 #define c4iw_put_ep(ep) { \
 	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__,  \
-	     ep, atomic_read(&((ep)->kref.refcount))); \
-	WARN_ON(atomic_read(&((ep)->kref.refcount)) < 1); \
+	     ep, kref_read(&((ep)->kref))); \
+	WARN_ON(kref_read(&((ep)->kref)) < 1); \
 	kref_put(&((ep)->kref), _c4iw_free_ep); \
 }
 
 #define c4iw_get_ep(ep) { \
 	PDBG("get_ep (via %s:%u) ep %p, refcnt %d\n", __func__, __LINE__, \
-	     ep, atomic_read(&((ep)->kref.refcount))); \
+	     ep, kref_read(&((ep)->kref))); \
 	kref_get(&((ep)->kref));  \
 }
 void _c4iw_free_ep(struct kref *kref);
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index cda5542..347b3c9 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -1503,7 +1503,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 	case C4IW_QP_STATE_RTS:
 		switch (attrs->next_state) {
 		case C4IW_QP_STATE_CLOSING:
-			BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
+			BUG_ON(kref_read(&qhp->ep->com.kref) < 2);
 			t4_set_wq_in_error(&qhp->wq);
 			set_state(qhp, C4IW_QP_STATE_CLOSING);
 			ep = qhp->ep;
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
index 80ef3f8..0444324 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
@@ -80,7 +80,7 @@ usnic_ib_show_config(struct device *device, struct device_attribute *attr,
 	left = PAGE_SIZE;
 
 	mutex_lock(&us_ibdev->usdev_lock);
-	if (atomic_read(&us_ibdev->vf_cnt.refcount) > 0) {
+	if (kref_read(&us_ibdev->vf_cnt) > 0) {
 		char *busname;
 
 		/*
@@ -99,7 +99,7 @@ usnic_ib_show_config(struct device *device, struct device_attribute *attr,
 			PCI_FUNC(us_ibdev->pdev->devfn),
 			netdev_name(us_ibdev->netdev),
 			us_ibdev->ufdev->mac,
-			atomic_read(&us_ibdev->vf_cnt.refcount));
+			kref_read(&us_ibdev->vf_cnt));
 		UPDATE_PTR_LEFT(n, ptr, left);
 
 		for (res_type = USNIC_VNIC_RES_TYPE_EOL;
@@ -147,7 +147,7 @@ usnic_ib_show_max_vf(struct device *device, struct device_attribute *attr,
 	us_ibdev = container_of(device, struct usnic_ib_dev, ib_dev.dev);
 
 	return scnprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&us_ibdev->vf_cnt.refcount));
+			kref_read(&us_ibdev->vf_cnt));
 }
 
 static ssize_t
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 74819a7..69df8e3 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -291,11 +291,11 @@ int usnic_ib_query_device(struct ib_device *ibdev,
 	qp_per_vf = max(us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_WQ],
 			us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_RQ]);
 	props->max_qp = qp_per_vf *
-		atomic_read(&us_ibdev->vf_cnt.refcount);
+		kref_read(&us_ibdev->vf_cnt);
 	props->device_cap_flags = IB_DEVICE_PORT_ACTIVE_EVENT |
 		IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
 	props->max_cq = us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_CQ] *
-		atomic_read(&us_ibdev->vf_cnt.refcount);
+		kref_read(&us_ibdev->vf_cnt);
 	props->max_pd = USNIC_UIOM_MAX_PD_CNT;
 	props->max_mr = USNIC_UIOM_MAX_MR_CNT;
 	props->local_ca_ack_delay = 0;
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 7f1b282..cb290b8 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -1396,7 +1396,7 @@ int genwqe_device_remove(struct genwqe_dev *cd)
 	 * application which will decrease this reference from
 	 * 1/unused to 0/illegal and not from 2/used 1/empty.
 	 */
-	rc = atomic_read(&cd->cdev_genwqe.kobj.kref.refcount);
+	rc = kref_read(&cd->cdev_genwqe.kobj.kref);
 	if (rc != 1) {
 		dev_err(&pci_dev->dev,
 			"[%s] err: cdev_genwqe...refcount=%d\n", __func__, rc);
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index c6c051b..e32a923 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -67,7 +67,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
 				me_cl->props.max_number_of_connections,
 				me_cl->props.max_msg_length,
 				me_cl->props.single_recv_buf,
-				atomic_read(&me_cl->refcnt.refcount));
+				kref_read(&me_cl->refcnt));
 
 			mei_me_cl_put(me_cl);
 		}
diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c
index 56efaf7..d2961ef 100644
--- a/drivers/pci/hotplug/pnv_php.c
+++ b/drivers/pci/hotplug/pnv_php.c
@@ -155,7 +155,7 @@ static void pnv_php_detach_device_nodes(struct device_node *parent)
 		pnv_php_detach_device_nodes(dn);
 
 		of_node_put(dn);
-		refcount = atomic_read(&dn->kobj.kref.refcount);
+		refcount = kref_read(&dn->kobj.kref);
 		if (refcount != 1)
 			pr_warn("Invalid refcount %d on <%s>\n",
 				refcount, of_node_full_name(dn));
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 429d34c..e429095 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -345,7 +345,7 @@ EXPORT_SYMBOL_GPL(pci_create_slot);
 void pci_destroy_slot(struct pci_slot *slot)
 {
 	dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n",
-		slot->number, atomic_read(&slot->kobj.kref.refcount) - 1);
+		slot->number, kref_read(&slot->kobj.kref) - 1);
 
 	mutex_lock(&pci_slot_mutex);
 	kobject_put(&slot->kobj);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index f501095..898461b 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -74,7 +74,7 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
 				    &io_req->req_flags)) {
 			/* Handle internally generated ABTS timeout */
 			BNX2FC_IO_DBG(io_req, "ABTS timed out refcnt = %d\n",
-					io_req->refcount.refcount.counter);
+					kref_read(&io_req->refcount));
 			if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
 					       &io_req->req_flags))) {
 				/*
@@ -1141,7 +1141,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
 		return SUCCESS;
 	}
 	BNX2FC_IO_DBG(io_req, "eh_abort - refcnt = %d\n",
-		      io_req->refcount.refcount.counter);
+		      kref_read(&io_req->refcount));
 
 	/* Hold IO request across abort processing */
 	kref_get(&io_req->refcount);
@@ -1299,7 +1299,7 @@ void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
 {
 	BNX2FC_IO_DBG(io_req, "Entered process_cleanup_compl "
 			      "refcnt = %d, cmd_type = %d\n",
-		   io_req->refcount.refcount.counter, io_req->cmd_type);
+		   kref_read(&io_req->refcount), io_req->cmd_type);
 	bnx2fc_scsi_done(io_req, DID_ERROR);
 	kref_put(&io_req->refcount, bnx2fc_cmd_release);
 	if (io_req->wait_for_comp)
@@ -1318,7 +1318,7 @@ void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
 	BNX2FC_IO_DBG(io_req, "Entered process_abts_compl xid = 0x%x"
 			      "refcnt = %d, cmd_type = %d\n",
 		   io_req->xid,
-		   io_req->refcount.refcount.counter, io_req->cmd_type);
+		   kref_read(&io_req->refcount), io_req->cmd_type);
 
 	if (test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
 				       &io_req->req_flags)) {
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 95ba990..18e0ea8 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -301,7 +301,7 @@ static inline void __cxgbi_sock_put(const char *fn, struct cxgbi_sock *csk)
 {
 	log_debug(1 << CXGBI_DBG_SOCK,
 		"%s, put csk 0x%p, ref %u-1.\n",
-		fn, csk, atomic_read(&csk->refcnt.refcount));
+		fn, csk, kref_read(&csk->refcnt));
 	kref_put(&csk->refcnt, cxgbi_sock_free);
 }
 #define cxgbi_sock_put(csk)	__cxgbi_sock_put(__func__, csk)
@@ -310,7 +310,7 @@ static inline void __cxgbi_sock_get(const char *fn, struct cxgbi_sock *csk)
 {
 	log_debug(1 << CXGBI_DBG_SOCK,
 		"%s, get csk 0x%p, ref %u+1.\n",
-		fn, csk, atomic_read(&csk->refcnt.refcount));
+		fn, csk, kref_read(&csk->refcnt));
 	kref_get(&csk->refcnt);
 }
 #define cxgbi_sock_get(csk)	__cxgbi_sock_get(__func__, csk)
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index a63542b..caa7a7b 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -607,7 +607,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
 		len += snprintf(buf+len, size-len, "usgmap:%x ",
 			ndlp->nlp_usg_map);
 		len += snprintf(buf+len, size-len, "refcnt:%x",
-			atomic_read(&ndlp->kref.refcount));
+			kref_read(&ndlp->kref));
 		len +=  snprintf(buf+len, size-len, "\n");
 	}
 	spin_unlock_irq(shost->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 236e4e5..7a88295 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3688,7 +3688,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 		lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
 				 "0006 rpi%x DID:%x flg:%x %d map:%x %p\n",
 				 ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
-				 atomic_read(&ndlp->kref.refcount),
+				 kref_read(&ndlp->kref),
 				 ndlp->nlp_usg_map, ndlp);
 		if (NLP_CHK_NODE_ACT(ndlp)) {
 			lpfc_nlp_put(ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index ed22393..8204707 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -3440,7 +3440,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
 			 "0002 rpi:%x DID:%x flg:%x %d map:%x %p\n",
 			 ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
-			 atomic_read(&ndlp->kref.refcount),
+			 kref_read(&ndlp->kref),
 			 ndlp->nlp_usg_map, ndlp);
 	if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
 		ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
@@ -3861,7 +3861,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
 			 "0003 rpi:%x DID:%x flg:%x %d map%x %p\n",
 			 ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
-			 atomic_read(&ndlp->kref.refcount),
+			 kref_read(&ndlp->kref),
 			 ndlp->nlp_usg_map, ndlp);
 
 	if (vport->port_state < LPFC_VPORT_READY) {
@@ -4238,7 +4238,7 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 				"0277 lpfc_enable_node: ndlp:x%p "
 				"usgmap:x%x refcnt:%d\n",
 				(void *)ndlp, ndlp->nlp_usg_map,
-				atomic_read(&ndlp->kref.refcount));
+				kref_read(&ndlp->kref));
 		return NULL;
 	}
 	/* The ndlp should not already be in active mode */
@@ -4248,7 +4248,7 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 				"0278 lpfc_enable_node: ndlp:x%p "
 				"usgmap:x%x refcnt:%d\n",
 				(void *)ndlp, ndlp->nlp_usg_map,
-				atomic_read(&ndlp->kref.refcount));
+				kref_read(&ndlp->kref));
 		return NULL;
 	}
 
@@ -4272,7 +4272,7 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 				 "0008 rpi:%x DID:%x flg:%x refcnt:%d "
 				 "map:%x %p\n", ndlp->nlp_rpi, ndlp->nlp_DID,
 				 ndlp->nlp_flag,
-				 atomic_read(&ndlp->kref.refcount),
+				 kref_read(&ndlp->kref),
 				 ndlp->nlp_usg_map, ndlp);
 	}
 
@@ -4546,7 +4546,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 				    (bf_get(lpfc_sli_intf_if_type,
 				     &phba->sli4_hba.sli_intf) ==
 				      LPFC_SLI_INTF_IF_TYPE_2) &&
-				    (atomic_read(&ndlp->kref.refcount) > 0)) {
+				    (kref_read(&ndlp->kref) > 0)) {
 					mbox->context1 = lpfc_nlp_get(ndlp);
 					mbox->mbox_cmpl =
 						lpfc_sli4_unreg_rpi_cmpl_clr;
@@ -4695,14 +4695,14 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 				"0280 lpfc_cleanup_node: ndlp:x%p "
 				"usgmap:x%x refcnt:%d\n",
 				(void *)ndlp, ndlp->nlp_usg_map,
-				atomic_read(&ndlp->kref.refcount));
+				kref_read(&ndlp->kref));
 		lpfc_dequeue_node(vport, ndlp);
 	} else {
 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
 				"0281 lpfc_cleanup_node: ndlp:x%p "
 				"usgmap:x%x refcnt:%d\n",
 				(void *)ndlp, ndlp->nlp_usg_map,
-				atomic_read(&ndlp->kref.refcount));
+				kref_read(&ndlp->kref));
 		lpfc_disable_node(vport, ndlp);
 	}
 
@@ -4791,7 +4791,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 		lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
 				 "0005 rpi:%x DID:%x flg:%x %d map:%x %p\n",
 				 ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
-				 atomic_read(&ndlp->kref.refcount),
+				 kref_read(&ndlp->kref),
 				 ndlp->nlp_usg_map, ndlp);
 		if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))
 			!= NULL) {
@@ -5557,7 +5557,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
 			 "0004 rpi:%x DID:%x flg:%x %d map:%x %p\n",
 			 ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
-			 atomic_read(&ndlp->kref.refcount),
+			 kref_read(&ndlp->kref),
 			 ndlp->nlp_usg_map, ndlp);
 	/*
 	 * Start issuing Fabric-Device Management Interface (FDMI) command to
@@ -5728,7 +5728,7 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 				 "0007 rpi:%x DID:%x flg:%x refcnt:%d "
 				 "map:%x %p\n", ndlp->nlp_rpi, ndlp->nlp_DID,
 				 ndlp->nlp_flag,
-				 atomic_read(&ndlp->kref.refcount),
+				 kref_read(&ndlp->kref),
 				 ndlp->nlp_usg_map, ndlp);
 
 		ndlp->active_rrqs_xri_bitmap =
@@ -5767,7 +5767,7 @@ lpfc_nlp_release(struct kref *kref)
 			"0279 lpfc_nlp_release: ndlp:x%p did %x "
 			"usgmap:x%x refcnt:%d rpi:%x\n",
 			(void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map,
-			atomic_read(&ndlp->kref.refcount), ndlp->nlp_rpi);
+			kref_read(&ndlp->kref), ndlp->nlp_rpi);
 
 	/* remove ndlp from action. */
 	lpfc_nlp_remove(ndlp->vport, ndlp);
@@ -5804,7 +5804,7 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
 		lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
 			"node get:        did:x%x flg:x%x refcnt:x%x",
 			ndlp->nlp_DID, ndlp->nlp_flag,
-			atomic_read(&ndlp->kref.refcount));
+			kref_read(&ndlp->kref));
 		/* The check of ndlp usage to prevent incrementing the
 		 * ndlp reference count that is in the process of being
 		 * released.
@@ -5817,7 +5817,7 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
 				"0276 lpfc_nlp_get: ndlp:x%p "
 				"usgmap:x%x refcnt:%d\n",
 				(void *)ndlp, ndlp->nlp_usg_map,
-				atomic_read(&ndlp->kref.refcount));
+				kref_read(&ndlp->kref));
 			return NULL;
 		} else
 			kref_get(&ndlp->kref);
@@ -5844,7 +5844,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)
 	lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
 	"node put:        did:x%x flg:x%x refcnt:x%x",
 		ndlp->nlp_DID, ndlp->nlp_flag,
-		atomic_read(&ndlp->kref.refcount));
+		kref_read(&ndlp->kref));
 	phba = ndlp->phba;
 	spin_lock_irqsave(&phba->ndlp_lock, flags);
 	/* Check the ndlp memory free acknowledge flag to avoid the
@@ -5857,7 +5857,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)
 				"0274 lpfc_nlp_put: ndlp:x%p "
 				"usgmap:x%x refcnt:%d\n",
 				(void *)ndlp, ndlp->nlp_usg_map,
-				atomic_read(&ndlp->kref.refcount));
+				kref_read(&ndlp->kref));
 		return 1;
 	}
 	/* Check the ndlp inactivate log flag to avoid the possible
@@ -5870,7 +5870,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)
 				"0275 lpfc_nlp_put: ndlp:x%p "
 				"usgmap:x%x refcnt:%d\n",
 				(void *)ndlp, ndlp->nlp_usg_map,
-				atomic_read(&ndlp->kref.refcount));
+				kref_read(&ndlp->kref));
 		return 1;
 	}
 	/* For last put, mark the ndlp usage flags to make sure no
@@ -5878,7 +5878,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)
 	 * in between the process when the final kref_put has been
 	 * invoked on this ndlp.
 	 */
-	if (atomic_read(&ndlp->kref.refcount) == 1) {
+	if (kref_read(&ndlp->kref) == 1) {
 		/* Indicate ndlp is put to inactive state. */
 		NLP_SET_IACT_REQ(ndlp);
 		/* Acknowledge ndlp memory free has been seen. */
@@ -5906,8 +5906,8 @@ lpfc_nlp_not_used(struct lpfc_nodelist *ndlp)
 	lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
 		"node not used:   did:x%x flg:x%x refcnt:x%x",
 		ndlp->nlp_DID, ndlp->nlp_flag,
-		atomic_read(&ndlp->kref.refcount));
-	if (atomic_read(&ndlp->kref.refcount) == 1)
+		kref_read(&ndlp->kref));
+	if (kref_read(&ndlp->kref) == 1)
 		if (lpfc_nlp_put(ndlp))
 			return 1;
 	return 0;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4776fd8..64717c1 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2660,8 +2660,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
 						"usgmap:x%x refcnt:%d\n",
 						ndlp->nlp_DID, (void *)ndlp,
 						ndlp->nlp_usg_map,
-						atomic_read(
-							&ndlp->kref.refcount));
+						kref_read(&ndlp->kref));
 			}
 			break;
 		}
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 6643f6f..dd28c69 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -371,7 +371,7 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
 		 */
 		pr_debug("write_pending aborted cmd[%p] refcount %d "
 			"transport_state %x, t_state %x, se_cmd_flags %x\n",
-			cmd,cmd->se_cmd.cmd_kref.refcount.counter,
+			cmd, kref_read(&cmd->se_cmd.cmd_kref),
 			cmd->se_cmd.transport_state,
 			cmd->se_cmd.t_state,
 			cmd->se_cmd.se_cmd_flags);
@@ -584,7 +584,7 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
 		 */
 		pr_debug("queue_data_in aborted cmd[%p] refcount %d "
 			"transport_state %x, t_state %x, se_cmd_flags %x\n",
-			cmd,cmd->se_cmd.cmd_kref.refcount.counter,
+			cmd, kref_read(&cmd->se_cmd.cmd_kref),
 			cmd->se_cmd.transport_state,
 			cmd->se_cmd.t_state,
 			cmd->se_cmd.se_cmd_flags);
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index b653451..937c2d5 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -1300,7 +1300,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused)
 			seq_printf(s, "%16s %16u %16zu %d %d\n",
 				   buffer->task_comm, buffer->pid,
 				   buffer->size, buffer->kmap_cnt,
-				   atomic_read(&buffer->ref.refcount));
+				   kref_read(&buffer->ref));
 			total_orphaned_size += buffer->size;
 		}
 	}
diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
index c7d7682..1e1df89 100644
--- a/drivers/staging/comedi/comedi_buf.c
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -188,7 +188,7 @@ bool comedi_buf_is_mmapped(struct comedi_subdevice *s)
 {
 	struct comedi_buf_map *bm = s->async->buf_map;
 
-	return bm && (atomic_read(&bm->refcount.refcount) > 1);
+	return bm && (kref_read(&bm->refcount) > 1);
 }
 
 int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index d761025..e180511 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -788,7 +788,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
 			 * __core_scsi3_add_registration()
 			 */
 			dest_lun = rcu_dereference_check(deve_tmp->se_lun,
-				atomic_read(&deve_tmp->pr_kref.refcount) != 0);
+				kref_read(&deve_tmp->pr_kref) != 0);
 
 			pr_reg_atp = __core_scsi3_do_alloc_registration(dev,
 						nacl_tmp, dest_lun, deve_tmp,
@@ -1463,7 +1463,7 @@ static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
 	 * For nacl->dynamic_node_acl=1
 	 */
 	lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
-				atomic_read(&se_deve->pr_kref.refcount) != 0);
+				kref_read(&se_deve->pr_kref) != 0);
 	if (!lun_acl)
 		return 0;
 
@@ -1478,7 +1478,7 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
 	 * For nacl->dynamic_node_acl=1
 	 */
 	lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
-				atomic_read(&se_deve->pr_kref.refcount) != 0);
+				kref_read(&se_deve->pr_kref) != 0);
 	if (!lun_acl) {
 		kref_put(&se_deve->pr_kref, target_pr_kref_release);
 		return;
@@ -1759,7 +1759,7 @@ core_scsi3_decode_spec_i_port(
 		 * 2nd loop which will never fail.
 		 */
 		dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
-				atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
+				kref_read(&dest_se_deve->pr_kref) != 0);
 
 		dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
 					dest_node_acl, dest_lun, dest_se_deve,
@@ -3466,7 +3466,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
 					iport_ptr);
 	if (!dest_pr_reg) {
 		struct se_lun *dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
-				atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
+				kref_read(&dest_se_deve->pr_kref) != 0);
 
 		spin_unlock(&dev->dev_reservation_lock);
 		if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl,
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index fd5c3de..c91979c 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -454,7 +454,7 @@ static void ft_sess_free(struct kref *kref)
 
 void ft_sess_put(struct ft_sess *sess)
 {
-	int sess_held = atomic_read(&sess->kref.refcount);
+	int sess_held = kref_read(&sess->kref);
 
 	BUG_ON(!sess_held);
 	kref_put(&sess->kref, ft_sess_free);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index aab3fc1..1eeb319 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -3686,7 +3686,7 @@ static void ffs_closed(struct ffs_data *ffs)
 		goto done;
 
 	if (opts->no_configfs || !opts->func_inst.group.cg_item.ci_parent
-	    || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
+	    || !kref_read(&opts->func_inst.group.cg_item.ci_kref))
 		goto done;
 
 	unregister_gadget_item(ffs_obj->opts->
diff --git a/fs/exofs/sys.c b/fs/exofs/sys.c
index 5e6a2c0..1f7d5e4 100644
--- a/fs/exofs/sys.c
+++ b/fs/exofs/sys.c
@@ -122,7 +122,7 @@ void exofs_sysfs_dbg_print(void)
 	list_for_each_entry_safe(k_name, k_tmp, &exofs_kset->list, entry) {
 		printk(KERN_INFO "%s: name %s ref %d\n",
 			__func__, kobject_name(k_name),
-			(int)atomic_read(&k_name->kref.refcount));
+			(int)kref_read(&k_name->kref));
 	}
 #endif
 }
diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c
index 27d1242..564c504 100644
--- a/fs/ocfs2/cluster/netdebug.c
+++ b/fs/ocfs2/cluster/netdebug.c
@@ -349,7 +349,7 @@ static void sc_show_sock_container(struct seq_file *seq,
 		   "  func key:        0x%08x\n"
 		   "  func type:       %u\n",
 		   sc,
-		   atomic_read(&sc->sc_kref.refcount),
+		   kref_read(&sc->sc_kref),
 		   &saddr, inet ? ntohs(sport) : 0,
 		   &daddr, inet ? ntohs(dport) : 0,
 		   sc->sc_node->nd_name,
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index d4b5c81..ec00057 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -97,7 +97,7 @@
 	typeof(sc) __sc = (sc);						\
 	mlog(ML_SOCKET, "[sc %p refs %d sock %p node %u page %p "	\
 	     "pg_off %zu] " fmt, __sc,					\
-	     atomic_read(&__sc->sc_kref.refcount), __sc->sc_sock,	\
+	     kref_read(&__sc->sc_kref), __sc->sc_sock,	\
 	    __sc->sc_node->nd_num, __sc->sc_page, __sc->sc_page_off ,	\
 	    ##args);							\
 } while (0)
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index e7b760d..9b984ca 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -81,7 +81,7 @@ static void __dlm_print_lock(struct dlm_lock *lock)
 	       lock->ml.type, lock->ml.convert_type, lock->ml.node,
 	       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
 	       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
-	       atomic_read(&lock->lock_refs.refcount),
+	       kref_read(&lock->lock_refs),
 	       (list_empty(&lock->ast_list) ? 'y' : 'n'),
 	       (lock->ast_pending ? 'y' : 'n'),
 	       (list_empty(&lock->bast_list) ? 'y' : 'n'),
@@ -106,7 +106,7 @@ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
 	printk("lockres: %s, owner=%u, state=%u\n",
 	       buf, res->owner, res->state);
 	printk("  last used: %lu, refcnt: %u, on purge list: %s\n",
-	       res->last_used, atomic_read(&res->refs.refcount),
+	       res->last_used, kref_read(&res->refs),
 	       list_empty(&res->purge) ? "no" : "yes");
 	printk("  on dirty list: %s, on reco list: %s, "
 	       "migrating pending: %s\n",
@@ -298,7 +298,7 @@ static int dump_mle(struct dlm_master_list_entry *mle, char *buf, int len)
 			mle_type, mle->master, mle->new_master,
 			!list_empty(&mle->hb_events),
 			!!mle->inuse,
-			atomic_read(&mle->mle_refs.refcount));
+			kref_read(&mle->mle_refs));
 
 	out += snprintf(buf + out, len - out, "Maybe=");
 	out += stringify_nodemap(mle->maybe_map, O2NM_MAX_NODES,
@@ -494,7 +494,7 @@ static int dump_lock(struct dlm_lock *lock, int list_type, char *buf, int len)
 		       lock->ast_pending, lock->bast_pending,
 		       lock->convert_pending, lock->lock_pending,
 		       lock->cancel_pending, lock->unlock_pending,
-		       atomic_read(&lock->lock_refs.refcount));
+		       kref_read(&lock->lock_refs));
 	spin_unlock(&lock->spinlock);
 
 	return out;
@@ -521,7 +521,7 @@ static int dump_lockres(struct dlm_lock_resource *res, char *buf, int len)
 			!list_empty(&res->recovering),
 			res->inflight_locks, res->migration_pending,
 			atomic_read(&res->asts_reserved),
-			atomic_read(&res->refs.refcount));
+			kref_read(&res->refs));
 
 	/* refmap */
 	out += snprintf(buf + out, len - out, "RMAP:");
@@ -777,7 +777,7 @@ static int debug_state_print(struct dlm_ctxt *dlm, char *buf, int len)
 	/* Purge Count: xxx  Refs: xxx */
 	out += snprintf(buf + out, len - out,
 			"Purge Count: %d  Refs: %d\n", dlm->purge_count,
-			atomic_read(&dlm->dlm_refs.refcount));
+			kref_read(&dlm->dlm_refs));
 
 	/* Dead Node: xxx */
 	out += snprintf(buf + out, len - out,
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 733e4e7..32fd261 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -2072,7 +2072,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
 	INIT_LIST_HEAD(&dlm->dlm_eviction_callbacks);
 
 	mlog(0, "context init: refcount %u\n",
-		  atomic_read(&dlm->dlm_refs.refcount));
+		  kref_read(&dlm->dlm_refs));
 
 leave:
 	if (ret < 0 && dlm) {
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index a464c80..7025d8c 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -233,7 +233,7 @@ static void __dlm_put_mle(struct dlm_master_list_entry *mle)
 
 	assert_spin_locked(&dlm->spinlock);
 	assert_spin_locked(&dlm->master_lock);
-	if (!atomic_read(&mle->mle_refs.refcount)) {
+	if (!kref_read(&mle->mle_refs)) {
 		/* this may or may not crash, but who cares.
 		 * it's a BUG. */
 		mlog(ML_ERROR, "bad mle: %p\n", mle);
@@ -1124,9 +1124,9 @@ static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm,
 		unsigned long timeo = msecs_to_jiffies(DLM_MASTERY_TIMEOUT_MS);
 
 		/*
-		if (atomic_read(&mle->mle_refs.refcount) < 2)
+		if (kref_read(&mle->mle_refs) < 2)
 			mlog(ML_ERROR, "mle (%p) refs=%d, name=%.*s\n", mle,
-			atomic_read(&mle->mle_refs.refcount),
+			kref_read(&mle->mle_refs),
 			res->lockname.len, res->lockname.name);
 		*/
 		atomic_set(&mle->woken, 0);
@@ -1979,7 +1979,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
 		 * on this mle. */
 		spin_lock(&dlm->master_lock);
 
-		rr = atomic_read(&mle->mle_refs.refcount);
+		rr = kref_read(&mle->mle_refs);
 		if (mle->inuse > 0) {
 			if (extra_ref && rr < 3)
 				err = 1;
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index 1082b2c..63d701c 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -251,7 +251,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
 		mlog(0, "lock %u:%llu should be gone now! refs=%d\n",
 		     dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
 		     dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
-		     atomic_read(&lock->lock_refs.refcount)-1);
+		     kref_read(&lock->lock_refs)-1);
 		dlm_lock_put(lock);
 	}
 	if (actions & DLM_UNLOCK_CALL_AST)
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index 1ddfa29..a232e7f 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -247,7 +247,7 @@ static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
  */
 static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
 {
-	return atomic_read(&fb->base.refcount.refcount);
+	return kref_read(&fb->base.refcount);
 }
 
 /**
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index cdbdb40..feecf33 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -878,7 +878,7 @@ static inline int ttm_bo_reserve(struct ttm_buffer_object *bo,
 {
 	int ret;
 
-	WARN_ON(!atomic_read(&bo->kref.refcount));
+	WARN_ON(!kref_read(&bo->kref));
 
 	ret = __ttm_bo_reserve(bo, interruptible, no_wait, ticket);
 	if (likely(ret == 0))
@@ -903,7 +903,7 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
 {
 	int ret = 0;
 
-	WARN_ON(!atomic_read(&bo->kref.refcount));
+	WARN_ON(!kref_read(&bo->kref));
 
 	if (interruptible)
 		ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
diff --git a/include/linux/kref.h b/include/linux/kref.h
index 9af255a..7c88d86 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -35,6 +35,11 @@ static inline void kref_init(struct kref *kref)
 	atomic_set(&kref->refcount, 1);
 }
 
+static inline int kref_read(const struct kref *kref)
+{
+	return atomic_read(&kref->refcount);
+}
+
 /**
  * kref_get - increment refcount for object.
  * @kref: object.
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 62a60ee..8a511c0 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -198,7 +198,7 @@ static inline struct cache_head  *cache_get(struct cache_head *h)
 
 static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
 {
-	if (atomic_read(&h->ref.refcount) <= 2 &&
+	if (kref_read(&h->ref) <= 2 &&
 	    h->expiry_time < cd->nextcheck)
 		cd->nextcheck = h->expiry_time;
 	kref_put(&h->ref, cd->cache_put);
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 554671c..90708f6 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -987,7 +987,7 @@ static inline void hci_conn_drop(struct hci_conn *conn)
 static inline void hci_dev_put(struct hci_dev *d)
 {
 	BT_DBG("%s orig refcnt %d", d->name,
-	       atomic_read(&d->dev.kobj.kref.refcount));
+	       kref_read(&d->dev.kobj.kref));
 
 	put_device(&d->dev);
 }
@@ -995,7 +995,7 @@ static inline void hci_dev_put(struct hci_dev *d)
 static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
 {
 	BT_DBG("%s orig refcnt %d", d->name,
-	       atomic_read(&d->dev.kobj.kref.refcount));
+	       kref_read(&d->dev.kobj.kref));
 
 	get_device(&d->dev);
 	return d;
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 1904a93..d491529 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -920,7 +920,7 @@ static void chan_close_cb(struct l2cap_chan *chan)
 			BT_DBG("dev %p removing %speer %p", dev,
 			       last ? "last " : "1 ", peer);
 			BT_DBG("chan %p orig refcnt %d", chan,
-			       atomic_read(&chan->kref.refcount));
+			       kref_read(&chan->kref));
 
 			l2cap_chan_put(chan);
 			break;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index e32f341..02a4ccc 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -24,7 +24,7 @@
 void amp_ctrl_get(struct amp_ctrl *ctrl)
 {
 	BT_DBG("ctrl %p orig refcnt %d", ctrl,
-	       atomic_read(&ctrl->kref.refcount));
+	       kref_read(&ctrl->kref));
 
 	kref_get(&ctrl->kref);
 }
@@ -42,7 +42,7 @@ static void amp_ctrl_destroy(struct kref *kref)
 int amp_ctrl_put(struct amp_ctrl *ctrl)
 {
 	BT_DBG("ctrl %p orig refcnt %d", ctrl,
-	       atomic_read(&ctrl->kref.refcount));
+	       kref_read(&ctrl->kref));
 
 	return kref_put(&ctrl->kref, &amp_ctrl_destroy);
 }
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ce0b5dd..fc7f321 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -481,14 +481,14 @@ static void l2cap_chan_destroy(struct kref *kref)
 
 void l2cap_chan_hold(struct l2cap_chan *c)
 {
-	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
+	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
 
 	kref_get(&c->kref);
 }
 
 void l2cap_chan_put(struct l2cap_chan *c)
 {
-	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
+	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
 
 	kref_put(&c->kref, l2cap_chan_destroy);
 }
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 770c527..bad3d4a 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -3425,7 +3425,7 @@ static void ceph_msg_release(struct kref *kref)
 struct ceph_msg *ceph_msg_get(struct ceph_msg *msg)
 {
 	dout("%s %p (was %d)\n", __func__, msg,
-	     atomic_read(&msg->kref.refcount));
+	     kref_read(&msg->kref));
 	kref_get(&msg->kref);
 	return msg;
 }
@@ -3434,7 +3434,7 @@ EXPORT_SYMBOL(ceph_msg_get);
 void ceph_msg_put(struct ceph_msg *msg)
 {
 	dout("%s %p (was %d)\n", __func__, msg,
-	     atomic_read(&msg->kref.refcount));
+	     kref_read(&msg->kref));
 	kref_put(&msg->kref, ceph_msg_release);
 }
 EXPORT_SYMBOL(ceph_msg_put);
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 842f049..b490e74 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -438,7 +438,7 @@ static void ceph_osdc_release_request(struct kref *kref)
 void ceph_osdc_get_request(struct ceph_osd_request *req)
 {
 	dout("%s %p (was %d)\n", __func__, req,
-	     atomic_read(&req->r_kref.refcount));
+	     kref_read(&req->r_kref));
 	kref_get(&req->r_kref);
 }
 EXPORT_SYMBOL(ceph_osdc_get_request);
@@ -447,7 +447,7 @@ void ceph_osdc_put_request(struct ceph_osd_request *req)
 {
 	if (req) {
 		dout("%s %p (was %d)\n", __func__, req,
-		     atomic_read(&req->r_kref.refcount));
+		     kref_read(&req->r_kref));
 		kref_put(&req->r_kref, ceph_osdc_release_request);
 	}
 }
@@ -487,11 +487,11 @@ static void request_reinit(struct ceph_osd_request *req)
 	struct ceph_msg *reply_msg = req->r_reply;
 
 	dout("%s req %p\n", __func__, req);
-	WARN_ON(atomic_read(&req->r_kref.refcount) != 1);
+	WARN_ON(kref_read(&req->r_kref) != 1);
 	request_release_checks(req);
 
-	WARN_ON(atomic_read(&request_msg->kref.refcount) != 1);
-	WARN_ON(atomic_read(&reply_msg->kref.refcount) != 1);
+	WARN_ON(kref_read(&req->r_kref) != 1);
+	WARN_ON(kref_read(&req->r_kref) != 1);
 	target_destroy(&req->r_t);
 
 	request_init(req);
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 8147e8d..f39e3e1 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1358,7 +1358,7 @@ static int c_show(struct seq_file *m, void *p)
 	ifdebug(CACHE)
 		seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
 			   convert_to_wallclock(cp->expiry_time),
-			   atomic_read(&cp->ref.refcount), cp->flags);
+			   kref_read(&cp->ref), cp->flags);
 	cache_get(cp);
 	if (cache_check(cd, cp, NULL))
 		/* cache_check does a cache_put on failure */
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 3bc1d61..04e7f87 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -490,7 +490,7 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
 		svc_xprt_get(xprt);
 
 		dprintk("svc: transport %p dequeued, inuse=%d\n",
-			xprt, atomic_read(&xprt->xpt_ref.refcount));
+			xprt, kref_read(&xprt->xpt_ref));
 	}
 	spin_unlock_bh(&pool->sp_lock);
 out:
@@ -820,7 +820,7 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
 		/* XPT_DATA|XPT_DEFERRED case: */
 		dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
 			rqstp, rqstp->rq_pool->sp_id, xprt,
-			atomic_read(&xprt->xpt_ref.refcount));
+			kref_read(&xprt->xpt_ref));
 		rqstp->rq_deferred = svc_deferred_dequeue(xprt);
 		if (rqstp->rq_deferred)
 			len = svc_deferred_recv(rqstp);
@@ -978,7 +978,7 @@ static void svc_age_temp_xprts(unsigned long closure)
 		 * through, close it. */
 		if (!test_and_set_bit(XPT_OLD, &xprt->xpt_flags))
 			continue;
-		if (atomic_read(&xprt->xpt_ref.refcount) > 1 ||
+		if (kref_read(&xprt->xpt_ref) > 1 ||
 		    test_bit(XPT_BUSY, &xprt->xpt_flags))
 			continue;
 		list_del_init(le);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index ca2799a..39652d3 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -1201,9 +1201,9 @@ static void __svc_rdma_free(struct work_struct *work)
 		ib_drain_qp(rdma->sc_qp);
 
 	/* We should only be called from kref_put */
-	if (atomic_read(&xprt->xpt_ref.refcount) != 0)
+	if (kref_read(&xprt->xpt_ref) != 0)
 		pr_err("svcrdma: sc_xprt still in use? (%d)\n",
-		       atomic_read(&xprt->xpt_ref.refcount));
+		       kref_read(&xprt->xpt_ref));
 
 	/*
 	 * Destroy queued, but not processed read completions. Note
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 03/18] kref: Kill kref_sub()
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 01/18] kref: Add KREF_INIT() Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 02/18] kref: Add kref_read() Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 04/18] kref: Use kref_get_unless_zero() more Elena Reshetova
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh

From: Peter Zijlstra <peterz@infradead.org>

By general sentiment kref_sub() is a bad interface, make it go away.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/block/drbd/drbd_main.c         |  7 ++--
 drivers/block/drbd/drbd_req.c          | 31 ++++++------------
 drivers/gpu/drm/ttm/ttm_bo.c           | 59 +++++++++-------------------------
 drivers/gpu/drm/ttm/ttm_execbuf_util.c |  4 +--
 include/drm/ttm/ttm_bo_api.h           | 15 +--------
 include/linux/kref.h                   | 32 +++---------------
 6 files changed, 36 insertions(+), 112 deletions(-)

diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 8348272..c3ff60c 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2948,7 +2948,6 @@ void drbd_delete_device(struct drbd_device *device)
 	struct drbd_resource *resource = device->resource;
 	struct drbd_connection *connection;
 	struct drbd_peer_device *peer_device;
-	int refs = 3;
 
 	/* move to free_peer_device() */
 	for_each_peer_device(peer_device, device)
@@ -2956,13 +2955,15 @@ void drbd_delete_device(struct drbd_device *device)
 	drbd_debugfs_device_cleanup(device);
 	for_each_connection(connection, resource) {
 		idr_remove(&connection->peer_devices, device->vnr);
-		refs++;
+		kref_put(&device->kref, drbd_destroy_device);
 	}
 	idr_remove(&resource->devices, device->vnr);
+	kref_put(&device->kref, drbd_destroy_device);
 	idr_remove(&drbd_devices, device_to_minor(device));
+	kref_put(&device->kref, drbd_destroy_device);
 	del_gendisk(device->vdisk);
 	synchronize_rcu();
-	kref_sub(&device->kref, refs, drbd_destroy_device);
+	kref_put(&device->kref, drbd_destroy_device);
 }
 
 static int __init drbd_init(void)
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 74306c0..b489ac2 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -421,7 +421,6 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 	struct drbd_peer_device *peer_device = first_peer_device(device);
 	unsigned s = req->rq_state;
 	int c_put = 0;
-	int k_put = 0;
 
 	if (drbd_suspended(device) && !((s | clear) & RQ_COMPLETION_SUSP))
 		set |= RQ_COMPLETION_SUSP;
@@ -437,6 +436,8 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 
 	/* intent: get references */
 
+	kref_get(&req->kref);
+
 	if (!(s & RQ_LOCAL_PENDING) && (set & RQ_LOCAL_PENDING))
 		atomic_inc(&req->completion_ref);
 
@@ -473,15 +474,12 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 
 	if (!(s & RQ_LOCAL_ABORTED) && (set & RQ_LOCAL_ABORTED)) {
 		D_ASSERT(device, req->rq_state & RQ_LOCAL_PENDING);
-		/* local completion may still come in later,
-		 * we need to keep the req object around. */
-		kref_get(&req->kref);
 		++c_put;
 	}
 
 	if ((s & RQ_LOCAL_PENDING) && (clear & RQ_LOCAL_PENDING)) {
 		if (req->rq_state & RQ_LOCAL_ABORTED)
-			++k_put;
+			kref_put(&req->kref, drbd_req_destroy);
 		else
 			++c_put;
 		list_del_init(&req->req_pending_local);
@@ -503,7 +501,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 		if (s & RQ_NET_SENT)
 			atomic_sub(req->i.size >> 9, &device->ap_in_flight);
 		if (s & RQ_EXP_BARR_ACK)
-			++k_put;
+			kref_put(&req->kref, drbd_req_destroy);
 		req->net_done_jif = jiffies;
 
 		/* in ahead/behind mode, or just in case,
@@ -516,25 +514,16 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
 
 	/* potentially complete and destroy */
 
-	if (k_put || c_put) {
-		/* Completion does it's own kref_put.  If we are going to
-		 * kref_sub below, we need req to be still around then. */
-		int at_least = k_put + !!c_put;
-		int refcount = kref_read(&req->kref);
-		if (refcount < at_least)
-			drbd_err(device,
-				"mod_rq_state: Logic BUG: %x -> %x: refcount = %d, should be >= %d\n",
-				s, req->rq_state, refcount, at_least);
-	}
-
 	/* If we made progress, retry conflicting peer requests, if any. */
 	if (req->i.waiting)
 		wake_up(&device->misc_wait);
 
-	if (c_put)
-		k_put += drbd_req_put_completion_ref(req, m, c_put);
-	if (k_put)
-		kref_sub(&req->kref, k_put, drbd_req_destroy);
+	if (c_put) {
+		if (drbd_req_put_completion_ref(req, m, c_put))
+			kref_put(&req->kref, drbd_req_destroy);
+	} else {
+		kref_put(&req->kref, drbd_req_destroy);
+	}
 }
 
 static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 30aefcc..ffc6cb5 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -181,61 +181,46 @@ void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
 }
 EXPORT_SYMBOL(ttm_bo_add_to_lru);
 
-int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
+static void ttm_bo_ref_bug(struct kref *list_kref)
+{
+	BUG();
+}
+
+void ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
-	int put_count = 0;
 
 	if (bdev->driver->lru_removal)
 		bdev->driver->lru_removal(bo);
 
 	if (!list_empty(&bo->swap)) {
 		list_del_init(&bo->swap);
-		++put_count;
+		kref_put(&bo->list_kref, ttm_bo_ref_bug);
 	}
 	if (!list_empty(&bo->lru)) {
 		list_del_init(&bo->lru);
-		++put_count;
+		kref_put(&bo->list_kref, ttm_bo_ref_bug);
 	}
-
-	return put_count;
-}
-
-static void ttm_bo_ref_bug(struct kref *list_kref)
-{
-	BUG();
-}
-
-void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count,
-			 bool never_free)
-{
-	kref_sub(&bo->list_kref, count,
-		 (never_free) ? ttm_bo_ref_bug : ttm_bo_release_list);
 }
 
 void ttm_bo_del_sub_from_lru(struct ttm_buffer_object *bo)
 {
-	int put_count;
-
 	spin_lock(&bo->glob->lru_lock);
-	put_count = ttm_bo_del_from_lru(bo);
+	ttm_bo_del_from_lru(bo);
 	spin_unlock(&bo->glob->lru_lock);
-	ttm_bo_list_ref_sub(bo, put_count, true);
 }
 EXPORT_SYMBOL(ttm_bo_del_sub_from_lru);
 
 void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
-	int put_count = 0;
 
 	lockdep_assert_held(&bo->resv->lock.base);
 
 	if (bdev->driver->lru_removal)
 		bdev->driver->lru_removal(bo);
 
-	put_count = ttm_bo_del_from_lru(bo);
-	ttm_bo_list_ref_sub(bo, put_count, true);
+	ttm_bo_del_from_lru(bo);
 	ttm_bo_add_to_lru(bo);
 }
 EXPORT_SYMBOL(ttm_bo_move_to_lru_tail);
@@ -447,7 +432,6 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
 	struct ttm_bo_global *glob = bo->glob;
-	int put_count;
 	int ret;
 
 	spin_lock(&glob->lru_lock);
@@ -455,13 +439,10 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
 
 	if (!ret) {
 		if (!ttm_bo_wait(bo, false, true)) {
-			put_count = ttm_bo_del_from_lru(bo);
-
+			ttm_bo_del_from_lru(bo);
 			spin_unlock(&glob->lru_lock);
 			ttm_bo_cleanup_memtype_use(bo);
 
-			ttm_bo_list_ref_sub(bo, put_count, true);
-
 			return;
 		} else
 			ttm_bo_flush_all_fences(bo);
@@ -504,7 +485,6 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo,
 					  bool no_wait_gpu)
 {
 	struct ttm_bo_global *glob = bo->glob;
-	int put_count;
 	int ret;
 
 	ret = ttm_bo_wait(bo, false, true);
@@ -554,15 +534,13 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo,
 		return ret;
 	}
 
-	put_count = ttm_bo_del_from_lru(bo);
+	ttm_bo_del_from_lru(bo);
 	list_del_init(&bo->ddestroy);
-	++put_count;
+	kref_put(&bo->list_kref, ttm_bo_ref_bug);
 
 	spin_unlock(&glob->lru_lock);
 	ttm_bo_cleanup_memtype_use(bo);
 
-	ttm_bo_list_ref_sub(bo, put_count, true);
-
 	return 0;
 }
 
@@ -740,7 +718,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
 	struct ttm_bo_global *glob = bdev->glob;
 	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
 	struct ttm_buffer_object *bo;
-	int ret = -EBUSY, put_count;
+	int ret = -EBUSY;
 
 	spin_lock(&glob->lru_lock);
 	list_for_each_entry(bo, &man->lru, lru) {
@@ -771,13 +749,11 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
 		return ret;
 	}
 
-	put_count = ttm_bo_del_from_lru(bo);
+	ttm_bo_del_from_lru(bo);
 	spin_unlock(&glob->lru_lock);
 
 	BUG_ON(ret != 0);
 
-	ttm_bo_list_ref_sub(bo, put_count, true);
-
 	ret = ttm_bo_evict(bo, interruptible, no_wait_gpu);
 	ttm_bo_unreserve(bo);
 
@@ -1669,7 +1645,6 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
 	    container_of(shrink, struct ttm_bo_global, shrink);
 	struct ttm_buffer_object *bo;
 	int ret = -EBUSY;
-	int put_count;
 	uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM);
 
 	spin_lock(&glob->lru_lock);
@@ -1692,11 +1667,9 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
 		return ret;
 	}
 
-	put_count = ttm_bo_del_from_lru(bo);
+	ttm_bo_del_from_lru(bo);
 	spin_unlock(&glob->lru_lock);
 
-	ttm_bo_list_ref_sub(bo, put_count, true);
-
 	/**
 	 * Move to system cached
 	 */
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index d35bc49..5e1bcab 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -48,9 +48,7 @@ static void ttm_eu_del_from_lru_locked(struct list_head *list)
 
 	list_for_each_entry(entry, list, head) {
 		struct ttm_buffer_object *bo = entry->bo;
-		unsigned put_count = ttm_bo_del_from_lru(bo);
-
-		ttm_bo_list_ref_sub(bo, put_count, true);
+		ttm_bo_del_from_lru(bo);
 	}
 }
 
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index 652e45b..9a46531 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -332,19 +332,6 @@ extern int ttm_bo_validate(struct ttm_buffer_object *bo,
  */
 extern void ttm_bo_unref(struct ttm_buffer_object **bo);
 
-
-/**
- * ttm_bo_list_ref_sub
- *
- * @bo: The buffer object.
- * @count: The number of references with which to decrease @bo::list_kref;
- * @never_free: The refcount should not reach zero with this operation.
- *
- * Release @count lru list references to this buffer object.
- */
-extern void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count,
-				bool never_free);
-
 /**
  * ttm_bo_add_to_lru
  *
@@ -367,7 +354,7 @@ extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);
  * and is usually called just immediately after the bo has been reserved to
  * avoid recursive reservation from lru lists.
  */
-extern int ttm_bo_del_from_lru(struct ttm_buffer_object *bo);
+extern void ttm_bo_del_from_lru(struct ttm_buffer_object *bo);
 
 /**
  * ttm_bo_move_to_lru_tail
diff --git a/include/linux/kref.h b/include/linux/kref.h
index 7c88d86..31c49a6 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -54,9 +54,8 @@ static inline void kref_get(struct kref *kref)
 }
 
 /**
- * kref_sub - subtract a number of refcounts for object.
+ * kref_put - decrement refcount for object.
  * @kref: object.
- * @count: Number of recounts to subtract.
  * @release: pointer to the function that will clean up the object when the
  *	     last reference to the object is released.
  *	     This pointer is required, and it is not acceptable to pass kfree
@@ -65,46 +64,23 @@ static inline void kref_get(struct kref *kref)
  *	     maintainer, and anyone else who happens to notice it.  You have
  *	     been warned.
  *
- * Subtract @count from the refcount, and if 0, call release().
+ * Decrement the refcount, and if 0, call release().
  * Return 1 if the object was removed, otherwise return 0.  Beware, if this
  * function returns 0, you still can not count on the kref from remaining in
  * memory.  Only use the return value if you want to see if the kref is now
  * gone, not present.
  */
-static inline int kref_sub(struct kref *kref, unsigned int count,
-	     void (*release)(struct kref *kref))
+static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
 {
 	WARN_ON(release == NULL);
 
-	if (atomic_sub_and_test((int) count, &kref->refcount)) {
+	if (atomic_dec_and_test(&kref->refcount)) {
 		release(kref);
 		return 1;
 	}
 	return 0;
 }
 
-/**
- * kref_put - decrement refcount for object.
- * @kref: object.
- * @release: pointer to the function that will clean up the object when the
- *	     last reference to the object is released.
- *	     This pointer is required, and it is not acceptable to pass kfree
- *	     in as this function.  If the caller does pass kfree to this
- *	     function, you will be publicly mocked mercilessly by the kref
- *	     maintainer, and anyone else who happens to notice it.  You have
- *	     been warned.
- *
- * Decrement the refcount, and if 0, call release().
- * Return 1 if the object was removed, otherwise return 0.  Beware, if this
- * function returns 0, you still can not count on the kref from remaining in
- * memory.  Only use the return value if you want to see if the kref is now
- * gone, not present.
- */
-static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
-{
-	return kref_sub(kref, 1, release);
-}
-
 static inline int kref_put_mutex(struct kref *kref,
 				 void (*release)(struct kref *kref),
 				 struct mutex *lock)
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 04/18] kref: Use kref_get_unless_zero() more
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (2 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 03/18] kref: Kill kref_sub() Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 05/18] kref: Implement kref_put_lock() Elena Reshetova
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh

From: Peter Zijlstra <peterz@infradead.org>

For some obscure reason apparmor thinks its needs to locally implement
kref primitives that already exist. Stop doing this.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 security/apparmor/include/apparmor.h | 6 ------
 security/apparmor/include/policy.h   | 4 ++--
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 5d721e9..f067be8 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -78,12 +78,6 @@ static inline void *kvzalloc(size_t size)
 	return __aa_kvmalloc(size, __GFP_ZERO);
 }
 
-/* returns 0 if kref not incremented */
-static inline int kref_get_not0(struct kref *kref)
-{
-	return atomic_inc_not_zero(&kref->refcount);
-}
-
 /**
  * aa_strneq - compare null terminated @str to a non null terminated substring
  * @str: a null terminated string
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 52275f0..46467aa 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -287,7 +287,7 @@ static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
  */
 static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
 {
-	if (p && kref_get_not0(&p->count))
+	if (p && kref_get_unless_zero(&p->count))
 		return p;
 
 	return NULL;
@@ -307,7 +307,7 @@ static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
 	rcu_read_lock();
 	do {
 		c = rcu_dereference(*p);
-	} while (c && !kref_get_not0(&c->count));
+	} while (c && !kref_get_unless_zero(&c->count));
 	rcu_read_unlock();
 
 	return c;
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 05/18] kref: Implement kref_put_lock()
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (3 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 04/18] kref: Use kref_get_unless_zero() more Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 06/18] kref: Avoid more abuse Elena Reshetova
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh

From: Peter Zijlstra <peterz@infradead.org>

Because home-rolling your own is _awesome_, stop doing it. Provide
kref_put_lock(), just like kref_put_mutex() but for a spinlock.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/kref.h | 21 +++++++++++++++------
 net/sunrpc/svcauth.c | 15 ++++++++++-----
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/include/linux/kref.h b/include/linux/kref.h
index 31c49a6..aef7e19 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -86,12 +86,21 @@ static inline int kref_put_mutex(struct kref *kref,
 				 struct mutex *lock)
 {
 	WARN_ON(release == NULL);
-	if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) {
-		mutex_lock(lock);
-		if (unlikely(!atomic_dec_and_test(&kref->refcount))) {
-			mutex_unlock(lock);
-			return 0;
-		}
+
+	if (atomic_dec_and_mutex_lock(&kref->refcount, lock)) {
+		release(kref);
+		return 1;
+	}
+	return 0;
+}
+
+static inline int kref_put_lock(struct kref *kref,
+				void (*release)(struct kref *kref),
+				spinlock_t *lock)
+{
+	WARN_ON(release == NULL);
+
+	if (atomic_dec_and_lock(&kref->refcount, lock)) {
 		release(kref);
 		return 1;
 	}
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index e112da8..bb8db3c 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -126,13 +126,18 @@ EXPORT_SYMBOL_GPL(svc_auth_unregister);
 static struct hlist_head	auth_domain_table[DN_HASHMAX];
 static DEFINE_SPINLOCK(auth_domain_lock);
 
+static void auth_domain_release(struct kref *kref)
+{
+	struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
+
+	hlist_del(&dom->hash);
+	dom->flavour->domain_release(dom);
+	spin_unlock(&auth_domain_lock);
+}
+
 void auth_domain_put(struct auth_domain *dom)
 {
-	if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
-		hlist_del(&dom->hash);
-		dom->flavour->domain_release(dom);
-		spin_unlock(&auth_domain_lock);
-	}
+	kref_put_lock(&dom->ref, auth_domain_release, &auth_domain_lock);
 }
 EXPORT_SYMBOL_GPL(auth_domain_put);
 
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 06/18] kref: Avoid more abuse
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (4 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 05/18] kref: Implement kref_put_lock() Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 07/18] kref: Implement using refcount_t Elena Reshetova
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh

From: Peter Zijlstra <peterz@infradead.org>

Leak references by unbalanced get, instead of poking at kref
implementation details.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/usb/mon/mon_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 33ff49c..4684734 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -409,7 +409,7 @@ static void __exit mon_exit(void)
 			printk(KERN_ERR TAG
 			    ": Outstanding opens (%d) on usb%d, leaking...\n",
 			    mbus->nreaders, mbus->u_bus->busnum);
-			atomic_set(&mbus->ref.refcount, 2);	/* Force leak */
+			kref_get(&mbus->ref); /* Force leak */
 		}
 
 		mon_dissolve(mbus, mbus->u_bus);
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 07/18] kref: Implement using refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (5 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 06/18] kref: Avoid more abuse Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 08/18] kernel, mm: convert from atomic_t to refcount_t Elena Reshetova
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh

From: Peter Zijlstra <peterz@infradead.org>

Provide refcount_t, an atomic_t like primitive built just for refcounting.

It provides saturation semantics such that overflow becomes impossible and
thereby 'spurious' use-after-free is avoided.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/kref.h     |  23 ++---
 include/linux/refcount.h | 262 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 272 insertions(+), 13 deletions(-)
 create mode 100644 include/linux/refcount.h

diff --git a/include/linux/kref.h b/include/linux/kref.h
index aef7e19..78f840a 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -19,12 +19,13 @@
 #include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 
 struct kref {
-	atomic_t refcount;
+	refcount_t refcount;
 };
 
-#define KREF_INIT(n)	{ .refcount = ATOMIC_INIT(n), }
+#define KREF_INIT(n)	{ .refcount = REFCOUNT_INIT(n), }
 
 /**
  * kref_init - initialize object.
@@ -32,12 +33,12 @@ struct kref {
  */
 static inline void kref_init(struct kref *kref)
 {
-	atomic_set(&kref->refcount, 1);
+	refcount_set(&kref->refcount, 1);
 }
 
 static inline int kref_read(const struct kref *kref)
 {
-	return atomic_read(&kref->refcount);
+	return refcount_read(&kref->refcount);
 }
 
 /**
@@ -46,11 +47,7 @@ static inline int kref_read(const struct kref *kref)
  */
 static inline void kref_get(struct kref *kref)
 {
-	/* If refcount was 0 before incrementing then we have a race
-	 * condition when this kref is freeing by some other thread right now.
-	 * In this case one should use kref_get_unless_zero()
-	 */
-	WARN_ON_ONCE(atomic_inc_return(&kref->refcount) < 2);
+	refcount_inc(&kref->refcount);
 }
 
 /**
@@ -74,7 +71,7 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)
 {
 	WARN_ON(release == NULL);
 
-	if (atomic_dec_and_test(&kref->refcount)) {
+	if (refcount_dec_and_test(&kref->refcount)) {
 		release(kref);
 		return 1;
 	}
@@ -87,7 +84,7 @@ static inline int kref_put_mutex(struct kref *kref,
 {
 	WARN_ON(release == NULL);
 
-	if (atomic_dec_and_mutex_lock(&kref->refcount, lock)) {
+	if (refcount_dec_and_mutex_lock(&kref->refcount, lock)) {
 		release(kref);
 		return 1;
 	}
@@ -100,7 +97,7 @@ static inline int kref_put_lock(struct kref *kref,
 {
 	WARN_ON(release == NULL);
 
-	if (atomic_dec_and_lock(&kref->refcount, lock)) {
+	if (refcount_dec_and_lock(&kref->refcount, lock)) {
 		release(kref);
 		return 1;
 	}
@@ -125,6 +122,6 @@ static inline int kref_put_lock(struct kref *kref,
  */
 static inline int __must_check kref_get_unless_zero(struct kref *kref)
 {
-	return atomic_add_unless(&kref->refcount, 1, 0);
+	return refcount_inc_not_zero(&kref->refcount);
 }
 #endif /* _KREF_H_ */
diff --git a/include/linux/refcount.h b/include/linux/refcount.h
new file mode 100644
index 0000000..fc5abdb
--- /dev/null
+++ b/include/linux/refcount.h
@@ -0,0 +1,262 @@
+#ifndef _LINUX_REFCOUNT_H
+#define _LINUX_REFCOUNT_H
+
+/*
+ * Variant of atomic_t specialized for reference counts.
+ *
+ * The interface matches the atomic_t interface (to aid in porting) but only
+ * provides the few functions one should use for reference counting.
+ *
+ * It differs in that the counter saturates at UINT_MAX and will not move once
+ * there. This avoids wrapping the counter and causing 'spurious'
+ * use-after-free issues.
+ *
+ * Memory ordering rules are slightly relaxed wrt regular atomic_t functions
+ * and provide only what is strictly required for refcounts.
+ *
+ * The increments are fully relaxed; these will not provide ordering. The
+ * rationale is that whatever is used to obtain the object we're increasing the
+ * reference count on will provide the ordering. For locked data structures,
+ * its the lock acquire, for RCU/lockless data structures its the dependent
+ * load.
+ *
+ * Do note that inc_not_zero() provides a control dependency which will order
+ * future stores against the inc, this ensures we'll never modify the object
+ * if we did not in fact acquire a reference.
+ *
+ * The decrements will provide release order, such that all the prior loads and
+ * stores will be issued before, it also provides a control dependency, which
+ * will order us against the subsequent free().
+ *
+ * The control dependency is against the load of the cmpxchg (ll/sc) that
+ * succeeded. This means the stores aren't fully ordered, but this is fine
+ * because the 1->0 transition indicates no concurrency.
+ *
+ * Note that the allocator is responsible for ordering things between free()
+ * and alloc().
+ *
+ */
+
+#include <linux/atomic.h>
+#include <linux/bug.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+typedef struct refcount_struct {
+       atomic_t refs;
+} refcount_t;
+
+#define REFCOUNT_INIT(n)       { .refs = ATOMIC_INIT(n), }
+
+static inline void refcount_set(refcount_t *r, unsigned int n)
+{
+       atomic_set(&r->refs, n);
+}
+
+static inline unsigned int refcount_read(const refcount_t *r)
+{
+       return atomic_read(&r->refs);
+}
+
+static inline __must_check
+bool refcount_add_not_zero(unsigned int i, refcount_t *r)
+{
+       unsigned int old, new, val = atomic_read(&r->refs);
+
+       for (;;) {
+               if (!val)
+                       return false;
+
+               if (unlikely(val == UINT_MAX))
+                       return true;
+
+               new = val + i;
+               if (new < val)
+                       new = UINT_MAX;
+               old = atomic_cmpxchg_relaxed(&r->refs, val, new);
+               if (old == val)
+                       break;
+
+               val = old;
+       }
+
+       WARN(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n");
+
+       return true;
+}
+
+/*
+ * Similar to atomic_inc_not_zero(), will saturate at UINT_MAX and WARN.
+ *
+ * Provides no memory ordering, it is assumed the caller has guaranteed the
+ * object memory to be stable (RCU, etc.). It does provide a control dependency
+ * and thereby orders future stores. See the comment on top.
+ */
+static inline __must_check
+bool refcount_inc_not_zero(refcount_t *r)
+{
+       return refcount_add_not_zero(1, r);
+}
+
+/*
+ * Similar to atomic_inc(), will saturate at UINT_MAX and WARN.
+ *
+ * Provides no memory ordering, it is assumed the caller already has a
+ * reference on the object, will WARN when this is not so.
+ */
+static inline void refcount_inc(refcount_t *r)
+{
+       WARN(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n");
+}
+
+static inline void refcount_add(unsigned int i, refcount_t *r)
+{
+       WARN(!refcount_add_not_zero(i, r), "refcount_t: addition on 0; use-after-free.\n");
+}
+
+/*
+ * Similar to atomic_dec_and_test(), it will WARN on underflow and fail to
+ * decrement when saturated at UINT_MAX.
+ *
+ * Provides release memory ordering, such that prior loads and stores are done
+ * before, and provides a control dependency such that free() must come after.
+ * See the comment on top.
+ */
+static inline __must_check
+bool refcount_sub_and_test(unsigned int i, refcount_t *r)
+{
+       unsigned int old, new, val = atomic_read(&r->refs);
+
+       for (;;) {
+               if (val == UINT_MAX)
+                       return false;
+
+               new = val - i;
+               if (WARN(new > val, "refcount_t: underflow; use-after-free.\n"))
+                       return false;
+
+               old = atomic_cmpxchg_release(&r->refs, val, new);
+               if (old == val)
+                       break;
+
+               val = old;
+       }
+
+       return !new;
+}
+
+static inline __must_check
+bool refcount_dec_and_test(refcount_t *r)
+{
+       return refcount_sub_and_test(1, r);
+}
+
+/*
+ * Similar to atomic_dec(), it will WARN on underflow and fail to decrement
+ * when saturated at UINT_MAX.
+ *
+ * Provides release memory ordering, such that prior loads and stores are done
+ * before.
+ */
+static inline
+void refcount_dec(refcount_t *r)
+{
+       WARN(refcount_dec_and_test(r), "refcount_t: decrement hit 0; leaking memory.\n");
+}
+
+/*
+ * No atomic_t counterpart, it attempts a 1 -> 0 transition and returns the
+ * success thereof.
+ *
+ * Like all decrement operations, it provides release memory order and provides
+ * a control dependency.
+ *
+ * It can be used like a try-delete operator; this explicit case is provided
+ * and not cmpxchg in generic, because that would allow implementing unsafe
+ * operations.
+ */
+static inline __must_check
+bool refcount_dec_if_one(refcount_t *r)
+{
+       return atomic_cmpxchg_release(&r->refs, 1, 0) == 1;
+}
+
+/*
+ * No atomic_t counterpart, it decrements unless the value is 1, in which case
+ * it will return false.
+ *
+ * Was often done like: atomic_add_unless(&var, -1, 1)
+ */
+static inline __must_check
+bool refcount_dec_not_one(refcount_t *r)
+{
+       unsigned int old, new, val = atomic_read(&r->refs);
+
+       for (;;) {
+               if (val == UINT_MAX)
+                       return true;
+
+               if (val == 1)
+                       return false;
+
+               new = val - 1;
+               if (WARN(new > val, "refcount_t: underflow; use-after-free.\n"))
+                       return true;
+
+               old = atomic_cmpxchg_release(&r->refs, val, new);
+               if (old == val)
+                       break;
+
+               val = old;
+       }
+
+       return true;
+}
+
+/*
+ * Similar to atomic_dec_and_mutex_lock(), it will WARN on underflow and fail
+ * to decrement when saturated at UINT_MAX.
+ *
+ * Provides release memory ordering, such that prior loads and stores are done
+ * before, and provides a control dependency such that free() must come after.
+ * See the comment on top.
+ */
+static inline __must_check
+bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock)
+{
+       if (refcount_dec_not_one(r))
+               return false;
+
+       mutex_lock(lock);
+       if (!refcount_dec_and_test(r)) {
+               mutex_unlock(lock);
+               return false;
+       }
+
+       return true;
+}
+
+/*
+ * Similar to atomic_dec_and_lock(), it will WARN on underflow and fail to
+ * decrement when saturated at UINT_MAX.
+ *
+ * Provides release memory ordering, such that prior loads and stores are done
+ * before, and provides a control dependency such that free() must come after.
+ * See the comment on top.
+ */
+static inline __must_check
+bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock)
+{
+       if (refcount_dec_not_one(r))
+               return false;
+
+       spin_lock(lock);
+       if (!refcount_dec_and_test(r)) {
+               spin_unlock(lock);
+               return false;
+       }
+
+       return true;
+}
+
+#endif /* _LINUX_REFCOUNT_H */
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 08/18] kernel, mm: convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (6 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 07/18] kref: Implement using refcount_t Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 09/18] net: " Elena Reshetova
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/alpha/kernel/smp.c                 |  6 ++---
 arch/arc/kernel/smp.c                   |  2 +-
 arch/arc/mm/tlb.c                       |  2 +-
 arch/arm/kernel/smp.c                   |  2 +-
 arch/arm64/kernel/smp.c                 |  2 +-
 arch/blackfin/mach-common/smp.c         |  4 +--
 arch/frv/mm/mmu-context.c               |  2 +-
 arch/ia64/include/asm/tlbflush.h        |  2 +-
 arch/ia64/kernel/smp.c                  |  2 +-
 arch/ia64/sn/kernel/sn2/sn2_smp.c       |  4 +--
 arch/metag/kernel/smp.c                 |  2 +-
 arch/mips/kernel/process.c              |  2 +-
 arch/mips/kernel/smp.c                  |  6 ++---
 arch/parisc/include/asm/mmu_context.h   |  2 +-
 arch/powerpc/mm/hugetlbpage.c           |  2 +-
 arch/powerpc/mm/icswx.c                 |  4 +--
 arch/s390/include/asm/debug.h           |  3 ++-
 arch/s390/kernel/debug.c                |  6 ++---
 arch/sh/kernel/smp.c                    |  8 +++---
 arch/sparc/kernel/mdesc.c               | 17 ++++++------
 arch/sparc/kernel/smp_64.c              |  6 ++---
 arch/sparc/mm/srmmu.c                   |  2 +-
 arch/um/kernel/tlb.c                    |  2 +-
 arch/x86/include/asm/amd_nb.h           |  3 ++-
 arch/x86/kernel/cpu/common.c            |  4 +--
 arch/x86/kernel/cpu/mcheck/mce_amd.c    |  6 ++---
 arch/x86/kernel/tboot.c                 |  4 +--
 arch/xtensa/kernel/smp.c                |  2 +-
 drivers/firmware/efi/arm-runtime.c      |  4 +--
 drivers/gpu/drm/i915/i915_gem_userptr.c |  4 +--
 drivers/iommu/intel-svm.c               |  2 +-
 fs/coredump.c                           |  2 +-
 fs/exec.c                               |  4 +--
 fs/proc/base.c                          | 10 +++----
 fs/proc/task_mmu.c                      |  4 +--
 fs/proc/task_nommu.c                    |  2 +-
 fs/userfaultfd.c                        |  2 +-
 include/linux/backing-dev-defs.h        |  3 ++-
 include/linux/backing-dev.h             |  4 +--
 include/linux/cgroup-defs.h             |  3 ++-
 include/linux/cgroup.h                  |  7 ++---
 include/linux/cred.h                    | 13 +++++-----
 include/linux/init_task.h               |  7 ++---
 include/linux/kvm_host.h                |  3 ++-
 include/linux/mm_types.h                |  5 ++--
 include/linux/nsproxy.h                 |  6 ++---
 include/linux/perf_event.h              |  3 ++-
 include/linux/rmap.h                    |  7 ++---
 include/linux/sched.h                   | 25 +++++++++---------
 kernel/audit_tree.c                     | 10 +++----
 kernel/audit_watch.c                    |  8 +++---
 kernel/cgroup.c                         | 23 ++++++++++-------
 kernel/cred.c                           | 46 ++++++++++++++++-----------------
 kernel/events/core.c                    | 16 ++++++------
 kernel/events/internal.h                |  5 ++--
 kernel/events/ring_buffer.c             |  8 +++---
 kernel/events/uprobes.c                 | 13 +++++-----
 kernel/exit.c                           |  4 +--
 kernel/fork.c                           | 40 ++++++++++++++--------------
 kernel/futex.c                          | 17 ++++++------
 kernel/groups.c                         |  2 +-
 kernel/kcov.c                           |  9 ++++---
 kernel/nsproxy.c                        |  6 ++---
 kernel/sched/core.c                     |  7 ++---
 kernel/sched/fair.c                     |  8 +++---
 kernel/user.c                           |  8 +++---
 lib/is_single_threaded.c                |  2 +-
 mm/backing-dev.c                        | 11 ++++----
 mm/debug.c                              |  4 +--
 mm/huge_memory.c                        | 16 +++++++-----
 mm/init-mm.c                            |  4 +--
 mm/khugepaged.c                         |  4 +--
 mm/kmemleak.c                           | 16 ++++++------
 mm/ksm.c                                |  4 +--
 mm/memory.c                             |  2 +-
 mm/mmu_context.c                        |  2 +-
 mm/mmu_notifier.c                       | 12 ++++-----
 mm/mprotect.c                           |  2 +-
 mm/oom_kill.c                           |  6 ++---
 mm/rmap.c                               | 14 +++++-----
 mm/swapfile.c                           | 14 +++++-----
 mm/vmacache.c                           |  2 +-
 mm/zpool.c                              |  4 +--
 net/sunrpc/auth_null.c                  |  2 +-
 virt/kvm/async_pf.c                     |  2 +-
 virt/kvm/kvm_main.c                     | 10 +++----
 86 files changed, 309 insertions(+), 283 deletions(-)

diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 46bf263..cc5aa0a 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -653,7 +653,7 @@ flush_tlb_mm(struct mm_struct *mm)
 
 	if (mm == current->active_mm) {
 		flush_tlb_current(mm);
-		if (atomic_read(&mm->mm_users) <= 1) {
+		if (refcount_read(&mm->mm_users) <= 1) {
 			int cpu, this_cpu = smp_processor_id();
 			for (cpu = 0; cpu < NR_CPUS; cpu++) {
 				if (!cpu_online(cpu) || cpu == this_cpu)
@@ -702,7 +702,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
 
 	if (mm == current->active_mm) {
 		flush_tlb_current_page(mm, vma, addr);
-		if (atomic_read(&mm->mm_users) <= 1) {
+		if (refcount_read(&mm->mm_users) <= 1) {
 			int cpu, this_cpu = smp_processor_id();
 			for (cpu = 0; cpu < NR_CPUS; cpu++) {
 				if (!cpu_online(cpu) || cpu == this_cpu)
@@ -758,7 +758,7 @@ flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 
 	if (mm == current->active_mm) {
 		__load_new_mm_context(mm);
-		if (atomic_read(&mm->mm_users) <= 1) {
+		if (refcount_read(&mm->mm_users) <= 1) {
 			int cpu, this_cpu = smp_processor_id();
 			for (cpu = 0; cpu < NR_CPUS; cpu++) {
 				if (!cpu_online(cpu) || cpu == this_cpu)
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 88674d9..8e22594 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -124,7 +124,7 @@ void start_kernel_secondary(void)
 	/* MMU, Caches, Vector Table, Interrupts etc */
 	setup_processor();
 
-	atomic_inc(&mm->mm_users);
+	refcount_inc(&mm->mm_users);
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index bdb295e..6dbdfe7 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -297,7 +297,7 @@ noinline void local_flush_tlb_mm(struct mm_struct *mm)
 	 * Only for fork( ) do we need to move parent to a new MMU ctxt,
 	 * all other cases are NOPs, hence this check.
 	 */
-	if (atomic_read(&mm->mm_users) == 0)
+	if (refcount_read(&mm->mm_users) == 0)
 		return;
 
 	/*
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 7dd14e8..1d59aca 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -371,7 +371,7 @@ asmlinkage void secondary_start_kernel(void)
 	 * reference and switch to it.
 	 */
 	cpu = smp_processor_id();
-	atomic_inc(&mm->mm_count);
+	refcount_inc(&mm->mm_count);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
 
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index cb87234..fa43f21 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -222,7 +222,7 @@ asmlinkage void secondary_start_kernel(void)
 	 * All kernel threads share the same mm context; grab a
 	 * reference and switch to it.
 	 */
-	atomic_inc(&mm->mm_count);
+	refcount_inc(&mm->mm_count);
 	current->active_mm = mm;
 
 	/*
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 23c4ef5..d90422d 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -307,7 +307,7 @@ void secondary_start_kernel(void)
 	local_irq_disable();
 
 	/* Attach the new idle task to the global mm. */
-	atomic_inc(&mm->mm_users);
+	refcount_inc(&mm->mm_users);
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 
@@ -422,7 +422,7 @@ void cpu_die(void)
 {
 	(void)cpu_report_death();
 
-	atomic_dec(&init_mm.mm_users);
+	refcount_dec(&init_mm.mm_users);
 	atomic_dec(&init_mm.mm_count);
 
 	local_irq_disable();
diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c
index 81757d5..128cfd6 100644
--- a/arch/frv/mm/mmu-context.c
+++ b/arch/frv/mm/mmu-context.c
@@ -188,7 +188,7 @@ int cxn_pin_by_pid(pid_t pid)
 		task_lock(tsk);
 		if (tsk->mm) {
 			mm = tsk->mm;
-			atomic_inc(&mm->mm_users);
+			refcount_inc(&mm->mm_users);
 			ret = 0;
 		}
 		task_unlock(tsk);
diff --git a/arch/ia64/include/asm/tlbflush.h b/arch/ia64/include/asm/tlbflush.h
index 3be25df..650708a 100644
--- a/arch/ia64/include/asm/tlbflush.h
+++ b/arch/ia64/include/asm/tlbflush.h
@@ -56,7 +56,7 @@ flush_tlb_mm (struct mm_struct *mm)
 	set_bit(mm->context, ia64_ctx.flushmap);
 	mm->context = 0;
 
-	if (atomic_read(&mm->mm_users) == 0)
+	if (refcount_read(&mm->mm_users) == 0)
 		return;		/* happens as a result of exit_mmap() */
 
 #ifdef CONFIG_SMP
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 7f706d4..dd7b680 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -295,7 +295,7 @@ smp_flush_tlb_mm (struct mm_struct *mm)
 	cpumask_var_t cpus;
 	preempt_disable();
 	/* this happens for the common case of a single-threaded fork():  */
-	if (likely(mm == current->active_mm && atomic_read(&mm->mm_users) == 1))
+	if (likely(mm == current->active_mm && refcount_read(&mm->mm_users) == 1))
 	{
 		local_finish_flush_tlb_mm(mm);
 		preempt_enable();
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index c98dc96..1c801b3 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -122,7 +122,7 @@ void sn_migrate(struct task_struct *task)
 void sn_tlb_migrate_finish(struct mm_struct *mm)
 {
 	/* flush_tlb_mm is inefficient if more than 1 users of mm */
-	if (mm == current->mm && mm && atomic_read(&mm->mm_users) == 1)
+	if (mm == current->mm && mm && refcount_read(&mm->mm_users) == 1)
 		flush_tlb_mm(mm);
 }
 
@@ -204,7 +204,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
 		return;
 	}
 
-	if (atomic_read(&mm->mm_users) == 1 && mymm) {
+	if (refcount_read(&mm->mm_users) == 1 && mymm) {
 		flush_tlb_mm(mm);
 		__this_cpu_inc(ptcstats.change_rid);
 		preempt_enable();
diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c
index bad1323..5a9835b 100644
--- a/arch/metag/kernel/smp.c
+++ b/arch/metag/kernel/smp.c
@@ -344,7 +344,7 @@ asmlinkage void secondary_start_kernel(void)
 	 * All kernel threads share the same mm context; grab a
 	 * reference and switch to it.
 	 */
-	atomic_inc(&mm->mm_users);
+	refcount_inc(&mm->mm_users);
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 5142b1d..c0143d9 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -642,7 +642,7 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 		/* No need to send an IPI for the local CPU */
 		max_users = (task->mm == current->mm) ? 1 : 0;
 
-		if (atomic_read(&current->mm->mm_users) > max_users)
+		if (refcount_read(&current->mm->mm_users) > max_users)
 			smp_call_function(prepare_for_fp_mode_switch,
 					  (void *)current->mm, 1);
 	}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 7ebb191..9017ff3 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -510,7 +510,7 @@ void flush_tlb_mm(struct mm_struct *mm)
 {
 	preempt_disable();
 
-	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
+	if ((refcount_read(&mm->mm_users) != 1) || (current->mm != mm)) {
 		smp_on_other_tlbs(flush_tlb_mm_ipi, mm);
 	} else {
 		unsigned int cpu;
@@ -543,7 +543,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned l
 	struct mm_struct *mm = vma->vm_mm;
 
 	preempt_disable();
-	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
+	if ((refcount_read(&mm->mm_users) != 1) || (current->mm != mm)) {
 		struct flush_tlb_data fd = {
 			.vma = vma,
 			.addr1 = start,
@@ -597,7 +597,7 @@ static void flush_tlb_page_ipi(void *info)
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
 	preempt_disable();
-	if ((atomic_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) {
+	if ((refcount_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) {
 		struct flush_tlb_data fd = {
 			.vma = vma,
 			.addr1 = page,
diff --git a/arch/parisc/include/asm/mmu_context.h b/arch/parisc/include/asm/mmu_context.h
index 59be257..e64f398 100644
--- a/arch/parisc/include/asm/mmu_context.h
+++ b/arch/parisc/include/asm/mmu_context.h
@@ -21,7 +21,7 @@ extern void free_sid(unsigned long);
 static inline int
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
-	BUG_ON(atomic_read(&mm->mm_users) != 1);
+	BUG_ON(refcount_read(&mm->mm_users) != 1);
 
 	mm->context = alloc_sid();
 	return 0;
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 289df38..f3db57b 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -403,7 +403,7 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
 
 	batchp = &get_cpu_var(hugepd_freelist_cur);
 
-	if (atomic_read(&tlb->mm->mm_users) < 2 ||
+	if (refcount_read(&tlb->mm->mm_users) < 2 ||
 	    cpumask_equal(mm_cpumask(tlb->mm),
 			  cpumask_of(smp_processor_id()))) {
 		kmem_cache_free(hugepte_cache, hugepte);
diff --git a/arch/powerpc/mm/icswx.c b/arch/powerpc/mm/icswx.c
index 915412e..2406ff8 100644
--- a/arch/powerpc/mm/icswx.c
+++ b/arch/powerpc/mm/icswx.c
@@ -110,7 +110,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm)
 	 * running. We need to send an IPI to force them to pick up any
 	 * change in PID and ACOP.
 	 */
-	if (atomic_read(&mm->mm_users) > 1)
+	if (refcount_read(&mm->mm_users) > 1)
 		smp_call_function(sync_cop, mm, 1);
 
 out:
@@ -150,7 +150,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm)
 	 * running. We need to send an IPI to force them to pick up any
 	 * change in PID and ACOP.
 	 */
-	if (atomic_read(&mm->mm_users) > 1)
+	if (refcount_read(&mm->mm_users) > 1)
 		smp_call_function(sync_cop, mm, 1);
 
 	if (free_pid != COP_PID_NONE)
diff --git a/arch/s390/include/asm/debug.h b/arch/s390/include/asm/debug.h
index 0206c80..df7b54e 100644
--- a/arch/s390/include/asm/debug.h
+++ b/arch/s390/include/asm/debug.h
@@ -10,6 +10,7 @@
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
+#include <linux/refcount.h>
 #include <uapi/asm/debug.h>
 
 #define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
@@ -31,7 +32,7 @@ struct debug_view;
 typedef struct debug_info {	
 	struct debug_info* next;
 	struct debug_info* prev;
-	atomic_t ref_count;
+	refcount_t ref_count;
 	spinlock_t lock;			
 	int level;
 	int nr_areas;
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 79f8ae9..c563d9f 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -277,7 +277,7 @@ debug_info_alloc(const char *name, int pages_per_area, int nr_areas,
 	memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
 	memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
 		sizeof(struct dentry*));
-	atomic_set(&(rc->ref_count), 0);
+	refcount_set(&(rc->ref_count), 0);
 
 	return rc;
 
@@ -416,7 +416,7 @@ static void
 debug_info_get(debug_info_t * db_info)
 {
 	if (db_info)
-		atomic_inc(&db_info->ref_count);
+		refcount_inc(&db_info->ref_count);
 }
 
 /*
@@ -431,7 +431,7 @@ debug_info_put(debug_info_t *db_info)
 
 	if (!db_info)
 		return;
-	if (atomic_dec_and_test(&db_info->ref_count)) {
+	if (refcount_dec_and_test(&db_info->ref_count)) {
 		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
 			if (!db_info->views[i])
 				continue;
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index 38e7860..f0aabeb 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -179,7 +179,7 @@ asmlinkage void start_secondary(void)
 
 	enable_mmu();
 	atomic_inc(&mm->mm_count);
-	atomic_inc(&mm->mm_users);
+	refcount_inc(&mm->mm_users);
 	current->active_mm = mm;
 #ifdef CONFIG_MMU
 	enter_lazy_tlb(mm, current);
@@ -363,7 +363,7 @@ void flush_tlb_mm(struct mm_struct *mm)
 {
 	preempt_disable();
 
-	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
+	if ((refcount_read(&mm->mm_users) != 1) || (current->mm != mm)) {
 		smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1);
 	} else {
 		int i;
@@ -395,7 +395,7 @@ void flush_tlb_range(struct vm_area_struct *vma,
 	struct mm_struct *mm = vma->vm_mm;
 
 	preempt_disable();
-	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
+	if ((refcount_read(&mm->mm_users) != 1) || (current->mm != mm)) {
 		struct flush_tlb_data fd;
 
 		fd.vma = vma;
@@ -438,7 +438,7 @@ static void flush_tlb_page_ipi(void *info)
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
 	preempt_disable();
-	if ((atomic_read(&vma->vm_mm->mm_users) != 1) ||
+	if ((refcount_read(&vma->vm_mm->mm_users) != 1) ||
 	    (current->mm != vma->vm_mm)) {
 		struct flush_tlb_data fd;
 
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index c0765bb..ac3fe0d 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -12,6 +12,7 @@
 #include <linux/miscdevice.h>
 #include <linux/bootmem.h>
 #include <linux/export.h>
+#include <linux/refcount.h>
 
 #include <asm/cpudata.h>
 #include <asm/hypervisor.h>
@@ -70,7 +71,7 @@ struct mdesc_handle {
 	struct list_head	list;
 	struct mdesc_mem_ops	*mops;
 	void			*self_base;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	unsigned int		handle_size;
 	struct mdesc_hdr	mdesc;
 };
@@ -84,7 +85,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
 	memset(hp, 0, handle_size);
 	INIT_LIST_HEAD(&hp->list);
 	hp->self_base = base;
-	atomic_set(&hp->refcnt, 1);
+	refcount_set(&hp->refcnt, 1);
 	hp->handle_size = handle_size;
 }
 
@@ -114,7 +115,7 @@ static void __init mdesc_memblock_free(struct mdesc_handle *hp)
 	unsigned int alloc_size;
 	unsigned long start;
 
-	BUG_ON(atomic_read(&hp->refcnt) != 0);
+	BUG_ON(refcount_read(&hp->refcnt) != 0);
 	BUG_ON(!list_empty(&hp->list));
 
 	alloc_size = PAGE_ALIGN(hp->handle_size);
@@ -154,7 +155,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
 
 static void mdesc_kfree(struct mdesc_handle *hp)
 {
-	BUG_ON(atomic_read(&hp->refcnt) != 0);
+	BUG_ON(refcount_read(&hp->refcnt) != 0);
 	BUG_ON(!list_empty(&hp->list));
 
 	kfree(hp->self_base);
@@ -193,7 +194,7 @@ struct mdesc_handle *mdesc_grab(void)
 	spin_lock_irqsave(&mdesc_lock, flags);
 	hp = cur_mdesc;
 	if (hp)
-		atomic_inc(&hp->refcnt);
+		refcount_inc(&hp->refcnt);
 	spin_unlock_irqrestore(&mdesc_lock, flags);
 
 	return hp;
@@ -205,7 +206,7 @@ void mdesc_release(struct mdesc_handle *hp)
 	unsigned long flags;
 
 	spin_lock_irqsave(&mdesc_lock, flags);
-	if (atomic_dec_and_test(&hp->refcnt)) {
+	if (refcount_dec_and_test(&hp->refcnt)) {
 		list_del_init(&hp->list);
 		hp->mops->free(hp);
 	}
@@ -344,7 +345,7 @@ void mdesc_update(void)
 	if (status != HV_EOK || real_len > len) {
 		printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
 		       status);
-		atomic_dec(&hp->refcnt);
+		refcount_dec(&hp->refcnt);
 		mdesc_free(hp);
 		goto out;
 	}
@@ -357,7 +358,7 @@ void mdesc_update(void)
 	mdesc_notify_clients(orig_hp, hp);
 
 	spin_lock_irqsave(&mdesc_lock, flags);
-	if (atomic_dec_and_test(&orig_hp->refcnt))
+	if (refcount_dec_and_test(&orig_hp->refcnt))
 		mdesc_free(orig_hp);
 	else
 		list_add(&orig_hp->list, &mdesc_zombie_list);
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 0ce347f..92de6df 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1063,7 +1063,7 @@ void smp_flush_tlb_mm(struct mm_struct *mm)
 	u32 ctx = CTX_HWBITS(mm->context);
 	int cpu = get_cpu();
 
-	if (atomic_read(&mm->mm_users) == 1) {
+	if (refcount_read(&mm->mm_users) == 1) {
 		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
 		goto local_flush_and_out;
 	}
@@ -1101,7 +1101,7 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long
 	info.nr = nr;
 	info.vaddrs = vaddrs;
 
-	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
+	if (mm == current->mm && refcount_read(&mm->mm_users) == 1)
 		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
 	else
 		smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
@@ -1117,7 +1117,7 @@ void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
 	unsigned long context = CTX_HWBITS(mm->context);
 	int cpu = get_cpu();
 
-	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
+	if (mm == current->mm && refcount_read(&mm->mm_users) == 1)
 		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
 	else
 		smp_cross_call_masked(&xcall_flush_tlb_page,
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index c7f2a52..17941a8 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1662,7 +1662,7 @@ static void smp_flush_tlb_mm(struct mm_struct *mm)
 		cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
 		if (!cpumask_empty(&cpu_mask)) {
 			xc1((smpfunc_t) local_ops->tlb_mm, (unsigned long) mm);
-			if (atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
+			if (refcount_read(&mm->mm_users) == 1 && current->active_mm == mm)
 				cpumask_copy(mm_cpumask(mm),
 					     cpumask_of(smp_processor_id()));
 		}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 3777b82..1da0463 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -530,7 +530,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
 	 * Don't bother flushing if this address space is about to be
 	 * destroyed.
 	 */
-	if (atomic_read(&mm->mm_users) == 0)
+	if (refcount_read(&mm->mm_users) == 0)
 		return;
 
 	fix_range(mm, start, end, 0);
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index 00c88a0..da181ad 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -3,6 +3,7 @@
 
 #include <linux/ioport.h>
 #include <linux/pci.h>
+#include <linux/refcount.h>
 
 struct amd_nb_bus_dev_range {
 	u8 bus;
@@ -55,7 +56,7 @@ struct threshold_bank {
 	struct threshold_block	*blocks;
 
 	/* initialized to the number of CPUs on the node sharing this bank */
-	atomic_t		cpus;
+	refcount_t		cpus;
 };
 
 struct amd_northbridge {
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index dc1697c..7e096fc 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1491,7 +1491,7 @@ void cpu_init(void)
 	for (i = 0; i <= IO_BITMAP_LONGS; i++)
 		t->io_bitmap[i] = ~0UL;
 
-	atomic_inc(&init_mm.mm_count);
+	refcount_inc(&init_mm.mm_count);
 	me->active_mm = &init_mm;
 	BUG_ON(me->mm);
 	enter_lazy_tlb(&init_mm, me);
@@ -1542,7 +1542,7 @@ void cpu_init(void)
 	/*
 	 * Set up and load the per-CPU TSS and LDT
 	 */
-	atomic_inc(&init_mm.mm_count);
+	refcount_inc(&init_mm.mm_count);
 	curr->active_mm = &init_mm;
 	BUG_ON(curr->mm);
 	enter_lazy_tlb(&init_mm, curr);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index a5fd137..ca351d7 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -1197,7 +1197,7 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
 				goto out;
 
 			per_cpu(threshold_banks, cpu)[bank] = b;
-			atomic_inc(&b->cpus);
+			refcount_inc(&b->cpus);
 
 			err = __threshold_add_blocks(b);
 
@@ -1220,7 +1220,7 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
 	per_cpu(threshold_banks, cpu)[bank] = b;
 
 	if (is_shared_bank(bank)) {
-		atomic_set(&b->cpus, 1);
+		refcount_set(&b->cpus, 1);
 
 		/* nb is already initialized, see above */
 		if (nb) {
@@ -1284,7 +1284,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
 		goto free_out;
 
 	if (is_shared_bank(bank)) {
-		if (!atomic_dec_and_test(&b->cpus)) {
+		if (!refcount_dec_and_test(&b->cpus)) {
 			__threshold_remove_blocks(b);
 			per_cpu(threshold_banks, cpu)[bank] = NULL;
 			return;
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index b868fa1..fdbae72 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -102,8 +102,8 @@ static pgd_t *tboot_pg_dir;
 static struct mm_struct tboot_mm = {
 	.mm_rb          = RB_ROOT,
 	.pgd            = swapper_pg_dir,
-	.mm_users       = ATOMIC_INIT(2),
-	.mm_count       = ATOMIC_INIT(1),
+	.mm_users       = REFCOUNT_INIT(2),
+	.mm_count       = REFCOUNT_INIT(1),
 	.mmap_sem       = __RWSEM_INITIALIZER(init_mm.mmap_sem),
 	.page_table_lock =  __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
 	.mmlist         = LIST_HEAD_INIT(init_mm.mmlist),
diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c
index fc4ad21..4e9ec31 100644
--- a/arch/xtensa/kernel/smp.c
+++ b/arch/xtensa/kernel/smp.c
@@ -135,7 +135,7 @@ void secondary_start_kernel(void)
 
 	/* All kernel threads share the same mm context. */
 
-	atomic_inc(&mm->mm_users);
+	refcount_inc(&mm->mm_users);
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 349dc3e..f0571f2 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -32,8 +32,8 @@ extern u64 efi_system_table;
 
 static struct mm_struct efi_mm = {
 	.mm_rb			= RB_ROOT,
-	.mm_users		= ATOMIC_INIT(2),
-	.mm_count		= ATOMIC_INIT(1),
+	.mm_users		= REFCOUNT_INIT(2),
+	.mm_count		= REFCOUNT_INIT(1),
 	.mmap_sem		= __RWSEM_INITIALIZER(efi_mm.mmap_sem),
 	.page_table_lock	= __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
 	.mmlist			= LIST_HEAD_INIT(efi_mm.mmlist),
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index d068af2..430eeba 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -334,7 +334,7 @@ i915_gem_userptr_init__mm_struct(struct drm_i915_gem_object *obj)
 		mm->i915 = to_i915(obj->base.dev);
 
 		mm->mm = current->mm;
-		atomic_inc(&current->mm->mm_count);
+		refcount_inc(&current->mm->mm_count);
 
 		mm->mn = NULL;
 
@@ -507,7 +507,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
 			flags |= FOLL_WRITE;
 
 		ret = -EFAULT;
-		if (atomic_inc_not_zero(&mm->mm_users)) {
+		if (refcount_inc_not_zero(&mm->mm_users)) {
 			down_read(&mm->mmap_sem);
 			while (pinned < npages) {
 				ret = get_user_pages_remote
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index cb72e00..d46eb3b 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -579,7 +579,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
 		if (!svm->mm)
 			goto bad_req;
 		/* If the mm is already defunct, don't handle faults. */
-		if (!atomic_inc_not_zero(&svm->mm->mm_users))
+		if (!refcount_inc_not_zero(&svm->mm->mm_users))
 			goto bad_req;
 		down_read(&svm->mm->mmap_sem);
 		vma = find_extend_vma(svm->mm, address);
diff --git a/fs/coredump.c b/fs/coredump.c
index e525b60..064f467 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -347,7 +347,7 @@ static int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
 		return nr;
 
 	tsk->flags |= PF_DUMPCORE;
-	if (atomic_read(&mm->mm_users) == nr + 1)
+	if (refcount_read(&mm->mm_users) == nr + 1)
 		goto done;
 	/*
 	 * We should find and kill all tasks which use this mm, and we should
diff --git a/fs/exec.c b/fs/exec.c
index e579466..d583170 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1174,7 +1174,7 @@ static int de_thread(struct task_struct *tsk)
 	flush_itimer_signals();
 #endif
 
-	if (atomic_read(&oldsighand->count) != 1) {
+	if (refcount_read(&oldsighand->count) != 1) {
 		struct sighand_struct *newsighand;
 		/*
 		 * This ->sighand is shared with the CLONE_SIGHAND
@@ -1184,7 +1184,7 @@ static int de_thread(struct task_struct *tsk)
 		if (!newsighand)
 			return -ENOMEM;
 
-		atomic_set(&newsighand->count, 1);
+		refcount_set(&newsighand->count, 1);
 		memcpy(newsighand->action, oldsighand->action,
 		       sizeof(newsighand->action));
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8e7e61b..fbfbb5e 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -798,7 +798,7 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
 
 		if (!IS_ERR_OR_NULL(mm)) {
 			/* ensure this mm_struct can't be freed */
-			atomic_inc(&mm->mm_count);
+			refcount_inc(&mm->mm_count);
 			/* but do not pin its memory */
 			mmput(mm);
 		}
@@ -845,7 +845,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
 		return -ENOMEM;
 
 	copied = 0;
-	if (!atomic_inc_not_zero(&mm->mm_users))
+	if (!refcount_inc_not_zero(&mm->mm_users))
 		goto free;
 
 	/* Maybe we should limit FOLL_FORCE to actual ptrace users? */
@@ -953,7 +953,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
 		return -ENOMEM;
 
 	ret = 0;
-	if (!atomic_inc_not_zero(&mm->mm_users))
+	if (!refcount_inc_not_zero(&mm->mm_users))
 		goto free;
 
 	down_read(&mm->mmap_sem);
@@ -1094,9 +1094,9 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
 		struct task_struct *p = find_lock_task_mm(task);
 
 		if (p) {
-			if (atomic_read(&p->mm->mm_users) > 1) {
+			if (refcount_read(&p->mm->mm_users) > 1) {
 				mm = p->mm;
-				atomic_inc(&mm->mm_count);
+				refcount_inc(&mm->mm_count);
 			}
 			task_unlock(p);
 		}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 8f96a49..5ce3b35 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -167,7 +167,7 @@ static void *m_start(struct seq_file *m, loff_t *ppos)
 		return ERR_PTR(-ESRCH);
 
 	mm = priv->mm;
-	if (!mm || !atomic_inc_not_zero(&mm->mm_users))
+	if (!mm || !refcount_inc_not_zero(&mm->mm_users))
 		return NULL;
 
 	down_read(&mm->mmap_sem);
@@ -1352,7 +1352,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
 	unsigned long end_vaddr;
 	int ret = 0, copied = 0;
 
-	if (!mm || !atomic_inc_not_zero(&mm->mm_users))
+	if (!mm || !refcount_inc_not_zero(&mm->mm_users))
 		goto out;
 
 	ret = -EINVAL;
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 3717562..bf0b163 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -219,7 +219,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 		return ERR_PTR(-ESRCH);
 
 	mm = priv->mm;
-	if (!mm || !atomic_inc_not_zero(&mm->mm_users))
+	if (!mm || !refcount_inc_not_zero(&mm->mm_users))
 		return NULL;
 
 	down_read(&mm->mmap_sem);
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index d96e2f3..a866d9a 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -1306,7 +1306,7 @@ static struct file *userfaultfd_file_create(int flags)
 	ctx->released = false;
 	ctx->mm = current->mm;
 	/* prevent the mm struct to be freed */
-	atomic_inc(&ctx->mm->mm_count);
+	refcount_inc(&ctx->mm->mm_count);
 
 	file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, ctx,
 				  O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index e850e76..a123fe7 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -4,6 +4,7 @@
 #include <linux/list.h>
 #include <linux/radix-tree.h>
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 #include <linux/spinlock.h>
 #include <linux/percpu_counter.h>
 #include <linux/percpu-refcount.h>
@@ -50,7 +51,7 @@ enum wb_stat_item {
  */
 struct bdi_writeback_congested {
 	unsigned long state;		/* WB_[a]sync_congested flags */
-	atomic_t refcnt;		/* nr of attached wb's and blkg */
+	refcount_t refcnt;		/* nr of attached wb's and blkg */
 
 #ifdef CONFIG_CGROUP_WRITEBACK
 	struct backing_dev_info *bdi;	/* the associated bdi */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 43b93a9..0c9f5ed 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -422,13 +422,13 @@ static inline bool inode_cgwb_enabled(struct inode *inode)
 static inline struct bdi_writeback_congested *
 wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
 {
-	atomic_inc(&bdi->wb_congested->refcnt);
+	refcount_inc(&bdi->wb_congested->refcnt);
 	return bdi->wb_congested;
 }
 
 static inline void wb_congested_put(struct bdi_writeback_congested *congested)
 {
-	if (atomic_dec_and_test(&congested->refcnt))
+	if (refcount_dec_and_test(&congested->refcnt))
 		kfree(congested);
 }
 
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 861b467..3556adb 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -13,6 +13,7 @@
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/rcupdate.h>
+#include <linux/refcount.h>
 #include <linux/percpu-refcount.h>
 #include <linux/percpu-rwsem.h>
 #include <linux/workqueue.h>
@@ -149,7 +150,7 @@ struct cgroup_subsys_state {
  */
 struct css_set {
 	/* Reference count */
-	atomic_t refcount;
+	refcount_t refcount;
 
 	/*
 	 * List running through all cgroup groups in the same hash
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index c83c23f..9b0d3f4 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -22,6 +22,7 @@
 #include <linux/ns_common.h>
 #include <linux/nsproxy.h>
 #include <linux/user_namespace.h>
+#include <linux/refcount.h>
 
 #include <linux/cgroup-defs.h>
 
@@ -640,7 +641,7 @@ static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {}
 #endif	/* CONFIG_CGROUP_DATA */
 
 struct cgroup_namespace {
-	atomic_t		count;
+	refcount_t		count;
 	struct ns_common	ns;
 	struct user_namespace	*user_ns;
 	struct ucounts		*ucounts;
@@ -675,12 +676,12 @@ copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
 static inline void get_cgroup_ns(struct cgroup_namespace *ns)
 {
 	if (ns)
-		atomic_inc(&ns->count);
+		refcount_inc(&ns->count);
 }
 
 static inline void put_cgroup_ns(struct cgroup_namespace *ns)
 {
-	if (ns && atomic_dec_and_test(&ns->count))
+	if (ns && refcount_dec_and_test(&ns->count))
 		free_cgroup_ns(ns);
 }
 
diff --git a/include/linux/cred.h b/include/linux/cred.h
index f0e70a1..25fdc87 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -17,6 +17,7 @@
 #include <linux/key.h>
 #include <linux/selinux.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/uidgid.h>
 
 struct user_struct;
@@ -27,7 +28,7 @@ struct inode;
  * COW Supplementary groups list
  */
 struct group_info {
-	atomic_t	usage;
+	refcount_t	usage;
 	int		ngroups;
 	kgid_t		gid[0];
 };
@@ -43,7 +44,7 @@ struct group_info {
  */
 static inline struct group_info *get_group_info(struct group_info *gi)
 {
-	atomic_inc(&gi->usage);
+	refcount_inc(&gi->usage);
 	return gi;
 }
 
@@ -53,7 +54,7 @@ static inline struct group_info *get_group_info(struct group_info *gi)
  */
 #define put_group_info(group_info)			\
 do {							\
-	if (atomic_dec_and_test(&(group_info)->usage))	\
+	if (refcount_dec_and_test(&(group_info)->usage))	\
 		groups_free(group_info);		\
 } while (0)
 
@@ -107,7 +108,7 @@ extern bool may_setgroups(void);
  * same context as task->real_cred.
  */
 struct cred {
-	atomic_t	usage;
+	refcount_t	usage;
 #ifdef CONFIG_DEBUG_CREDENTIALS
 	atomic_t	subscribers;	/* number of processes subscribed */
 	void		*put_addr;
@@ -220,7 +221,7 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred)
  */
 static inline struct cred *get_new_cred(struct cred *cred)
 {
-	atomic_inc(&cred->usage);
+	refcount_inc(&cred->usage);
 	return cred;
 }
 
@@ -260,7 +261,7 @@ static inline void put_cred(const struct cred *_cred)
 	struct cred *cred = (struct cred *) _cred;
 
 	validate_creds(cred);
-	if (atomic_dec_and_test(&(cred)->usage))
+	if (refcount_dec_and_test(&(cred)->usage))
 		__put_cred(cred);
 }
 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 325f649..9b84ce6 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -12,6 +12,7 @@
 #include <linux/securebits.h>
 #include <linux/seqlock.h>
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 #include <net/net_namespace.h>
 #include <linux/sched/rt.h>
 
@@ -65,7 +66,7 @@ extern struct fs_struct init_fs;
 extern struct nsproxy init_nsproxy;
 
 #define INIT_SIGHAND(sighand) {						\
-	.count		= ATOMIC_INIT(1), 				\
+	.count		= REFCOUNT_INIT(1), 				\
 	.action		= { { { .sa_handler = SIG_DFL, } }, },		\
 	.siglock	= __SPIN_LOCK_UNLOCKED(sighand.siglock),	\
 	.signalfd_wqh	= __WAIT_QUEUE_HEAD_INITIALIZER(sighand.signalfd_wqh),	\
@@ -188,7 +189,7 @@ extern struct task_group root_task_group;
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 # define INIT_TASK_TI(tsk)			\
 	.thread_info = INIT_THREAD_INFO(tsk),	\
-	.stack_refcount = ATOMIC_INIT(1),
+	.stack_refcount = REFCOUNT_INIT(1),
 #else
 # define INIT_TASK_TI(tsk)
 #endif
@@ -202,7 +203,7 @@ extern struct task_group root_task_group;
 	INIT_TASK_TI(tsk)						\
 	.state		= 0,						\
 	.stack		= init_stack,					\
-	.usage		= ATOMIC_INIT(2),				\
+	.usage		= REFCOUNT_INIT(2),				\
 	.flags		= PF_KTHREAD,					\
 	.prio		= MAX_PRIO-20,					\
 	.static_prio	= MAX_PRIO-20,					\
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 1c5190d..865ec17 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -26,6 +26,7 @@
 #include <linux/context_tracking.h>
 #include <linux/irqbypass.h>
 #include <linux/swait.h>
+#include <linux/refcount.h>
 #include <asm/signal.h>
 
 #include <linux/kvm.h>
@@ -403,7 +404,7 @@ struct kvm {
 #endif
 	struct kvm_vm_stat stat;
 	struct kvm_arch arch;
-	atomic_t users_count;
+	refcount_t users_count;
 #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
 	struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
 	spinlock_t ring_lock;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 808751d..f4b048f 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -7,6 +7,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 #include <linux/rwsem.h>
 #include <linux/completion.h>
 #include <linux/cpumask.h>
@@ -407,8 +408,8 @@ struct mm_struct {
 	unsigned long task_size;		/* size of task vm space */
 	unsigned long highest_vm_end;		/* highest vma end address */
 	pgd_t * pgd;
-	atomic_t mm_users;			/* How many users with user space? */
-	atomic_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
+	refcount_t mm_users;			/* How many users with user space? */
+	refcount_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
 	atomic_long_t nr_ptes;			/* PTE page table pages */
 #if CONFIG_PGTABLE_LEVELS > 2
 	atomic_long_t nr_pmds;			/* PMD page table pages */
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index ac0d65b..f862ba8 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -28,7 +28,7 @@ struct fs_struct;
  * nsproxy is copied.
  */
 struct nsproxy {
-	atomic_t count;
+	refcount_t count;
 	struct uts_namespace *uts_ns;
 	struct ipc_namespace *ipc_ns;
 	struct mnt_namespace *mnt_ns;
@@ -74,14 +74,14 @@ int __init nsproxy_cache_init(void);
 
 static inline void put_nsproxy(struct nsproxy *ns)
 {
-	if (atomic_dec_and_test(&ns->count)) {
+	if (refcount_dec_and_test(&ns->count)) {
 		free_nsproxy(ns);
 	}
 }
 
 static inline void get_nsproxy(struct nsproxy *ns)
 {
-	atomic_inc(&ns->count);
+	refcount_inc(&ns->count);
 }
 
 #endif
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 4741ecd..321a332 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -54,6 +54,7 @@ struct perf_guest_info_callbacks {
 #include <linux/perf_regs.h>
 #include <linux/workqueue.h>
 #include <linux/cgroup.h>
+#include <linux/refcount.h>
 #include <asm/local.h>
 
 struct perf_callchain_entry {
@@ -741,7 +742,7 @@ struct perf_event_context {
 	int				nr_stat;
 	int				nr_freq;
 	int				rotate_disable;
-	atomic_t			refcount;
+	refcount_t			refcount;
 	struct task_struct		*task;
 
 	/*
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 15321fb..8c8f896 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/rwsem.h>
 #include <linux/memcontrol.h>
+#include <linux/refcount.h>
 
 /*
  * The anon_vma heads a list of private "related" vmas, to scan if
@@ -34,7 +35,7 @@ struct anon_vma {
 	 * the reference is responsible for clearing up the
 	 * anon_vma if they are the last user on release
 	 */
-	atomic_t refcount;
+	refcount_t refcount;
 
 	/*
 	 * Count of child anon_vmas and VMAs which points to this anon_vma.
@@ -101,14 +102,14 @@ enum ttu_flags {
 #ifdef CONFIG_MMU
 static inline void get_anon_vma(struct anon_vma *anon_vma)
 {
-	atomic_inc(&anon_vma->refcount);
+	refcount_inc(&anon_vma->refcount);
 }
 
 void __put_anon_vma(struct anon_vma *anon_vma);
 
 static inline void put_anon_vma(struct anon_vma *anon_vma)
 {
-	if (atomic_dec_and_test(&anon_vma->refcount))
+	if (refcount_dec_and_test(&anon_vma->refcount))
 		__put_anon_vma(anon_vma);
 }
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4d19052..4d7bd87 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -43,6 +43,7 @@ struct sched_param {
 #include <linux/seccomp.h>
 #include <linux/rcupdate.h>
 #include <linux/rculist.h>
+#include <linux/refcount.h>
 #include <linux/rtmutex.h>
 
 #include <linux/time.h>
@@ -555,7 +556,7 @@ static inline int get_dumpable(struct mm_struct *mm)
 #define MMF_INIT_MASK		(MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK)
 
 struct sighand_struct {
-	atomic_t		count;
+	refcount_t		count;
 	struct k_sigaction	action[_NSIG];
 	spinlock_t		siglock;
 	wait_queue_head_t	signalfd_wqh;
@@ -695,7 +696,7 @@ struct autogroup;
  * the locking of signal_struct.
  */
 struct signal_struct {
-	atomic_t		sigcnt;
+	refcount_t		sigcnt;
 	atomic_t		live;
 	int			nr_threads;
 	struct list_head	thread_head;
@@ -865,7 +866,7 @@ static inline int signal_group_exit(const struct signal_struct *sig)
  * Some day this will be a full-fledged user tracking system..
  */
 struct user_struct {
-	atomic_t __count;	/* reference count */
+	refcount_t __count;	/* reference count */
 	atomic_t processes;	/* How many processes does this user have? */
 	atomic_t sigpending;	/* How many pending signals does this user have? */
 #ifdef CONFIG_INOTIFY_USER
@@ -1508,7 +1509,7 @@ struct task_struct {
 #endif
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	void *stack;
-	atomic_t usage;
+	refcount_t usage;
 	unsigned int flags;	/* per process flags, defined below */
 	unsigned int ptrace;
 
@@ -1986,7 +1987,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 	/* A live task holds one reference. */
-	atomic_t stack_refcount;
+	refcount_t stack_refcount;
 #endif
 /* CPU-specific state of this task */
 	struct thread_struct thread;
@@ -2237,13 +2238,13 @@ static inline int is_global_init(struct task_struct *tsk)
 extern struct pid *cad_pid;
 
 extern void free_task(struct task_struct *tsk);
-#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
+#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0)
 
 extern void __put_task_struct(struct task_struct *t);
 
 static inline void put_task_struct(struct task_struct *t)
 {
-	if (atomic_dec_and_test(&t->usage))
+	if (refcount_dec_and_test(&t->usage))
 		__put_task_struct(t);
 }
 
@@ -2703,7 +2704,7 @@ extern struct task_struct *find_task_by_pid_ns(pid_t nr,
 extern struct user_struct * alloc_uid(kuid_t);
 static inline struct user_struct *get_uid(struct user_struct *u)
 {
-	atomic_inc(&u->__count);
+	refcount_inc(&u->__count);
 	return u;
 }
 extern void free_uid(struct user_struct *);
@@ -2918,7 +2919,7 @@ extern struct mm_struct * mm_alloc(void);
 extern void __mmdrop(struct mm_struct *);
 static inline void mmdrop(struct mm_struct *mm)
 {
-	if (unlikely(atomic_dec_and_test(&mm->mm_count)))
+	if (unlikely(refcount_dec_and_test(&mm->mm_count)))
 		__mmdrop(mm);
 }
 
@@ -2930,7 +2931,7 @@ static inline void mmdrop_async_fn(struct work_struct *work)
 
 static inline void mmdrop_async(struct mm_struct *mm)
 {
-	if (unlikely(atomic_dec_and_test(&mm->mm_count))) {
+	if (unlikely(refcount_dec_and_test(&mm->mm_count))) {
 		INIT_WORK(&mm->async_put_work, mmdrop_async_fn);
 		schedule_work(&mm->async_put_work);
 	}
@@ -2938,7 +2939,7 @@ static inline void mmdrop_async(struct mm_struct *mm)
 
 static inline bool mmget_not_zero(struct mm_struct *mm)
 {
-	return atomic_inc_not_zero(&mm->mm_users);
+	return refcount_inc_not_zero(&mm->mm_users);
 }
 
 /* mmput gets rid of the mappings and all user-space */
@@ -3223,7 +3224,7 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 static inline void *try_get_task_stack(struct task_struct *tsk)
 {
-	return atomic_inc_not_zero(&tsk->stack_refcount) ?
+	return refcount_inc_not_zero(&tsk->stack_refcount) ?
 		task_stack_page(tsk) : NULL;
 }
 
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 8b1dde9..8a7533b 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -9,7 +9,7 @@ struct audit_tree;
 struct audit_chunk;
 
 struct audit_tree {
-	atomic_t count;
+	refcount_t count;
 	int goner;
 	struct audit_chunk *root;
 	struct list_head chunks;
@@ -77,7 +77,7 @@ static struct audit_tree *alloc_tree(const char *s)
 
 	tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL);
 	if (tree) {
-		atomic_set(&tree->count, 1);
+		refcount_set(&tree->count, 1);
 		tree->goner = 0;
 		INIT_LIST_HEAD(&tree->chunks);
 		INIT_LIST_HEAD(&tree->rules);
@@ -91,12 +91,12 @@ static struct audit_tree *alloc_tree(const char *s)
 
 static inline void get_tree(struct audit_tree *tree)
 {
-	atomic_inc(&tree->count);
+	refcount_inc(&tree->count);
 }
 
 static inline void put_tree(struct audit_tree *tree)
 {
-	if (atomic_dec_and_test(&tree->count))
+	if (refcount_dec_and_test(&tree->count))
 		kfree_rcu(tree, head);
 }
 
@@ -963,7 +963,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify
 	 * We are guaranteed to have at least one reference to the mark from
 	 * either the inode or the caller of fsnotify_destroy_mark().
 	 */
-	BUG_ON(atomic_read(&entry->refcnt) < 1);
+	BUG_ON(refcount_read(&entry->refcnt) < 1);
 }
 
 static const struct fsnotify_ops audit_tree_ops = {
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index f79e465..8ca9e6c 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -46,7 +46,7 @@
  */
 
 struct audit_watch {
-	atomic_t		count;	/* reference count */
+	refcount_t		count;	/* reference count */
 	dev_t			dev;	/* associated superblock device */
 	char			*path;	/* insertion path */
 	unsigned long		ino;	/* associated inode number */
@@ -111,12 +111,12 @@ static inline struct audit_parent *audit_find_parent(struct inode *inode)
 
 void audit_get_watch(struct audit_watch *watch)
 {
-	atomic_inc(&watch->count);
+	refcount_inc(&watch->count);
 }
 
 void audit_put_watch(struct audit_watch *watch)
 {
-	if (atomic_dec_and_test(&watch->count)) {
+	if (refcount_dec_and_test(&watch->count)) {
 		WARN_ON(watch->parent);
 		WARN_ON(!list_empty(&watch->rules));
 		kfree(watch->path);
@@ -178,7 +178,7 @@ static struct audit_watch *audit_init_watch(char *path)
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&watch->rules);
-	atomic_set(&watch->count, 1);
+	refcount_set(&watch->count, 1);
 	watch->path = path;
 	watch->dev = AUDIT_DEV_UNSET;
 	watch->ino = AUDIT_INO_UNSET;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 2ee9ec3..bfed258 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -223,7 +223,7 @@ static u16 have_free_callback __read_mostly;
 
 /* cgroup namespace for init task */
 struct cgroup_namespace init_cgroup_ns = {
-	.count		= { .counter = 2, },
+	.count		= REFCOUNT_INIT(2),
 	.user_ns	= &init_user_ns,
 	.ns.ops		= &cgroupns_operations,
 	.ns.inum	= PROC_CGROUP_INIT_INO,
@@ -646,7 +646,7 @@ struct cgrp_cset_link {
  * haven't been created.
  */
 struct css_set init_css_set = {
-	.refcount		= ATOMIC_INIT(1),
+	.refcount		= REFCOUNT_INIT(1),
 	.cgrp_links		= LIST_HEAD_INIT(init_css_set.cgrp_links),
 	.tasks			= LIST_HEAD_INIT(init_css_set.tasks),
 	.mg_tasks		= LIST_HEAD_INIT(init_css_set.mg_tasks),
@@ -816,7 +816,7 @@ static void put_css_set_locked(struct css_set *cset)
 
 	lockdep_assert_held(&css_set_lock);
 
-	if (!atomic_dec_and_test(&cset->refcount))
+	if (!refcount_dec_and_test(&cset->refcount))
 		return;
 
 	/* This css_set is dead. unlink it and release cgroup and css refs */
@@ -847,10 +847,13 @@ static void put_css_set(struct css_set *cset)
 	 * can see it. Similar to atomic_dec_and_lock(), but for an
 	 * rwlock
 	 */
-	if (atomic_add_unless(&cset->refcount, -1, 1))
+	spin_lock_irqsave(&css_set_lock, flags);
+	if (refcount_read(&cset->refcount) != 1) {
+		WARN_ON(refcount_dec_and_test(&cset->refcount));
+		spin_unlock_irqrestore(&css_set_lock, flags);
 		return;
+	}
 
-	spin_lock_irqsave(&css_set_lock, flags);
 	put_css_set_locked(cset);
 	spin_unlock_irqrestore(&css_set_lock, flags);
 }
@@ -860,7 +863,7 @@ static void put_css_set(struct css_set *cset)
  */
 static inline void get_css_set(struct css_set *cset)
 {
-	atomic_inc(&cset->refcount);
+	refcount_inc(&cset->refcount);
 }
 
 /**
@@ -1094,7 +1097,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
 		return NULL;
 	}
 
-	atomic_set(&cset->refcount, 1);
+	refcount_set(&cset->refcount, 1);
 	INIT_LIST_HEAD(&cset->cgrp_links);
 	INIT_LIST_HEAD(&cset->tasks);
 	INIT_LIST_HEAD(&cset->mg_tasks);
@@ -3940,7 +3943,7 @@ static int cgroup_task_count(const struct cgroup *cgrp)
 
 	spin_lock_irq(&css_set_lock);
 	list_for_each_entry(link, &cgrp->cset_links, cset_link)
-		count += atomic_read(&link->cset->refcount);
+		count += refcount_read(&link->cset->refcount);
 	spin_unlock_irq(&css_set_lock);
 	return count;
 }
@@ -6377,7 +6380,7 @@ static struct cgroup_namespace *alloc_cgroup_ns(void)
 		kfree(new_ns);
 		return ERR_PTR(ret);
 	}
-	atomic_set(&new_ns->count, 1);
+	refcount_set(&new_ns->count, 1);
 	new_ns->ns.ops = &cgroupns_operations;
 	return new_ns;
 }
@@ -6548,7 +6551,7 @@ static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css,
 	u64 count;
 
 	rcu_read_lock();
-	count = atomic_read(&task_css_set(current)->refcount);
+	count = refcount_read(&task_css_set(current)->refcount);
 	rcu_read_unlock();
 	return count;
 }
diff --git a/kernel/cred.c b/kernel/cred.c
index 5f264fb..31ebce0 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -35,13 +35,13 @@ do {									\
 static struct kmem_cache *cred_jar;
 
 /* init to 2 - one for init_task, one to ensure it is never freed */
-struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
+struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
 
 /*
  * The initial credentials for the initial task
  */
 struct cred init_cred = {
-	.usage			= ATOMIC_INIT(4),
+	.usage			= REFCOUNT_INIT(4),
 #ifdef CONFIG_DEBUG_CREDENTIALS
 	.subscribers		= ATOMIC_INIT(2),
 	.magic			= CRED_MAGIC,
@@ -100,17 +100,17 @@ static void put_cred_rcu(struct rcu_head *rcu)
 
 #ifdef CONFIG_DEBUG_CREDENTIALS
 	if (cred->magic != CRED_MAGIC_DEAD ||
-	    atomic_read(&cred->usage) != 0 ||
+	    refcount_read(&cred->usage) != 0 ||
 	    read_cred_subscribers(cred) != 0)
 		panic("CRED: put_cred_rcu() sees %p with"
 		      " mag %x, put %p, usage %d, subscr %d\n",
 		      cred, cred->magic, cred->put_addr,
-		      atomic_read(&cred->usage),
+		      refcount_read(&cred->usage),
 		      read_cred_subscribers(cred));
 #else
-	if (atomic_read(&cred->usage) != 0)
+	if (refcount_read(&cred->usage) != 0)
 		panic("CRED: put_cred_rcu() sees %p with usage %d\n",
-		      cred, atomic_read(&cred->usage));
+		      cred, refcount_read(&cred->usage));
 #endif
 
 	security_cred_free(cred);
@@ -134,10 +134,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
 void __put_cred(struct cred *cred)
 {
 	kdebug("__put_cred(%p{%d,%d})", cred,
-	       atomic_read(&cred->usage),
+	       refcount_read(&cred->usage),
 	       read_cred_subscribers(cred));
 
-	BUG_ON(atomic_read(&cred->usage) != 0);
+	BUG_ON(refcount_read(&cred->usage) != 0);
 #ifdef CONFIG_DEBUG_CREDENTIALS
 	BUG_ON(read_cred_subscribers(cred) != 0);
 	cred->magic = CRED_MAGIC_DEAD;
@@ -158,7 +158,7 @@ void exit_creds(struct task_struct *tsk)
 	struct cred *cred;
 
 	kdebug("exit_creds(%u,%p,%p,{%d,%d})", tsk->pid, tsk->real_cred, tsk->cred,
-	       atomic_read(&tsk->cred->usage),
+	       refcount_read(&tsk->cred->usage),
 	       read_cred_subscribers(tsk->cred));
 
 	cred = (struct cred *) tsk->real_cred;
@@ -193,7 +193,7 @@ const struct cred *get_task_cred(struct task_struct *task)
 	do {
 		cred = __task_cred((task));
 		BUG_ON(!cred);
-	} while (!atomic_inc_not_zero(&((struct cred *)cred)->usage));
+	} while (!refcount_inc_not_zero(&((struct cred *)cred)->usage));
 
 	rcu_read_unlock();
 	return cred;
@@ -211,7 +211,7 @@ struct cred *cred_alloc_blank(void)
 	if (!new)
 		return NULL;
 
-	atomic_set(&new->usage, 1);
+	refcount_set(&new->usage, 1);
 #ifdef CONFIG_DEBUG_CREDENTIALS
 	new->magic = CRED_MAGIC;
 #endif
@@ -257,7 +257,7 @@ struct cred *prepare_creds(void)
 	old = task->cred;
 	memcpy(new, old, sizeof(struct cred));
 
-	atomic_set(&new->usage, 1);
+	refcount_set(&new->usage, 1);
 	set_cred_subscribers(new, 0);
 	get_group_info(new->group_info);
 	get_uid(new->user);
@@ -334,7 +334,7 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
 		get_cred(p->cred);
 		alter_cred_subscribers(p->cred, 2);
 		kdebug("share_creds(%p{%d,%d})",
-		       p->cred, atomic_read(&p->cred->usage),
+		       p->cred, refcount_read(&p->cred->usage),
 		       read_cred_subscribers(p->cred));
 		atomic_inc(&p->cred->user->processes);
 		return 0;
@@ -425,7 +425,7 @@ int commit_creds(struct cred *new)
 	const struct cred *old = task->real_cred;
 
 	kdebug("commit_creds(%p{%d,%d})", new,
-	       atomic_read(&new->usage),
+	       refcount_read(&new->usage),
 	       read_cred_subscribers(new));
 
 	BUG_ON(task->cred != old);
@@ -434,7 +434,7 @@ int commit_creds(struct cred *new)
 	validate_creds(old);
 	validate_creds(new);
 #endif
-	BUG_ON(atomic_read(&new->usage) < 1);
+	BUG_ON(refcount_read(&new->usage) < 1);
 
 	get_cred(new); /* we will require a ref for the subj creds too */
 
@@ -499,13 +499,13 @@ EXPORT_SYMBOL(commit_creds);
 void abort_creds(struct cred *new)
 {
 	kdebug("abort_creds(%p{%d,%d})", new,
-	       atomic_read(&new->usage),
+	       refcount_read(&new->usage),
 	       read_cred_subscribers(new));
 
 #ifdef CONFIG_DEBUG_CREDENTIALS
 	BUG_ON(read_cred_subscribers(new) != 0);
 #endif
-	BUG_ON(atomic_read(&new->usage) < 1);
+	BUG_ON(refcount_read(&new->usage) < 1);
 	put_cred(new);
 }
 EXPORT_SYMBOL(abort_creds);
@@ -522,7 +522,7 @@ const struct cred *override_creds(const struct cred *new)
 	const struct cred *old = current->cred;
 
 	kdebug("override_creds(%p{%d,%d})", new,
-	       atomic_read(&new->usage),
+	       refcount_read(&new->usage),
 	       read_cred_subscribers(new));
 
 	validate_creds(old);
@@ -533,7 +533,7 @@ const struct cred *override_creds(const struct cred *new)
 	alter_cred_subscribers(old, -1);
 
 	kdebug("override_creds() = %p{%d,%d}", old,
-	       atomic_read(&old->usage),
+	       refcount_read(&old->usage),
 	       read_cred_subscribers(old));
 	return old;
 }
@@ -551,7 +551,7 @@ void revert_creds(const struct cred *old)
 	const struct cred *override = current->cred;
 
 	kdebug("revert_creds(%p{%d,%d})", old,
-	       atomic_read(&old->usage),
+	       refcount_read(&old->usage),
 	       read_cred_subscribers(old));
 
 	validate_creds(old);
@@ -610,7 +610,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
 	validate_creds(old);
 
 	*new = *old;
-	atomic_set(&new->usage, 1);
+	refcount_set(&new->usage, 1);
 	set_cred_subscribers(new, 0);
 	get_uid(new->user);
 	get_user_ns(new->user_ns);
@@ -734,7 +734,7 @@ static void dump_invalid_creds(const struct cred *cred, const char *label,
 	printk(KERN_ERR "CRED: ->magic=%x, put_addr=%p\n",
 	       cred->magic, cred->put_addr);
 	printk(KERN_ERR "CRED: ->usage=%d, subscr=%d\n",
-	       atomic_read(&cred->usage),
+	       refcount_read(&cred->usage),
 	       read_cred_subscribers(cred));
 	printk(KERN_ERR "CRED: ->*uid = { %d,%d,%d,%d }\n",
 		from_kuid_munged(&init_user_ns, cred->uid),
@@ -808,7 +808,7 @@ void validate_creds_for_do_exit(struct task_struct *tsk)
 {
 	kdebug("validate_creds_for_do_exit(%p,%p{%d,%d})",
 	       tsk->real_cred, tsk->cred,
-	       atomic_read(&tsk->cred->usage),
+	       refcount_read(&tsk->cred->usage),
 	       read_cred_subscribers(tsk->cred));
 
 	__validate_process_creds(tsk, __FILE__, __LINE__);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index ab15509..8c03c27 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1117,7 +1117,7 @@ static void perf_event_ctx_deactivate(struct perf_event_context *ctx)
 
 static void get_ctx(struct perf_event_context *ctx)
 {
-	WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
+	WARN_ON(!refcount_inc_not_zero(&ctx->refcount));
 }
 
 static void free_ctx(struct rcu_head *head)
@@ -1131,7 +1131,7 @@ static void free_ctx(struct rcu_head *head)
 
 static void put_ctx(struct perf_event_context *ctx)
 {
-	if (atomic_dec_and_test(&ctx->refcount)) {
+	if (refcount_dec_and_test(&ctx->refcount)) {
 		if (ctx->parent_ctx)
 			put_ctx(ctx->parent_ctx);
 		if (ctx->task && ctx->task != TASK_TOMBSTONE)
@@ -1209,7 +1209,7 @@ perf_event_ctx_lock_nested(struct perf_event *event, int nesting)
 again:
 	rcu_read_lock();
 	ctx = ACCESS_ONCE(event->ctx);
-	if (!atomic_inc_not_zero(&ctx->refcount)) {
+	if (!refcount_inc_not_zero(&ctx->refcount)) {
 		rcu_read_unlock();
 		goto again;
 	}
@@ -1337,7 +1337,7 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
 		}
 
 		if (ctx->task == TASK_TOMBSTONE ||
-		    !atomic_inc_not_zero(&ctx->refcount)) {
+		    !refcount_inc_not_zero(&ctx->refcount)) {
 			raw_spin_unlock(&ctx->lock);
 			ctx = NULL;
 		} else {
@@ -3639,7 +3639,7 @@ static void __perf_event_init_context(struct perf_event_context *ctx)
 	INIT_LIST_HEAD(&ctx->pinned_groups);
 	INIT_LIST_HEAD(&ctx->flexible_groups);
 	INIT_LIST_HEAD(&ctx->event_list);
-	atomic_set(&ctx->refcount, 1);
+	refcount_set(&ctx->refcount, 1);
 }
 
 static struct perf_event_context *
@@ -4934,7 +4934,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event *event)
 	rcu_read_lock();
 	rb = rcu_dereference(event->rb);
 	if (rb) {
-		if (!atomic_inc_not_zero(&rb->refcount))
+		if (!refcount_inc_not_zero(&rb->refcount))
 			rb = NULL;
 	}
 	rcu_read_unlock();
@@ -4944,7 +4944,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event *event)
 
 void ring_buffer_put(struct ring_buffer *rb)
 {
-	if (!atomic_dec_and_test(&rb->refcount))
+	if (!refcount_dec_and_test(&rb->refcount))
 		return;
 
 	WARN_ON_ONCE(!list_empty(&rb->event_list));
@@ -5009,7 +5009,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
 		/* this has to be the last one */
 		rb_free_aux(rb);
-		WARN_ON_ONCE(atomic_read(&rb->aux_refcount));
+		WARN_ON_ONCE(refcount_read(&rb->aux_refcount));
 
 		mutex_unlock(&event->mmap_mutex);
 	}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 486fd78..b36d917 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -2,6 +2,7 @@
 #define _KERNEL_EVENTS_INTERNAL_H
 
 #include <linux/hardirq.h>
+#include <linux/refcount.h>
 #include <linux/uaccess.h>
 
 /* Buffer handling */
@@ -9,7 +10,7 @@
 #define RING_BUFFER_WRITABLE		0x01
 
 struct ring_buffer {
-	atomic_t			refcount;
+	refcount_t			refcount;
 	struct rcu_head			rcu_head;
 #ifdef CONFIG_PERF_USE_VMALLOC
 	struct work_struct		work;
@@ -47,7 +48,7 @@ struct ring_buffer {
 	atomic_t			aux_mmap_count;
 	unsigned long			aux_mmap_locked;
 	void				(*free_aux)(void *);
-	atomic_t			aux_refcount;
+	refcount_t			aux_refcount;
 	void				**aux_pages;
 	void				*aux_priv;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 257fa46..c501d4e 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -284,7 +284,7 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
 	else
 		rb->overwrite = 1;
 
-	atomic_set(&rb->refcount, 1);
+	refcount_set(&rb->refcount, 1);
 
 	INIT_LIST_HEAD(&rb->event_list);
 	spin_lock_init(&rb->event_lock);
@@ -344,7 +344,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
 	if (!atomic_read(&rb->aux_mmap_count))
 		goto err;
 
-	if (!atomic_inc_not_zero(&rb->aux_refcount))
+	if (!refcount_inc_not_zero(&rb->aux_refcount))
 		goto err;
 
 	/*
@@ -636,7 +636,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
 	 * we keep a refcount here to make sure either of the two can
 	 * reference them safely.
 	 */
-	atomic_set(&rb->aux_refcount, 1);
+	refcount_set(&rb->aux_refcount, 1);
 
 	rb->aux_overwrite = overwrite;
 	rb->aux_watermark = watermark;
@@ -655,7 +655,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
 
 void rb_free_aux(struct ring_buffer *rb)
 {
-	if (atomic_dec_and_test(&rb->aux_refcount))
+	if (refcount_dec_and_test(&rb->aux_refcount))
 		__rb_free_aux(rb);
 }
 
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d416f3b..4ef8c5f 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -37,6 +37,7 @@
 #include <linux/percpu-rwsem.h>
 #include <linux/task_work.h>
 #include <linux/shmem_fs.h>
+#include <linux/refcount.h>
 
 #include <linux/uprobes.h>
 
@@ -64,7 +65,7 @@ static struct percpu_rw_semaphore dup_mmap_sem;
 
 struct uprobe {
 	struct rb_node		rb_node;	/* node in the rb tree */
-	atomic_t		ref;
+	refcount_t		ref;
 	struct rw_semaphore	register_rwsem;
 	struct rw_semaphore	consumer_rwsem;
 	struct list_head	pending_list;
@@ -363,13 +364,13 @@ set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long v
 
 static struct uprobe *get_uprobe(struct uprobe *uprobe)
 {
-	atomic_inc(&uprobe->ref);
+	refcount_inc(&uprobe->ref);
 	return uprobe;
 }
 
 static void put_uprobe(struct uprobe *uprobe)
 {
-	if (atomic_dec_and_test(&uprobe->ref))
+	if (refcount_dec_and_test(&uprobe->ref))
 		kfree(uprobe);
 }
 
@@ -451,7 +452,7 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
 	rb_link_node(&uprobe->rb_node, parent, p);
 	rb_insert_color(&uprobe->rb_node, &uprobes_tree);
 	/* get access + creation ref */
-	atomic_set(&uprobe->ref, 2);
+	refcount_set(&uprobe->ref, 2);
 
 	return u;
 }
@@ -741,7 +742,7 @@ build_map_info(struct address_space *mapping, loff_t offset, bool is_register)
 			continue;
 		}
 
-		if (!atomic_inc_not_zero(&vma->vm_mm->mm_users))
+		if (!refcount_inc_not_zero(&vma->vm_mm->mm_users))
 			continue;
 
 		info = prev;
@@ -1115,7 +1116,7 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
 	if (no_uprobe_events() || !valid_vma(vma, false))
 		return;
 
-	if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */
+	if (!refcount_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */
 		return;
 
 	if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) ||
diff --git a/kernel/exit.c b/kernel/exit.c
index 8f14b86..6cf1473 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -396,7 +396,7 @@ void mm_update_next_owner(struct mm_struct *mm)
 	 * candidates.  Do not leave the mm pointing to a possibly
 	 * freed task structure.
 	 */
-	if (atomic_read(&mm->mm_users) <= 1) {
+	if (refcount_read(&mm->mm_users) <= 1) {
 		mm->owner = NULL;
 		return;
 	}
@@ -509,7 +509,7 @@ static void exit_mm(struct task_struct *tsk)
 		__set_task_state(tsk, TASK_RUNNING);
 		down_read(&mm->mmap_sem);
 	}
-	atomic_inc(&mm->mm_count);
+	refcount_inc(&mm->mm_count);
 	BUG_ON(mm != tsk->active_mm);
 	/* more a memory barrier than a real lock */
 	task_lock(tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index 11c5c8a..4dfaf68 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -330,7 +330,7 @@ static void release_task_stack(struct task_struct *tsk)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 void put_task_stack(struct task_struct *tsk)
 {
-	if (atomic_dec_and_test(&tsk->stack_refcount))
+	if (refcount_dec_and_test(&tsk->stack_refcount))
 		release_task_stack(tsk);
 }
 #endif
@@ -348,7 +348,7 @@ void free_task(struct task_struct *tsk)
 	 * If the task had a separate stack allocation, it should be gone
 	 * by now.
 	 */
-	WARN_ON_ONCE(atomic_read(&tsk->stack_refcount) != 0);
+	WARN_ON_ONCE(refcount_read(&tsk->stack_refcount) != 0);
 #endif
 	rt_mutex_debug_task_free(tsk);
 	ftrace_graph_exit_task(tsk);
@@ -375,14 +375,14 @@ static inline void free_signal_struct(struct signal_struct *sig)
 
 static inline void put_signal_struct(struct signal_struct *sig)
 {
-	if (atomic_dec_and_test(&sig->sigcnt))
+	if (refcount_dec_and_test(&sig->sigcnt))
 		free_signal_struct(sig);
 }
 
 void __put_task_struct(struct task_struct *tsk)
 {
 	WARN_ON(!tsk->exit_state);
-	WARN_ON(atomic_read(&tsk->usage));
+	WARN_ON(refcount_read(&tsk->usage));
 	WARN_ON(tsk == current);
 
 	cgroup_free(tsk);
@@ -501,7 +501,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 	tsk->stack_vm_area = stack_vm_area;
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
-	atomic_set(&tsk->stack_refcount, 1);
+	refcount_set(&tsk->stack_refcount, 1);
 #endif
 
 	if (err)
@@ -530,7 +530,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 	 * One for us, one for whoever does the "release_task()" (usually
 	 * parent)
 	 */
-	atomic_set(&tsk->usage, 2);
+	refcount_set(&tsk->usage, 2);
 #ifdef CONFIG_BLK_DEV_IO_TRACE
 	tsk->btrace_seq = 0;
 #endif
@@ -753,8 +753,8 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
 	mm->mmap = NULL;
 	mm->mm_rb = RB_ROOT;
 	mm->vmacache_seqnum = 0;
-	atomic_set(&mm->mm_users, 1);
-	atomic_set(&mm->mm_count, 1);
+	refcount_set(&mm->mm_users, 1);
+	refcount_set(&mm->mm_count, 1);
 	init_rwsem(&mm->mmap_sem);
 	INIT_LIST_HEAD(&mm->mmlist);
 	mm->core_state = NULL;
@@ -856,7 +856,7 @@ EXPORT_SYMBOL_GPL(__mmdrop);
 
 static inline void __mmput(struct mm_struct *mm)
 {
-	VM_BUG_ON(atomic_read(&mm->mm_users));
+	VM_BUG_ON(refcount_read(&mm->mm_users));
 
 	uprobe_clear_state(mm);
 	exit_aio(mm);
@@ -883,7 +883,7 @@ void mmput(struct mm_struct *mm)
 {
 	might_sleep();
 
-	if (atomic_dec_and_test(&mm->mm_users))
+	if (refcount_dec_and_test(&mm->mm_users))
 		__mmput(mm);
 }
 EXPORT_SYMBOL_GPL(mmput);
@@ -897,7 +897,7 @@ static void mmput_async_fn(struct work_struct *work)
 
 void mmput_async(struct mm_struct *mm)
 {
-	if (atomic_dec_and_test(&mm->mm_users)) {
+	if (refcount_dec_and_test(&mm->mm_users)) {
 		INIT_WORK(&mm->async_put_work, mmput_async_fn);
 		schedule_work(&mm->async_put_work);
 	}
@@ -994,7 +994,7 @@ struct mm_struct *get_task_mm(struct task_struct *task)
 		if (task->flags & PF_KTHREAD)
 			mm = NULL;
 		else
-			atomic_inc(&mm->mm_users);
+			refcount_inc(&mm->mm_users);
 	}
 	task_unlock(task);
 	return mm;
@@ -1096,7 +1096,7 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
 	 */
 	if (tsk->clear_child_tid) {
 		if (!(tsk->signal->flags & SIGNAL_GROUP_COREDUMP) &&
-		    atomic_read(&mm->mm_users) > 1) {
+		    refcount_read(&mm->mm_users) > 1) {
 			/*
 			 * We don't check the error code - if userspace has
 			 * not set up a proper pointer then tough luck.
@@ -1182,7 +1182,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk)
 	vmacache_flush(tsk);
 
 	if (clone_flags & CLONE_VM) {
-		atomic_inc(&oldmm->mm_users);
+		refcount_inc(&oldmm->mm_users);
 		mm = oldmm;
 		goto good_mm;
 	}
@@ -1279,7 +1279,7 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
 	struct sighand_struct *sig;
 
 	if (clone_flags & CLONE_SIGHAND) {
-		atomic_inc(&current->sighand->count);
+		refcount_inc(&current->sighand->count);
 		return 0;
 	}
 	sig = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
@@ -1287,14 +1287,14 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
 	if (!sig)
 		return -ENOMEM;
 
-	atomic_set(&sig->count, 1);
+	refcount_set(&sig->count, 1);
 	memcpy(sig->action, current->sighand->action, sizeof(sig->action));
 	return 0;
 }
 
 void __cleanup_sighand(struct sighand_struct *sighand)
 {
-	if (atomic_dec_and_test(&sighand->count)) {
+	if (refcount_dec_and_test(&sighand->count)) {
 		signalfd_cleanup(sighand);
 		/*
 		 * sighand_cachep is SLAB_DESTROY_BY_RCU so we can free it
@@ -1337,7 +1337,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 
 	sig->nr_threads = 1;
 	atomic_set(&sig->live, 1);
-	atomic_set(&sig->sigcnt, 1);
+	refcount_set(&sig->sigcnt, 1);
 
 	/* list_add(thread_node, thread_head) without INIT_LIST_HEAD() */
 	sig->thread_head = (struct list_head)LIST_HEAD_INIT(tsk->thread_node);
@@ -1808,7 +1808,7 @@ static __latent_entropy struct task_struct *copy_process(
 		} else {
 			current->signal->nr_threads++;
 			atomic_inc(&current->signal->live);
-			atomic_inc(&current->signal->sigcnt);
+			refcount_inc(&current->signal->sigcnt);
 			list_add_tail_rcu(&p->thread_group,
 					  &p->group_leader->thread_group);
 			list_add_tail_rcu(&p->thread_node,
@@ -2120,7 +2120,7 @@ static int check_unshare_flags(unsigned long unshare_flags)
 			return -EINVAL;
 	}
 	if (unshare_flags & (CLONE_SIGHAND | CLONE_VM)) {
-		if (atomic_read(&current->sighand->count) > 1)
+		if (refcount_read(&current->sighand->count) > 1)
 			return -EINVAL;
 	}
 	if (unshare_flags & CLONE_VM) {
diff --git a/kernel/futex.c b/kernel/futex.c
index 0842c8ca..3515e4d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -65,6 +65,7 @@
 #include <linux/freezer.h>
 #include <linux/bootmem.h>
 #include <linux/fault-inject.h>
+#include <linux/refcount.h>
 
 #include <asm/futex.h>
 
@@ -207,7 +208,7 @@ struct futex_pi_state {
 	struct rt_mutex pi_mutex;
 
 	struct task_struct *owner;
-	atomic_t refcount;
+	refcount_t refcount;
 
 	union futex_key key;
 };
@@ -338,7 +339,7 @@ static inline bool should_fail_futex(bool fshared)
 
 static inline void futex_get_mm(union futex_key *key)
 {
-	atomic_inc(&key->private.mm->mm_count);
+	refcount_inc(&key->private.mm->mm_count);
 	/*
 	 * Ensure futex_get_mm() implies a full barrier such that
 	 * get_futex_key() implies a full barrier. This is relied upon
@@ -792,7 +793,7 @@ static int refill_pi_state_cache(void)
 	INIT_LIST_HEAD(&pi_state->list);
 	/* pi_mutex gets initialized later */
 	pi_state->owner = NULL;
-	atomic_set(&pi_state->refcount, 1);
+	refcount_set(&pi_state->refcount, 1);
 	pi_state->key = FUTEX_KEY_INIT;
 
 	current->pi_state_cache = pi_state;
@@ -821,7 +822,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
 	if (!pi_state)
 		return;
 
-	if (!atomic_dec_and_test(&pi_state->refcount))
+	if (!refcount_dec_and_test(&pi_state->refcount))
 		return;
 
 	/*
@@ -845,7 +846,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
 		 * refcount is at 0 - put it back to 1.
 		 */
 		pi_state->owner = NULL;
-		atomic_set(&pi_state->refcount, 1);
+		refcount_set(&pi_state->refcount, 1);
 		current->pi_state_cache = pi_state;
 	}
 }
@@ -989,7 +990,7 @@ static int attach_to_pi_state(u32 uval, struct futex_pi_state *pi_state,
 	if (unlikely(!pi_state))
 		return -EINVAL;
 
-	WARN_ON(!atomic_read(&pi_state->refcount));
+	WARN_ON(!refcount_read(&pi_state->refcount));
 
 	/*
 	 * Handle the owner died case:
@@ -1040,7 +1041,7 @@ static int attach_to_pi_state(u32 uval, struct futex_pi_state *pi_state,
 	if (pid != task_pid_vnr(pi_state->owner))
 		return -EINVAL;
 out_state:
-	atomic_inc(&pi_state->refcount);
+	refcount_inc(&pi_state->refcount);
 	*ps = pi_state;
 	return 0;
 }
@@ -1907,7 +1908,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
 			 * refcount on the pi_state and store the pointer in
 			 * the futex_q object of the waiter.
 			 */
-			atomic_inc(&pi_state->refcount);
+			refcount_inc(&pi_state->refcount);
 			this->pi_state = pi_state;
 			ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
 							this->rt_waiter,
diff --git a/kernel/groups.c b/kernel/groups.c
index 8dd7a61..455267f 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -22,7 +22,7 @@ struct group_info *groups_alloc(int gidsetsize)
 	if (!gi)
 		return NULL;
 
-	atomic_set(&gi->usage, 1);
+	refcount_set(&gi->usage, 1);
 	gi->ngroups = gidsetsize;
 	return gi;
 }
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 85e5546..b8506c3 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -19,6 +19,7 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/kcov.h>
+#include <linux/refcount.h>
 #include <asm/setup.h>
 
 /*
@@ -35,7 +36,7 @@ struct kcov {
 	 *  - opened file descriptor
 	 *  - task with enabled coverage (we can't unwire it from another task)
 	 */
-	atomic_t		refcount;
+	refcount_t		refcount;
 	/* The lock protects mode, size, area and t. */
 	spinlock_t		lock;
 	enum kcov_mode		mode;
@@ -101,12 +102,12 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_pc);
 
 static void kcov_get(struct kcov *kcov)
 {
-	atomic_inc(&kcov->refcount);
+	refcount_inc(&kcov->refcount);
 }
 
 static void kcov_put(struct kcov *kcov)
 {
-	if (atomic_dec_and_test(&kcov->refcount)) {
+	if (refcount_dec_and_test(&kcov->refcount)) {
 		vfree(kcov->area);
 		kfree(kcov);
 	}
@@ -182,7 +183,7 @@ static int kcov_open(struct inode *inode, struct file *filep)
 	kcov = kzalloc(sizeof(*kcov), GFP_KERNEL);
 	if (!kcov)
 		return -ENOMEM;
-	atomic_set(&kcov->refcount, 1);
+	refcount_set(&kcov->refcount, 1);
 	spin_lock_init(&kcov->lock);
 	filep->private_data = kcov;
 	return nonseekable_open(inode, filep);
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 782102e..435a0f9 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -30,7 +30,7 @@
 static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = {
-	.count			= ATOMIC_INIT(1),
+	.count			= REFCOUNT_INIT(1),
 	.uts_ns			= &init_uts_ns,
 #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
 	.ipc_ns			= &init_ipc_ns,
@@ -51,7 +51,7 @@ static inline struct nsproxy *create_nsproxy(void)
 
 	nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
 	if (nsproxy)
-		atomic_set(&nsproxy->count, 1);
+		refcount_set(&nsproxy->count, 1);
 	return nsproxy;
 }
 
@@ -224,7 +224,7 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
 	p->nsproxy = new;
 	task_unlock(p);
 
-	if (ns && atomic_dec_and_test(&ns->count))
+	if (ns && refcount_dec_and_test(&ns->count))
 		free_nsproxy(ns);
 }
 
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index c56fb57..26eebac 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2231,7 +2231,7 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
 #endif
 
 #ifdef CONFIG_NUMA_BALANCING
-	if (p->mm && atomic_read(&p->mm->mm_users) == 1) {
+	if (p->mm && refcount_read(&p->mm->mm_users) == 1) {
 		p->mm->numa_next_scan = jiffies + msecs_to_jiffies(sysctl_numa_balancing_scan_delay);
 		p->mm->numa_scan_seq = 0;
 	}
@@ -2878,7 +2878,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
 
 	if (!mm) {
 		next->active_mm = oldmm;
-		atomic_inc(&oldmm->mm_count);
+		refcount_inc(&oldmm->mm_count);
 		enter_lazy_tlb(oldmm, next);
 	} else
 		switch_mm_irqs_off(oldmm, mm, next);
@@ -6177,6 +6177,7 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu)
 		cpumask_or(covered, covered, sg_span);
 
 		sg->sgc = *per_cpu_ptr(sdd->sgc, i);
+
 		if (atomic_inc_return(&sg->sgc->ref) == 1)
 			build_group_mask(sd, sg);
 
@@ -7686,7 +7687,7 @@ void __init sched_init(void)
 	/*
 	 * The boot idle thread does lazy MMU switching as well:
 	 */
-	atomic_inc(&init_mm.mm_count);
+	refcount_inc(&init_mm.mm_count);
 	enter_lazy_tlb(&init_mm, current);
 
 	/*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6559d19..8622d15 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1133,7 +1133,7 @@ static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
 }
 
 struct numa_group {
-	atomic_t refcount;
+	refcount_t refcount;
 
 	spinlock_t lock; /* nr_tasks, tasks */
 	int nr_tasks;
@@ -2181,12 +2181,12 @@ static void task_numa_placement(struct task_struct *p)
 
 static inline int get_numa_group(struct numa_group *grp)
 {
-	return atomic_inc_not_zero(&grp->refcount);
+	return refcount_inc_not_zero(&grp->refcount);
 }
 
 static inline void put_numa_group(struct numa_group *grp)
 {
-	if (atomic_dec_and_test(&grp->refcount))
+	if (refcount_dec_and_test(&grp->refcount))
 		kfree_rcu(grp, rcu);
 }
 
@@ -2207,7 +2207,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
 		if (!grp)
 			return;
 
-		atomic_set(&grp->refcount, 1);
+		refcount_set(&grp->refcount, 1);
 		grp->active_nodes = 1;
 		grp->max_faults_cpu = 0;
 		spin_lock_init(&grp->lock);
diff --git a/kernel/user.c b/kernel/user.c
index b069ccb..d9dff8e 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -89,7 +89,7 @@ static DEFINE_SPINLOCK(uidhash_lock);
 
 /* root_user.__count is 1, for init task cred */
 struct user_struct root_user = {
-	.__count	= ATOMIC_INIT(1),
+	.__count	= REFCOUNT_INIT(1),
 	.processes	= ATOMIC_INIT(1),
 	.sigpending	= ATOMIC_INIT(0),
 	.locked_shm     = 0,
@@ -115,7 +115,7 @@ static struct user_struct *uid_hash_find(kuid_t uid, struct hlist_head *hashent)
 
 	hlist_for_each_entry(user, hashent, uidhash_node) {
 		if (uid_eq(user->uid, uid)) {
-			atomic_inc(&user->__count);
+			refcount_inc(&user->__count);
 			return user;
 		}
 	}
@@ -162,7 +162,7 @@ void free_uid(struct user_struct *up)
 		return;
 
 	local_irq_save(flags);
-	if (atomic_dec_and_lock(&up->__count, &uidhash_lock))
+	if (refcount_dec_and_lock(&up->__count, &uidhash_lock))
 		free_user(up, flags);
 	else
 		local_irq_restore(flags);
@@ -183,7 +183,7 @@ struct user_struct *alloc_uid(kuid_t uid)
 			goto out_unlock;
 
 		new->uid = uid;
-		atomic_set(&new->__count, 1);
+		refcount_set(&new->__count, 1);
 
 		/*
 		 * Before adding this, check whether we raced
diff --git a/lib/is_single_threaded.c b/lib/is_single_threaded.c
index 391fd23..295ddcf 100644
--- a/lib/is_single_threaded.c
+++ b/lib/is_single_threaded.c
@@ -25,7 +25,7 @@ bool current_is_single_threaded(void)
 	if (atomic_read(&task->signal->live) != 1)
 		return false;
 
-	if (atomic_read(&mm->mm_users) == 1)
+	if (refcount_read(&mm->mm_users) == 1)
 		return true;
 
 	ret = false;
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 3bfed5ab..103875d 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -416,8 +416,10 @@ wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
 			node = &parent->rb_left;
 		else if (congested->blkcg_id > blkcg_id)
 			node = &parent->rb_right;
-		else
-			goto found;
+		else {
+			refcount_inc(&congested->refcnt);
+ 			goto found;
+		}
 	}
 
 	if (new_congested) {
@@ -436,13 +438,12 @@ wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
 	if (!new_congested)
 		return NULL;
 
-	atomic_set(&new_congested->refcnt, 0);
+	refcount_set(&new_congested->refcnt, 1);
 	new_congested->bdi = bdi;
 	new_congested->blkcg_id = blkcg_id;
 	goto retry;
 
 found:
-	atomic_inc(&congested->refcnt);
 	spin_unlock_irqrestore(&cgwb_lock, flags);
 	kfree(new_congested);
 	return congested;
@@ -459,7 +460,7 @@ void wb_congested_put(struct bdi_writeback_congested *congested)
 	unsigned long flags;
 
 	local_irq_save(flags);
-	if (!atomic_dec_and_lock(&congested->refcnt, &cgwb_lock)) {
+	if (!refcount_dec_and_lock(&congested->refcnt, &cgwb_lock)) {
 		local_irq_restore(flags);
 		return;
 	}
diff --git a/mm/debug.c b/mm/debug.c
index db1cd26..eebbd15 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -134,8 +134,8 @@ void dump_mm(const struct mm_struct *mm)
 		mm->get_unmapped_area,
 #endif
 		mm->mmap_base, mm->mmap_legacy_base, mm->highest_vm_end,
-		mm->pgd, atomic_read(&mm->mm_users),
-		atomic_read(&mm->mm_count),
+		mm->pgd, refcount_read(&mm->mm_users),
+		refcount_read(&mm->mm_count),
 		atomic_long_read((atomic_long_t *)&mm->nr_ptes),
 		mm_nr_pmds((struct mm_struct *)mm),
 		mm->map_count,
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 10eedbf..5048e8f 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -30,6 +30,7 @@
 #include <linux/userfaultfd_k.h>
 #include <linux/page_idle.h>
 #include <linux/shmem_fs.h>
+#include <linux/refcount.h>
 
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
@@ -56,14 +57,14 @@ unsigned long transparent_hugepage_flags __read_mostly =
 
 static struct shrinker deferred_split_shrinker;
 
-static atomic_t huge_zero_refcount;
+static refcount_t huge_zero_refcount;
 struct page *huge_zero_page __read_mostly;
 
 static struct page *get_huge_zero_page(void)
 {
 	struct page *zero_page;
 retry:
-	if (likely(atomic_inc_not_zero(&huge_zero_refcount)))
+	if (likely(refcount_inc_not_zero(&huge_zero_refcount)))
 		return READ_ONCE(huge_zero_page);
 
 	zero_page = alloc_pages((GFP_TRANSHUGE | __GFP_ZERO) & ~__GFP_MOVABLE,
@@ -81,7 +82,7 @@ static struct page *get_huge_zero_page(void)
 	}
 
 	/* We take additional reference here. It will be put back by shrinker */
-	atomic_set(&huge_zero_refcount, 2);
+	refcount_set(&huge_zero_refcount, 2);
 	preempt_enable();
 	return READ_ONCE(huge_zero_page);
 }
@@ -92,7 +93,7 @@ static void put_huge_zero_page(void)
 	 * Counter should never go to zero here. Only shrinker can put
 	 * last reference.
 	 */
-	BUG_ON(atomic_dec_and_test(&huge_zero_refcount));
+	BUG_ON(refcount_dec_and_test(&huge_zero_refcount));
 }
 
 struct page *mm_get_huge_zero_page(struct mm_struct *mm)
@@ -119,13 +120,16 @@ static unsigned long shrink_huge_zero_page_count(struct shrinker *shrink,
 					struct shrink_control *sc)
 {
 	/* we can free zero page only if last reference remains */
-	return atomic_read(&huge_zero_refcount) == 1 ? HPAGE_PMD_NR : 0;
+	return refcount_read(&huge_zero_refcount) == 1 ? HPAGE_PMD_NR : 0;
 }
 
 static unsigned long shrink_huge_zero_page_scan(struct shrinker *shrink,
 				       struct shrink_control *sc)
 {
-	if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) {
+	/* the below is probably not fully safe */
+	/* do we need to take a lock? */
+	if (refcount_read(&huge_zero_refcount) == 1) {
+		refcount_set(&huge_zero_refcount, 0);
 		struct page *zero_page = xchg(&huge_zero_page, NULL);
 		BUG_ON(zero_page == NULL);
 		__free_pages(zero_page, compound_order(zero_page));
diff --git a/mm/init-mm.c b/mm/init-mm.c
index 975e49f..8de5267 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -17,8 +17,8 @@
 struct mm_struct init_mm = {
 	.mm_rb		= RB_ROOT,
 	.pgd		= swapper_pg_dir,
-	.mm_users	= ATOMIC_INIT(2),
-	.mm_count	= ATOMIC_INIT(1),
+	.mm_users	= REFCOUNT_INIT(2),
+	.mm_count	= REFCOUNT_INIT(1),
 	.mmap_sem	= __RWSEM_INITIALIZER(init_mm.mmap_sem),
 	.page_table_lock =  __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
 	.mmlist		= LIST_HEAD_INIT(init_mm.mmlist),
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index e32389a..85f584a 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -391,7 +391,7 @@ static void insert_to_mm_slots_hash(struct mm_struct *mm,
 
 static inline int khugepaged_test_exit(struct mm_struct *mm)
 {
-	return atomic_read(&mm->mm_users) == 0;
+	return refcount_read(&mm->mm_users) == 0;
 }
 
 int __khugepaged_enter(struct mm_struct *mm)
@@ -420,7 +420,7 @@ int __khugepaged_enter(struct mm_struct *mm)
 	list_add_tail(&mm_slot->mm_node, &khugepaged_scan.mm_head);
 	spin_unlock(&khugepaged_mm_lock);
 
-	atomic_inc(&mm->mm_count);
+	refcount_inc(&mm->mm_count);
 	if (wakeup)
 		wake_up_interruptible(&khugepaged_wait);
 
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index da34369..2e1167b 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -105,7 +105,7 @@
 
 #include <asm/sections.h>
 #include <asm/processor.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include <linux/kasan.h>
 #include <linux/kmemcheck.h>
@@ -154,7 +154,7 @@ struct kmemleak_object {
 	struct rb_node rb_node;
 	struct rcu_head rcu;		/* object_list lockless traversal */
 	/* object usage count; object freed when use_count == 0 */
-	atomic_t use_count;
+	refcount_t use_count;
 	unsigned long pointer;
 	size_t size;
 	/* minimum number of a pointers found before it is considered leak */
@@ -434,7 +434,7 @@ static struct kmemleak_object *lookup_object(unsigned long ptr, int alias)
  */
 static int get_object(struct kmemleak_object *object)
 {
-	return atomic_inc_not_zero(&object->use_count);
+	return refcount_inc_not_zero(&object->use_count);
 }
 
 /*
@@ -467,7 +467,7 @@ static void free_object_rcu(struct rcu_head *rcu)
  */
 static void put_object(struct kmemleak_object *object)
 {
-	if (!atomic_dec_and_test(&object->use_count))
+	if (!refcount_dec_and_test(&object->use_count))
 		return;
 
 	/* should only get here after delete_object was called */
@@ -556,7 +556,7 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size,
 	INIT_LIST_HEAD(&object->gray_list);
 	INIT_HLIST_HEAD(&object->area_list);
 	spin_lock_init(&object->lock);
-	atomic_set(&object->use_count, 1);
+	refcount_set(&object->use_count, 1);
 	object->flags = OBJECT_ALLOCATED;
 	object->pointer = ptr;
 	object->size = size;
@@ -629,7 +629,7 @@ static void __delete_object(struct kmemleak_object *object)
 	unsigned long flags;
 
 	WARN_ON(!(object->flags & OBJECT_ALLOCATED));
-	WARN_ON(atomic_read(&object->use_count) < 1);
+	WARN_ON(refcount_read(&object->use_count) < 1);
 
 	/*
 	 * Locking here also ensures that the corresponding memory block
@@ -1396,9 +1396,9 @@ static void kmemleak_scan(void)
 		 * With a few exceptions there should be a maximum of
 		 * 1 reference to any object at this point.
 		 */
-		if (atomic_read(&object->use_count) > 1) {
+		if (refcount_read(&object->use_count) > 1) {
 			pr_debug("object->use_count = %d\n",
-				 atomic_read(&object->use_count));
+				 refcount_read(&object->use_count));
 			dump_object_info(object);
 		}
 #endif
diff --git a/mm/ksm.c b/mm/ksm.c
index 9ae6011..8076183 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -352,7 +352,7 @@ static void insert_to_mm_slots_hash(struct mm_struct *mm,
  */
 static inline bool ksm_test_exit(struct mm_struct *mm)
 {
-	return atomic_read(&mm->mm_users) == 0;
+	return refcount_read(&mm->mm_users) == 0;
 }
 
 /*
@@ -1813,7 +1813,7 @@ int __ksm_enter(struct mm_struct *mm)
 	spin_unlock(&ksm_mmlist_lock);
 
 	set_bit(MMF_VM_MERGEABLE, &mm->flags);
-	atomic_inc(&mm->mm_count);
+	refcount_inc(&mm->mm_count);
 
 	if (needs_wakeup)
 		wake_up_interruptible(&ksm_thread_wait);
diff --git a/mm/memory.c b/mm/memory.c
index 7d23b50..80abee8 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -375,7 +375,7 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
 	 * When there's less then two users of this mm there cannot be a
 	 * concurrent page-table walk.
 	 */
-	if (atomic_read(&tlb->mm->mm_users) < 2) {
+	if (refcount_read(&tlb->mm->mm_users) < 2) {
 		__tlb_remove_table(table);
 		return;
 	}
diff --git a/mm/mmu_context.c b/mm/mmu_context.c
index 6f4d27c..b5071e3 100644
--- a/mm/mmu_context.c
+++ b/mm/mmu_context.c
@@ -25,7 +25,7 @@ void use_mm(struct mm_struct *mm)
 	task_lock(tsk);
 	active_mm = tsk->active_mm;
 	if (active_mm != mm) {
-		atomic_inc(&mm->mm_count);
+		refcount_inc(&mm->mm_count);
 		tsk->active_mm = mm;
 	}
 	tsk->mm = mm;
diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
index f4259e4..00c2833 100644
--- a/mm/mmu_notifier.c
+++ b/mm/mmu_notifier.c
@@ -249,7 +249,7 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
 	struct mmu_notifier_mm *mmu_notifier_mm;
 	int ret;
 
-	BUG_ON(atomic_read(&mm->mm_users) <= 0);
+	BUG_ON(refcount_read(&mm->mm_users) <= 0);
 
 	/*
 	 * Verify that mmu_notifier_init() already run and the global srcu is
@@ -275,7 +275,7 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
 		mm->mmu_notifier_mm = mmu_notifier_mm;
 		mmu_notifier_mm = NULL;
 	}
-	atomic_inc(&mm->mm_count);
+	refcount_inc(&mm->mm_count);
 
 	/*
 	 * Serialize the update against mmu_notifier_unregister. A
@@ -295,7 +295,7 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
 		up_write(&mm->mmap_sem);
 	kfree(mmu_notifier_mm);
 out:
-	BUG_ON(atomic_read(&mm->mm_users) <= 0);
+	BUG_ON(refcount_read(&mm->mm_users) <= 0);
 	return ret;
 }
 
@@ -348,7 +348,7 @@ void __mmu_notifier_mm_destroy(struct mm_struct *mm)
  */
 void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
 {
-	BUG_ON(atomic_read(&mm->mm_count) <= 0);
+	BUG_ON(refcount_read(&mm->mm_count) <= 0);
 
 	if (!hlist_unhashed(&mn->hlist)) {
 		/*
@@ -381,7 +381,7 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
 	 */
 	synchronize_srcu(&srcu);
 
-	BUG_ON(atomic_read(&mm->mm_count) <= 0);
+	BUG_ON(refcount_read(&mm->mm_count) <= 0);
 
 	mmdrop(mm);
 }
@@ -401,7 +401,7 @@ void mmu_notifier_unregister_no_release(struct mmu_notifier *mn,
 	hlist_del_init_rcu(&mn->hlist);
 	spin_unlock(&mm->mmu_notifier_mm->lock);
 
-	BUG_ON(atomic_read(&mm->mm_count) <= 0);
+	BUG_ON(refcount_read(&mm->mm_count) <= 0);
 	mmdrop(mm);
 }
 EXPORT_SYMBOL_GPL(mmu_notifier_unregister_no_release);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index f9c07f5..59897ce 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -77,7 +77,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
 	/* Get target node for single threaded private VMAs */
 	if (prot_numa && !(vma->vm_flags & VM_SHARED) &&
-	    atomic_read(&vma->vm_mm->mm_users) == 1)
+	    refcount_read(&vma->vm_mm->mm_users) == 1)
 		target_node = numa_node_id();
 
 	arch_enter_lazy_mmu_mode();
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index ec9f11d..8a98e1b 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -660,7 +660,7 @@ static void mark_oom_victim(struct task_struct *tsk)
 
 	/* oom_mm is bound to the signal struct life time. */
 	if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm))
-		atomic_inc(&tsk->signal->oom_mm->mm_count);
+		refcount_inc(&tsk->signal->oom_mm->mm_count);
 
 	/*
 	 * Make sure that the task is woken up from uninterruptible sleep
@@ -781,7 +781,7 @@ static bool task_will_free_mem(struct task_struct *task)
 	if (test_bit(MMF_OOM_SKIP, &mm->flags))
 		return false;
 
-	if (atomic_read(&mm->mm_users) <= 1)
+	if (refcount_read(&mm->mm_users) <= 1)
 		return true;
 
 	/*
@@ -877,7 +877,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
 
 	/* Get a reference to safely compare mm after task_unlock(victim) */
 	mm = victim->mm;
-	atomic_inc(&mm->mm_count);
+	refcount_inc(&mm->mm_count);
 	/*
 	 * We should send SIGKILL before setting TIF_MEMDIE in order to prevent
 	 * the OOM victim from depleting the memory reserves from the user
diff --git a/mm/rmap.c b/mm/rmap.c
index 91619fd..47fbdfd 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -77,7 +77,7 @@ static inline struct anon_vma *anon_vma_alloc(void)
 
 	anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
 	if (anon_vma) {
-		atomic_set(&anon_vma->refcount, 1);
+		refcount_set(&anon_vma->refcount, 1);
 		anon_vma->degree = 1;	/* Reference for first vma */
 		anon_vma->parent = anon_vma;
 		/*
@@ -92,7 +92,7 @@ static inline struct anon_vma *anon_vma_alloc(void)
 
 static inline void anon_vma_free(struct anon_vma *anon_vma)
 {
-	VM_BUG_ON(atomic_read(&anon_vma->refcount));
+	VM_BUG_ON(refcount_read(&anon_vma->refcount));
 
 	/*
 	 * Synchronize against page_lock_anon_vma_read() such that
@@ -421,7 +421,7 @@ static void anon_vma_ctor(void *data)
 	struct anon_vma *anon_vma = data;
 
 	init_rwsem(&anon_vma->rwsem);
-	atomic_set(&anon_vma->refcount, 0);
+	refcount_set(&anon_vma->refcount, 0);
 	anon_vma->rb_root = RB_ROOT;
 }
 
@@ -470,7 +470,7 @@ struct anon_vma *page_get_anon_vma(struct page *page)
 		goto out;
 
 	anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON);
-	if (!atomic_inc_not_zero(&anon_vma->refcount)) {
+	if (!refcount_inc_not_zero(&anon_vma->refcount)) {
 		anon_vma = NULL;
 		goto out;
 	}
@@ -529,7 +529,7 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
 	}
 
 	/* trylock failed, we got to sleep */
-	if (!atomic_inc_not_zero(&anon_vma->refcount)) {
+	if (!refcount_inc_not_zero(&anon_vma->refcount)) {
 		anon_vma = NULL;
 		goto out;
 	}
@@ -544,7 +544,7 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
 	rcu_read_unlock();
 	anon_vma_lock_read(anon_vma);
 
-	if (atomic_dec_and_test(&anon_vma->refcount)) {
+	if (refcount_dec_and_test(&anon_vma->refcount)) {
 		/*
 		 * Oops, we held the last refcount, release the lock
 		 * and bail -- can't simply use put_anon_vma() because
@@ -1711,7 +1711,7 @@ void __put_anon_vma(struct anon_vma *anon_vma)
 	struct anon_vma *root = anon_vma->root;
 
 	anon_vma_free(anon_vma);
-	if (root != anon_vma && atomic_dec_and_test(&root->refcount))
+	if (root != anon_vma && refcount_dec_and_test(&root->refcount))
 		anon_vma_free(root);
 }
 
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 1c6e032..6e870f7 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1401,7 +1401,7 @@ int try_to_unuse(unsigned int type, bool frontswap,
 	 * that.
 	 */
 	start_mm = &init_mm;
-	atomic_inc(&init_mm.mm_users);
+	refcount_inc(&init_mm.mm_users);
 
 	/*
 	 * Keep on scanning until all entries have gone.  Usually,
@@ -1447,10 +1447,10 @@ int try_to_unuse(unsigned int type, bool frontswap,
 		/*
 		 * Don't hold on to start_mm if it looks like exiting.
 		 */
-		if (atomic_read(&start_mm->mm_users) == 1) {
+		if (refcount_read(&start_mm->mm_users) == 1) {
 			mmput(start_mm);
 			start_mm = &init_mm;
-			atomic_inc(&init_mm.mm_users);
+			refcount_inc(&init_mm.mm_users);
 		}
 
 		/*
@@ -1487,13 +1487,13 @@ int try_to_unuse(unsigned int type, bool frontswap,
 			struct mm_struct *prev_mm = start_mm;
 			struct mm_struct *mm;
 
-			atomic_inc(&new_start_mm->mm_users);
-			atomic_inc(&prev_mm->mm_users);
+			refcount_inc(&new_start_mm->mm_users);
+			refcount_inc(&prev_mm->mm_users);
 			spin_lock(&mmlist_lock);
 			while (swap_count(*swap_map) && !retval &&
 					(p = p->next) != &start_mm->mmlist) {
 				mm = list_entry(p, struct mm_struct, mmlist);
-				if (!atomic_inc_not_zero(&mm->mm_users))
+				if (!refcount_inc_not_zero(&mm->mm_users))
 					continue;
 				spin_unlock(&mmlist_lock);
 				mmput(prev_mm);
@@ -1511,7 +1511,7 @@ int try_to_unuse(unsigned int type, bool frontswap,
 
 				if (set_start_mm && *swap_map < swcount) {
 					mmput(new_start_mm);
-					atomic_inc(&mm->mm_users);
+					refcount_inc(&mm->mm_users);
 					new_start_mm = mm;
 					set_start_mm = 0;
 				}
diff --git a/mm/vmacache.c b/mm/vmacache.c
index 035fdeb..4747ee6 100644
--- a/mm/vmacache.c
+++ b/mm/vmacache.c
@@ -26,7 +26,7 @@ void vmacache_flush_all(struct mm_struct *mm)
 	 * to worry about other threads' seqnum. Current's
 	 * flush will occur upon the next lookup.
 	 */
-	if (atomic_read(&mm->mm_users) == 1)
+	if (refcount_read(&mm->mm_users) == 1)
 		return;
 
 	rcu_read_lock();
diff --git a/mm/zpool.c b/mm/zpool.c
index fd3ff71..48ec64f 100644
--- a/mm/zpool.c
+++ b/mm/zpool.c
@@ -56,11 +56,11 @@ EXPORT_SYMBOL(zpool_register_driver);
  */
 int zpool_unregister_driver(struct zpool_driver *driver)
 {
-	int ret = 0, refcount;
+	int ret = 0;
+	unsigned int refcount;
 
 	spin_lock(&drivers_lock);
 	refcount = atomic_read(&driver->refcount);
-	WARN_ON(refcount < 0);
 	if (refcount > 0)
 		ret = -EBUSY;
 	else
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 4d17376..8c2470b 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -137,7 +137,7 @@ struct rpc_cred null_cred = {
 	.cr_lru		= LIST_HEAD_INIT(null_cred.cr_lru),
 	.cr_auth	= &null_auth,
 	.cr_ops		= &null_credops,
-	.cr_count	= ATOMIC_INIT(1),
+	.cr_count	= REFCOUNT_INIT(1),
 	.cr_flags	= 1UL << RPCAUTH_CRED_UPTODATE,
 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
 	.cr_magic	= RPCAUTH_CRED_MAGIC,
diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c
index 3815e94..8a298fc 100644
--- a/virt/kvm/async_pf.c
+++ b/virt/kvm/async_pf.c
@@ -204,7 +204,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
 	work->addr = hva;
 	work->arch = *arch;
 	work->mm = current->mm;
-	atomic_inc(&work->mm->mm_users);
+	refcount_inc(&work->mm->mm_users);
 	kvm_get_kvm(work->vcpu->kvm);
 
 	/* this can't really happen otherwise gfn_to_pfn_async
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 482612b..5f8ebe5 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -616,13 +616,13 @@ static struct kvm *kvm_create_vm(unsigned long type)
 		return ERR_PTR(-ENOMEM);
 
 	spin_lock_init(&kvm->mmu_lock);
-	atomic_inc(&current->mm->mm_count);
+	refcount_inc(&current->mm->mm_count);
 	kvm->mm = current->mm;
 	kvm_eventfd_init(kvm);
 	mutex_init(&kvm->lock);
 	mutex_init(&kvm->irq_lock);
 	mutex_init(&kvm->slots_lock);
-	atomic_set(&kvm->users_count, 1);
+	refcount_set(&kvm->users_count, 1);
 	INIT_LIST_HEAD(&kvm->devices);
 
 	r = kvm_arch_init_vm(kvm, type);
@@ -745,13 +745,13 @@ static void kvm_destroy_vm(struct kvm *kvm)
 
 void kvm_get_kvm(struct kvm *kvm)
 {
-	atomic_inc(&kvm->users_count);
+	refcount_inc(&kvm->users_count);
 }
 EXPORT_SYMBOL_GPL(kvm_get_kvm);
 
 void kvm_put_kvm(struct kvm *kvm)
 {
-	if (atomic_dec_and_test(&kvm->users_count))
+	if (refcount_dec_and_test(&kvm->users_count))
 		kvm_destroy_vm(kvm);
 }
 EXPORT_SYMBOL_GPL(kvm_put_kvm);
@@ -3640,7 +3640,7 @@ static int kvm_debugfs_open(struct inode *inode, struct file *file,
 	 * To avoid the race between open and the removal of the debugfs
 	 * directory we test against the users count.
 	 */
-	if (!atomic_add_unless(&stat_data->kvm->users_count, 1, 0))
+	if (!refcount_inc_not_zero(&stat_data->kvm->users_count))
 		return -ENOENT;
 
 	if (simple_attr_open(inode, file, get, set, fmt)) {
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 09/18] net: convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (7 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 08/18] kernel, mm: convert from atomic_t to refcount_t Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18 18:39   ` [kernel-hardening] " David Windsor
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 10/18] fs: " Elena Reshetova
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 crypto/algif_aead.c                                |  2 +-
 drivers/atm/fore200e.c                             | 13 +++------
 drivers/atm/he.c                                   |  2 +-
 drivers/atm/idt77252.c                             |  4 +--
 drivers/infiniband/hw/nes/nes_cm.c                 |  4 +--
 drivers/isdn/mISDN/socket.c                        |  2 +-
 drivers/net/rionet.c                               |  2 +-
 drivers/net/vxlan.c                                | 10 +++----
 drivers/net/wireless/intel/ipw2x00/libipw_rx.c     |  8 ++---
 drivers/net/wireless/intel/ipw2x00/libipw_tx.c     |  4 +--
 .../net/wireless/intersil/hostap/hostap_80211_rx.c |  8 ++---
 .../net/wireless/intersil/hostap/hostap_80211_tx.c |  4 +--
 drivers/s390/net/ctcm_main.c                       | 26 ++++++++---------
 drivers/s390/net/netiucv.c                         | 10 +++----
 drivers/s390/net/qeth_core_main.c                  |  4 +--
 drivers/scsi/cxgbi/libcxgbi.h                      |  2 +-
 drivers/staging/rtl8192e/rtllib_rx.c               |  8 ++---
 drivers/staging/rtl8192e/rtllib_tx.c               |  4 +--
 .../staging/rtl8192u/ieee80211/ieee80211_crypt.c   |  2 +-
 .../staging/rtl8192u/ieee80211/ieee80211_crypt.h   |  3 +-
 drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c  |  8 ++---
 drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c  |  4 +--
 include/linux/atmdev.h                             |  9 +++---
 include/linux/ceph/libceph.h                       |  3 +-
 include/linux/ceph/osd_client.h                    |  3 +-
 include/linux/ceph/pagelist.h                      |  6 ++--
 include/linux/filter.h                             |  3 +-
 include/linux/igmp.h                               |  3 +-
 include/linux/inetdevice.h                         | 11 +++----
 include/linux/netpoll.h                            |  3 +-
 include/linux/skbuff.h                             | 23 ++++++++-------
 include/linux/sunrpc/auth.h                        |  8 ++---
 include/linux/sunrpc/auth_gss.h                    |  3 +-
 include/net/addrconf.h                             | 14 ++++-----
 include/net/af_unix.h                              |  3 +-
 include/net/arp.h                                  |  2 +-
 include/net/ax25.h                                 | 20 ++++++-------
 include/net/bluetooth/hci_core.h                   | 10 +++----
 include/net/bluetooth/rfcomm.h                     |  8 +++--
 include/net/calipso.h                              |  4 +--
 include/net/cipso_ipv4.h                           |  3 +-
 include/net/dn_fib.h                               |  5 ++--
 include/net/fib_rules.h                            |  7 +++--
 include/net/if_inet6.h                             |  9 +++---
 include/net/inet_frag.h                            |  4 +--
 include/net/inet_hashtables.h                      |  4 +--
 include/net/inetpeer.h                             |  4 +--
 include/net/ip_fib.h                               |  7 +++--
 include/net/ip_vs.h                                | 24 ++++++++-------
 include/net/ipv6.h                                 |  7 +++--
 include/net/ipx.h                                  | 13 +++++----
 include/net/lapb.h                                 |  3 +-
 include/net/lib80211.h                             |  2 +-
 include/net/llc.h                                  |  6 ++--
 include/net/lwtunnel.h                             |  7 +++--
 include/net/ndisc.h                                |  2 +-
 include/net/neighbour.h                            | 15 +++++-----
 include/net/net_namespace.h                        |  3 +-
 include/net/netfilter/br_netfilter.h               |  2 +-
 include/net/netfilter/nf_conntrack_expect.h        |  4 ++-
 include/net/netfilter/nf_conntrack_timeout.h       |  3 +-
 include/net/netlabel.h                             |  8 ++---
 include/net/netrom.h                               | 13 +++++----
 include/net/request_sock.h                         |  9 +++---
 include/net/sch_generic.h                          |  3 +-
 include/net/sctp/auth.h                            |  5 ++--
 include/net/sctp/structs.h                         |  8 ++---
 include/net/sock.h                                 | 25 ++++++++--------
 include/net/vxlan.h                                |  2 +-
 include/net/x25.h                                  | 15 +++++-----
 include/net/xfrm.h                                 | 21 ++++++-------
 net/atm/br2684.c                                   |  2 +-
 net/atm/clip.c                                     |  8 ++---
 net/atm/common.c                                   | 10 +++----
 net/atm/lec.c                                      | 11 +++----
 net/atm/lec_arpc.h                                 |  2 +-
 net/atm/mpc.c                                      |  4 +--
 net/atm/mpoa_caches.c                              | 26 ++++++++---------
 net/atm/mpoa_caches.h                              |  5 ++--
 net/atm/pppoatm.c                                  |  2 +-
 net/atm/proc.c                                     |  4 +--
 net/atm/raw.c                                      |  2 +-
 net/atm/resources.c                                |  2 +-
 net/atm/signaling.c                                |  2 +-
 net/ax25/af_ax25.c                                 |  2 +-
 net/ax25/ax25_route.c                              |  2 +-
 net/ax25/ax25_uid.c                                |  2 +-
 net/bluetooth/a2mp.c                               |  4 +--
 net/bluetooth/af_bluetooth.c                       |  2 +-
 net/bluetooth/hci_conn.c                           |  4 +--
 net/bluetooth/rfcomm/core.c                        |  4 +--
 net/bluetooth/rfcomm/sock.c                        |  2 +-
 net/bridge/br_netfilter_hooks.c                    |  4 +--
 net/bridge/br_private.h                            |  3 +-
 net/bridge/br_vlan.c                               |  8 ++---
 net/caif/caif_socket.c                             |  2 +-
 net/ceph/osd_client.c                              | 16 +++++-----
 net/ceph/pagelist.c                                |  2 +-
 net/ceph/snapshot.c                                |  6 ++--
 net/core/datagram.c                                | 10 +++----
 net/core/dev.c                                     | 10 +++----
 net/core/dst.c                                     |  7 +----
 net/core/fib_rules.c                               |  4 +--
 net/core/filter.c                                  |  6 ++--
 net/core/neighbour.c                               | 22 +++++++-------
 net/core/net-sysfs.c                               |  2 +-
 net/core/net_namespace.c                           |  4 +--
 net/core/netpoll.c                                 | 10 +++----
 net/core/pktgen.c                                  | 16 +++++-----
 net/core/rtnetlink.c                               |  2 +-
 net/core/skbuff.c                                  | 34 +++++++++++-----------
 net/core/sock.c                                    | 30 +++++++++----------
 net/dccp/ipv6.c                                    |  2 +-
 net/decnet/dn_fib.c                                |  6 ++--
 net/decnet/dn_neigh.c                              |  2 +-
 net/ipv4/af_inet.c                                 |  2 +-
 net/ipv4/cipso_ipv4.c                              | 16 +++++-----
 net/ipv4/devinet.c                                 |  2 +-
 net/ipv4/fib_semantics.c                           |  2 +-
 net/ipv4/fib_trie.c                                |  2 +-
 net/ipv4/igmp.c                                    | 10 +++----
 net/ipv4/inet_connection_sock.c                    |  2 +-
 net/ipv4/inet_fragment.c                           | 14 ++++-----
 net/ipv4/inet_hashtables.c                         |  4 +--
 net/ipv4/inet_timewait_sock.c                      |  8 ++---
 net/ipv4/inetpeer.c                                | 18 ++++++------
 net/ipv4/ip_fragment.c                             |  2 +-
 net/ipv4/ip_output.c                               |  6 ++--
 net/ipv4/netfilter/ipt_CLUSTERIP.c                 | 19 ++++++------
 net/ipv4/ping.c                                    |  4 +--
 net/ipv4/raw.c                                     |  2 +-
 net/ipv4/syncookies.c                              |  2 +-
 net/ipv4/tcp.c                                     |  4 +--
 net/ipv4/tcp_fastopen.c                            |  2 +-
 net/ipv4/tcp_ipv4.c                                |  4 +--
 net/ipv4/tcp_offload.c                             |  2 +-
 net/ipv4/tcp_output.c                              | 13 ++++-----
 net/ipv4/udp.c                                     |  6 ++--
 net/ipv4/udp_diag.c                                |  4 +--
 net/ipv6/addrconf.c                                |  4 +--
 net/ipv6/addrlabel.c                               |  9 +++---
 net/ipv6/anycast.c                                 |  6 ++--
 net/ipv6/calipso.c                                 | 16 +++++-----
 net/ipv6/datagram.c                                |  2 +-
 net/ipv6/exthdrs.c                                 |  4 +--
 net/ipv6/inet6_hashtables.c                        |  4 +--
 net/ipv6/ip6_output.c                              |  4 +--
 net/ipv6/ipv6_sockglue.c                           |  2 +-
 net/ipv6/mcast.c                                   | 18 ++++++------
 net/ipv6/syncookies.c                              |  2 +-
 net/ipv6/tcp_ipv6.c                                |  6 ++--
 net/ipv6/udp.c                                     |  2 +-
 net/ipv6/xfrm6_input.c                             |  2 +-
 net/ipv6/xfrm6_tunnel.c                            |  8 ++---
 net/ipx/af_ipx.c                                   |  6 ++--
 net/ipx/ipx_proc.c                                 |  2 +-
 net/ipx/ipx_route.c                                |  2 +-
 net/kcm/kcmproc.c                                  |  2 +-
 net/key/af_key.c                                   | 10 +++----
 net/l2tp/l2tp_core.c                               | 12 ++++----
 net/l2tp/l2tp_core.h                               | 13 +++++----
 net/l2tp/l2tp_debugfs.c                            |  6 ++--
 net/l2tp/l2tp_ppp.c                                |  2 +-
 net/lapb/lapb_iface.c                              |  6 ++--
 net/llc/llc_conn.c                                 |  8 ++---
 net/llc/llc_core.c                                 |  2 +-
 net/llc/llc_sap.c                                  |  2 +-
 net/netfilter/ipset/ip_set_hash_gen.h              | 19 ++++++------
 net/netfilter/ipvs/ip_vs_conn.c                    | 24 +++++++--------
 net/netfilter/ipvs/ip_vs_core.c                    |  4 +--
 net/netfilter/ipvs/ip_vs_ctl.c                     | 24 +++++++--------
 net/netfilter/ipvs/ip_vs_dh.c                      |  2 +-
 net/netfilter/ipvs/ip_vs_fo.c                      |  2 +-
 net/netfilter/ipvs/ip_vs_lblc.c                    |  4 +--
 net/netfilter/ipvs/ip_vs_lblcr.c                   |  8 ++---
 net/netfilter/ipvs/ip_vs_lc.c                      |  2 +-
 net/netfilter/ipvs/ip_vs_nq.c                      |  4 +--
 net/netfilter/ipvs/ip_vs_ovf.c                     |  2 +-
 net/netfilter/ipvs/ip_vs_pe_sip.c                  |  2 +-
 net/netfilter/ipvs/ip_vs_proto_sctp.c              |  2 +-
 net/netfilter/ipvs/ip_vs_proto_tcp.c               |  2 +-
 net/netfilter/ipvs/ip_vs_rr.c                      |  4 +--
 net/netfilter/ipvs/ip_vs_sed.c                     |  4 +--
 net/netfilter/ipvs/ip_vs_sh.c                      |  2 +-
 net/netfilter/ipvs/ip_vs_wlc.c                     |  4 +--
 net/netfilter/ipvs/ip_vs_wrr.c                     |  4 +--
 net/netfilter/nf_conntrack_core.c                  | 26 ++++++++---------
 net/netfilter/nf_conntrack_expect.c                | 12 ++++----
 net/netfilter/nf_conntrack_netlink.c               | 10 +++----
 net/netfilter/nf_conntrack_standalone.c            |  4 +--
 net/netfilter/nfnetlink_acct.c                     | 16 +++++-----
 net/netfilter/nfnetlink_cttimeout.c                | 12 ++++----
 net/netfilter/nfnetlink_log.c                      | 14 +++++----
 net/netfilter/nft_ct.c                             |  2 +-
 net/netfilter/xt_CT.c                              |  2 +-
 net/netfilter/xt_TPROXY.c                          |  4 +--
 net/netlink/af_netlink.c                           | 14 ++++-----
 net/netrom/nr_route.c                              |  6 ++--
 net/packet/af_packet.c                             | 14 ++++-----
 net/packet/internal.h                              |  4 ++-
 net/phonet/socket.c                                |  4 +--
 net/rds/ib.c                                       | 12 ++++----
 net/rds/ib.h                                       |  2 +-
 net/rds/ib_rdma.c                                  |  4 +--
 net/rds/message.c                                  | 12 ++++----
 net/rds/rdma.c                                     | 10 +++----
 net/rds/rds.h                                      |  9 +++---
 net/rds/recv.c                                     | 12 ++++----
 net/rds/tcp_send.c                                 |  2 +-
 net/rxrpc/af_rxrpc.c                               |  6 ++--
 net/rxrpc/skbuff.c                                 | 12 ++++----
 net/sched/em_meta.c                                |  2 +-
 net/sched/sch_api.c                                |  8 ++---
 net/sched/sch_atm.c                                |  2 +-
 net/sched/sch_generic.c                            |  8 ++---
 net/sctp/associola.c                               |  6 ++--
 net/sctp/auth.c                                    |  4 +--
 net/sctp/chunk.c                                   |  6 ++--
 net/sctp/endpointola.c                             |  6 ++--
 net/sctp/output.c                                  |  2 +-
 net/sctp/outqueue.c                                |  2 +-
 net/sctp/proc.c                                    |  2 +-
 net/sctp/sm_make_chunk.c                           |  6 ++--
 net/sctp/socket.c                                  |  6 ++--
 net/sctp/transport.c                               |  8 ++---
 net/sunrpc/auth.c                                  | 12 ++++----
 net/sunrpc/auth_gss/auth_gss.c                     | 29 +++++++++---------
 net/tipc/socket.c                                  |  2 +-
 net/unix/af_unix.c                                 | 16 +++++-----
 net/wireless/lib80211.c                            |  2 +-
 net/x25/x25_link.c                                 |  2 +-
 net/x25/x25_route.c                                |  2 +-
 net/xfrm/xfrm_input.c                              |  4 +--
 net/xfrm/xfrm_policy.c                             |  4 +--
 net/xfrm/xfrm_state.c                              |  4 +--
 235 files changed, 833 insertions(+), 791 deletions(-)

diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index f849311..cd37cc0 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -749,7 +749,7 @@ static void aead_sock_destruct(struct sock *sk)
 	unsigned int ivlen = crypto_aead_ivsize(
 				crypto_aead_reqtfm(&ctx->aead_req));
 
-	WARN_ON(atomic_read(&sk->sk_refcnt) != 0);
+	WARN_ON(refcount_read(&sk->sk_refcnt) != 0);
 	aead_put_sgl(sk);
 	sock_kzfree_s(sk, ctx->iv, ivlen);
 	sock_kfree_s(sk, ctx, ctx->len);
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 637c3e6..cd39f6f 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -924,12 +924,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
 		else {
 		    dev_kfree_skb_any(entry->skb);
 		}
-#if 1
-		/* race fixed by the above incarnation mechanism, but... */
-		if (atomic_read(&sk_atm(vcc)->sk_wmem_alloc) < 0) {
-		    atomic_set(&sk_atm(vcc)->sk_wmem_alloc, 0);
-		}
-#endif
+
 		/* check error condition */
 		if (*entry->status & STATUS_ERROR)
 		    atomic_inc(&vcc->stats->tx_err);
@@ -1130,12 +1125,12 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
 	return -ENOMEM;
     }
 
-    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
+    ASSERT(refcount_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
 
     vcc->push(vcc, skb);
     atomic_inc(&vcc->stats->rx);
 
-    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
+    ASSERT(refcount_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
 
     return 0;
 }
@@ -1572,7 +1567,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
     unsigned long           flags;
 
     ASSERT(vcc);
-    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
+    ASSERT(refcount_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
     ASSERT(fore200e);
     ASSERT(fore200e_vcc);
 
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 3617659..fc1bbdb 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -2395,7 +2395,7 @@ he_close(struct atm_vcc *vcc)
 		 * TBRQ, the host issues the close command to the adapter.
 		 */
 
-		while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) &&
+		while (((tx_inuse = refcount_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) &&
 		       (retry < MAX_RETRY)) {
 			msleep(sleep);
 			if (sleep < 250)
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 471ddfd..fffdc49 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -724,7 +724,7 @@ push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
 		struct sock *sk = sk_atm(vcc);
 
 		vc->estimator->cells += (skb->len + 47) / 48;
-		if (atomic_read(&sk->sk_wmem_alloc) >
+		if (refcount_read(&sk->sk_wmem_alloc) >
 		    (sk->sk_sndbuf >> 1)) {
 			u32 cps = vc->estimator->maxcps;
 
@@ -2012,7 +2012,7 @@ idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)
 		atomic_inc(&vcc->stats->tx_err);
 		return -ENOMEM;
 	}
-	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 
 	memcpy(skb_put(skb, 52), cell, 52);
 
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 8e70347..53eb47b 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -743,7 +743,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
 
 	if (type == NES_TIMER_TYPE_SEND) {
 		new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
-		atomic_inc(&new_send->skb->users);
+		refcount_inc(&new_send->skb->users);
 		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
 		cm_node->send_entry = new_send;
 		add_ref_cm_node(cm_node);
@@ -925,7 +925,7 @@ static void nes_cm_timer_tick(unsigned long pass)
 						  flags);
 				break;
 			}
-			atomic_inc(&send_entry->skb->users);
+			refcount_inc(&send_entry->skb->users);
 			cm_packets_retrans++;
 			nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
 				  "for node %p, jiffies = %lu, time to send = "
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 99e5f97..c5603d1 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -155,7 +155,7 @@ mISDN_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 	copied = skb->len + MISDN_HEADER_LEN;
 	if (len < copied) {
 		if (flags & MSG_PEEK)
-			atomic_dec(&skb->users);
+			refcount_dec(&skb->users);
 		else
 			skb_queue_head(&sk->sk_receive_queue, skb);
 		return -ENOSPC;
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 300bb14..e9f101c 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -201,7 +201,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 				rionet_queue_tx_msg(skb, ndev,
 					nets[rnet->mport->id].active[i]);
 				if (count)
-					atomic_inc(&skb->users);
+					refcount_inc(&skb->users);
 				count++;
 			}
 	} else if (RIONET_MAC_MATCH(eth->h_dest)) {
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index bb70dd5..50d9ad8 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -958,11 +958,11 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
 	/* The vxlan_sock is only used by dev, leaving group has
 	 * no effect on other vxlan devices.
 	 */
-	if (family == AF_INET && sock4 && atomic_read(&sock4->refcnt) == 1)
+	if (family == AF_INET && sock4 && refcount_read(&sock4->refcnt) == 1)
 		return false;
 #if IS_ENABLED(CONFIG_IPV6)
 	sock6 = rtnl_dereference(dev->vn6_sock);
-	if (family == AF_INET6 && sock6 && atomic_read(&sock6->refcnt) == 1)
+	if (family == AF_INET6 && sock6 && refcount_read(&sock6->refcnt) == 1)
 		return false;
 #endif
 
@@ -999,7 +999,7 @@ static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
 
 	if (!vs)
 		return false;
-	if (!atomic_dec_and_test(&vs->refcnt))
+	if (!refcount_dec_and_test(&vs->refcnt))
 		return false;
 
 	vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id);
@@ -2699,7 +2699,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
 	}
 
 	vs->sock = sock;
-	atomic_set(&vs->refcnt, 1);
+	refcount_set(&vs->refcnt, 1);
 	vs->flags = (flags & VXLAN_F_RCV_FLAGS);
 
 	spin_lock(&vn->sock_lock);
@@ -2733,7 +2733,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
 		spin_lock(&vn->sock_lock);
 		vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
 				     vxlan->cfg.dst_port, vxlan->flags);
-		if (vs && !atomic_add_unless(&vs->refcnt, 1, 0)) {
+		if (vs && !refcount_inc_not_zero(&vs->refcnt)) {
 			spin_unlock(&vn->sock_lock);
 			return -EBUSY;
 		}
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
index 6df19f0..61a5b19 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
@@ -281,9 +281,9 @@ libipw_rx_frame_decrypt(struct libipw_device *ieee, struct sk_buff *skb,
 	hdr = (struct libipw_hdr_3addr *)skb->data;
 	hdrlen = libipw_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		LIBIPW_DEBUG_DROP("decryption failed (SA=%pM) res=%d\n",
 				     hdr->addr2, res);
@@ -313,9 +313,9 @@ libipw_rx_frame_decrypt_msdu(struct libipw_device *ieee,
 	hdr = (struct libipw_hdr_3addr *)skb->data;
 	hdrlen = libipw_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
 		       " (SA=%pM keyidx=%d)\n", ieee->dev->name, hdr->addr2,
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
index 048f1e3..c616089 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
@@ -161,12 +161,12 @@ static int libipw_encrypt_fragment(struct libipw_device *ieee,
 
 	/* To encrypt, frame format is:
 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = 0;
 	if (crypt->ops && crypt->ops->encrypt_mpdu)
 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
 
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
 		       ieee->dev->name, frag->len);
diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
index 34dbddb..9c5cadf 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
@@ -669,9 +669,9 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
 		return -1;
 	}
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: decryption failed (SA=%pM) res=%d\n",
 		       local->dev->name, hdr->addr2, res);
@@ -697,9 +697,9 @@ hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
 	hdr = (struct ieee80211_hdr *) skb->data;
 	hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
 		       " (SA=%pM keyidx=%d)\n",
diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
index 055e11d..810e9ba 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
@@ -359,13 +359,13 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
 
 	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
 	 * call both MSDU and MPDU encryption functions from here. */
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = 0;
 	if (crypt->ops->encrypt_msdu)
 		res = crypt->ops->encrypt_msdu(skb, hdr_len, crypt->priv);
 	if (res == 0 && crypt->ops->encrypt_mpdu)
 		res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		kfree_skb(skb);
 		return NULL;
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index ac65f12..d079d02 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -483,7 +483,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
 			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
 			return -EBUSY;
 		} else {
-			atomic_inc(&skb->users);
+			refcount_inc(&skb->users);
 			header.length = l;
 			header.type = skb->protocol;
 			header.unused = 0;
@@ -500,7 +500,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
 	 * Protect skb against beeing free'd by upper
 	 * layers.
 	 */
-	atomic_inc(&skb->users);
+	refcount_inc(&skb->users);
 	ch->prof.txlen += skb->len;
 	header.length = skb->len + LL_HEADER_LENGTH;
 	header.type = skb->protocol;
@@ -517,14 +517,14 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
 	if (hi) {
 		nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
 		if (!nskb) {
-			atomic_dec(&skb->users);
+			refcount_dec(&skb->users);
 			skb_pull(skb, LL_HEADER_LENGTH + 2);
 			ctcm_clear_busy(ch->netdev);
 			return -ENOMEM;
 		} else {
 			memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
-			atomic_inc(&nskb->users);
-			atomic_dec(&skb->users);
+			refcount_inc(&nskb->users);
+			refcount_dec(&skb->users);
 			dev_kfree_skb_irq(skb);
 			skb = nskb;
 		}
@@ -542,7 +542,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
 			 * Remove our header. It gets added
 			 * again on retransmit.
 			 */
-			atomic_dec(&skb->users);
+			refcount_dec(&skb->users);
 			skb_pull(skb, LL_HEADER_LENGTH + 2);
 			ctcm_clear_busy(ch->netdev);
 			return -ENOMEM;
@@ -553,7 +553,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
 		ch->ccw[1].count = skb->len;
 		skb_copy_from_linear_data(skb,
 				skb_put(ch->trans_skb, skb->len), skb->len);
-		atomic_dec(&skb->users);
+		refcount_dec(&skb->users);
 		dev_kfree_skb_irq(skb);
 		ccw_idx = 0;
 	} else {
@@ -679,7 +679,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
 
 	if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
 		spin_lock_irqsave(&ch->collect_lock, saveflags);
-		atomic_inc(&skb->users);
+		refcount_inc(&skb->users);
 		p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
 
 		if (!p_header) {
@@ -716,7 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
 	 * Protect skb against beeing free'd by upper
 	 * layers.
 	 */
-	atomic_inc(&skb->users);
+	refcount_inc(&skb->users);
 
 	/*
 	 * IDAL support in CTCM is broken, so we have to
@@ -729,8 +729,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
 			goto nomem_exit;
 		} else {
 			memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
-			atomic_inc(&nskb->users);
-			atomic_dec(&skb->users);
+			refcount_inc(&nskb->users);
+			refcount_dec(&skb->users);
 			dev_kfree_skb_irq(skb);
 			skb = nskb;
 		}
@@ -810,7 +810,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
 		ch->trans_skb->len = 0;
 		ch->ccw[1].count = skb->len;
 		memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
-		atomic_dec(&skb->users);
+		refcount_dec(&skb->users);
 		dev_kfree_skb_irq(skb);
 		ccw_idx = 0;
 		CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
@@ -855,7 +855,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
 			"%s(%s): MEMORY allocation ERROR\n",
 			CTCM_FUNTAIL, ch->id);
 	rc = -ENOMEM;
-	atomic_dec(&skb->users);
+	refcount_dec(&skb->users);
 	dev_kfree_skb_any(skb);
 	fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
 done:
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 3f85b97..44fd71c 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -743,7 +743,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
 	conn->prof.tx_pending--;
 	if (single_flag) {
 		if ((skb = skb_dequeue(&conn->commit_queue))) {
-			atomic_dec(&skb->users);
+			refcount_dec(&skb->users);
 			if (privptr) {
 				privptr->stats.tx_packets++;
 				privptr->stats.tx_bytes +=
@@ -767,7 +767,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
 		txbytes += skb->len;
 		txpackets++;
 		stat_maxcq++;
-		atomic_dec(&skb->users);
+		refcount_dec(&skb->users);
 		dev_kfree_skb_any(skb);
 	}
 	if (conn->collect_len > conn->prof.maxmulti)
@@ -959,7 +959,7 @@ static void netiucv_purge_skb_queue(struct sk_buff_head *q)
 	struct sk_buff *skb;
 
 	while ((skb = skb_dequeue(q))) {
-		atomic_dec(&skb->users);
+		refcount_dec(&skb->users);
 		dev_kfree_skb_any(skb);
 	}
 }
@@ -1177,7 +1177,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
 			IUCV_DBF_TEXT(data, 2,
 				      "EBUSY from netiucv_transmit_skb\n");
 		} else {
-			atomic_inc(&skb->users);
+			refcount_inc(&skb->users);
 			skb_queue_tail(&conn->collect_queue, skb);
 			conn->collect_len += l;
 			rc = 0;
@@ -1247,7 +1247,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
 		} else {
 			if (copied)
 				dev_kfree_skb(skb);
-			atomic_inc(&nskb->users);
+			refcount_inc(&nskb->users);
 			skb_queue_tail(&conn->commit_queue, nskb);
 		}
 	}
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index e335583..e6ebcd7 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1239,7 +1239,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
 				iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR);
 			}
 		}
-		atomic_dec(&skb->users);
+		refcount_dec(&skb->users);
 		dev_kfree_skb_any(skb);
 		skb = skb_dequeue(&buf->skb_list);
 	}
@@ -3970,7 +3970,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
 	int flush_cnt = 0, hdr_len, large_send = 0;
 
 	buffer = buf->buffer;
-	atomic_inc(&skb->users);
+	refcount_inc(&skb->users);
 	skb_queue_tail(&buf->skb_list, skb);
 
 	/*check first on TSO ....*/
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 18e0ea8..9584b062 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -378,7 +378,7 @@ static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk,
 	 * just one user currently so we use atomic_set rather than skb_get
 	 * to avoid the atomic op.
 	 */
-	atomic_set(&skb->users, 2);
+	refcount_set(&skb->users, 2);
 
 	if (!csk->wr_pending_head)
 		csk->wr_pending_head = skb;
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index e5ba7d1..2f72ee5 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -310,9 +310,9 @@ rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
 	hdr = (struct rtllib_hdr_4addr *) skb->data;
 	hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		netdev_dbg(ieee->dev, "decryption failed (SA= %pM) res=%d\n",
 			   hdr->addr2, res);
@@ -350,9 +350,9 @@ rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb,
 	hdr = (struct rtllib_hdr_4addr *) skb->data;
 	hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		netdev_dbg(ieee->dev,
 			   "MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n",
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
index 78a3ad5..796580a 100644
--- a/drivers/staging/rtl8192e/rtllib_tx.c
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -190,14 +190,14 @@ int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
 	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
 	 * call both MSDU and MPDU encryption functions from here.
 	 */
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = 0;
 	if (crypt->ops->encrypt_msdu)
 		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
 	if (res == 0 && crypt->ops->encrypt_mpdu)
 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
 
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		netdev_info(ieee->dev, "%s: Encryption failed: len=%d.\n",
 			    ieee->dev->name, frag->len);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
index 9cf90d0..b6d5673 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
@@ -46,7 +46,7 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
 	     ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
 		entry = list_entry(ptr, struct ieee80211_crypt_data, list);
 
-		if (atomic_read(&entry->refcnt) != 0 && !force)
+		if (refcount_read(&entry->refcnt) != 0 && !force)
 			continue;
 
 		list_del(ptr);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
index 0b4ea43..01718c1 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
@@ -23,6 +23,7 @@
 #ifndef IEEE80211_CRYPT_H
 #define IEEE80211_CRYPT_H
 
+#include <linux/refcount.h>
 #include <linux/skbuff.h>
 
 struct ieee80211_crypto_ops {
@@ -72,7 +73,7 @@ struct ieee80211_crypt_data {
 	struct list_head list; /* delayed deletion list */
 	struct ieee80211_crypto_ops *ops;
 	void *priv;
-	atomic_t refcnt;
+	refcount_t refcnt;
 };
 
 int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 82f6543..1157a72 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -361,9 +361,9 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
 		return -1;
 	}
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		IEEE80211_DEBUG_DROP(
 			"decryption failed (SA=%pM"
@@ -399,9 +399,9 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s
 	hdr = (struct rtl_80211_hdr_4addr *) skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
 		       " (SA=%pM keyidx=%d)\n",
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index 1ab0aea..014e53f 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -210,14 +210,14 @@ int ieee80211_encrypt_fragment(
 	// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
 	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
 	 * call both MSDU and MPDU encryption functions from here. */
-	atomic_inc(&crypt->refcnt);
+	refcount_inc(&crypt->refcnt);
 	res = 0;
 	if (crypt->ops->encrypt_msdu)
 		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
 	if (res == 0 && crypt->ops->encrypt_mpdu)
 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
 
-	atomic_dec(&crypt->refcnt);
+	refcount_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
 		       ieee->dev->name, frag->len);
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index c1da539..0ec9bdb 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -11,6 +11,7 @@
 #include <linux/uio.h>
 #include <net/sock.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <uapi/linux/atmdev.h>
 
 #ifdef CONFIG_PROC_FS
@@ -158,7 +159,7 @@ struct atm_dev {
 	struct k_atm_dev_stats stats;	/* statistics */
 	char		signal;		/* signal status (ATM_PHY_SIG_*) */
 	int		link_rate;	/* link rate (default: OC3) */
-	atomic_t	refcnt;		/* reference count */
+	refcount_t	refcnt;		/* reference count */
 	spinlock_t	lock;		/* protect internal members */
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *proc_entry; /* proc entry */
@@ -254,20 +255,20 @@ static inline void atm_return(struct atm_vcc *vcc,int truesize)
 
 static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
 {
-	return (size + atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) <
+	return (size + refcount_read(&sk_atm(vcc)->sk_wmem_alloc)) <
 	       sk_atm(vcc)->sk_sndbuf;
 }
 
 
 static inline void atm_dev_hold(struct atm_dev *dev)
 {
-	atomic_inc(&dev->refcnt);
+	refcount_inc(&dev->refcnt);
 }
 
 
 static inline void atm_dev_put(struct atm_dev *dev)
 {
-	if (atomic_dec_and_test(&dev->refcnt)) {
+	if (refcount_dec_and_test(&dev->refcnt)) {
 		BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags));
 		if (dev->ops->dev_close)
 			dev->ops->dev_close(dev);
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 1816c5e..26dc674 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -14,6 +14,7 @@
 #include <linux/wait.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/types.h>
 #include <linux/ceph/messenger.h>
@@ -159,7 +160,7 @@ struct ceph_client {
  * dirtied.
  */
 struct ceph_snap_context {
-	atomic_t nref;
+	refcount_t nref;
 	u64 seq;
 	u32 num_snaps;
 	u64 snaps[];
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index 03a6653..bd0db58 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -5,6 +5,7 @@
 #include <linux/kref.h>
 #include <linux/mempool.h>
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/types.h>
 #include <linux/ceph/osdmap.h>
@@ -28,7 +29,7 @@ typedef void (*ceph_osdc_unsafe_callback_t)(struct ceph_osd_request *, bool);
 
 /* a given osd we're communicating with */
 struct ceph_osd {
-	atomic_t o_ref;
+	refcount_t o_ref;
 	struct ceph_osd_client *o_osdc;
 	int o_osd;
 	int o_incarnation;
diff --git a/include/linux/ceph/pagelist.h b/include/linux/ceph/pagelist.h
index 13d71fe..75a7db2 100644
--- a/include/linux/ceph/pagelist.h
+++ b/include/linux/ceph/pagelist.h
@@ -2,7 +2,7 @@
 #define __FS_CEPH_PAGELIST_H
 
 #include <asm/byteorder.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/list.h>
 #include <linux/types.h>
 
@@ -13,7 +13,7 @@ struct ceph_pagelist {
 	size_t room;
 	struct list_head free_list;
 	size_t num_pages_free;
-	atomic_t refcnt;
+	refcount_t refcnt;
 };
 
 struct ceph_pagelist_cursor {
@@ -30,7 +30,7 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
 	pl->room = 0;
 	INIT_LIST_HEAD(&pl->free_list);
 	pl->num_pages_free = 0;
-	atomic_set(&pl->refcnt, 1);
+	refcount_set(&pl->refcnt, 1);
 }
 
 extern void ceph_pagelist_release(struct ceph_pagelist *pl);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index a0934e6..f994406 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -7,6 +7,7 @@
 #include <stdarg.h>
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/compat.h>
 #include <linux/skbuff.h>
 #include <linux/linkage.h>
@@ -421,7 +422,7 @@ struct bpf_prog {
 };
 
 struct sk_filter {
-	atomic_t	refcnt;
+	refcount_t	refcnt;
 	struct rcu_head	rcu;
 	struct bpf_prog	*prog;
 };
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 12f6fba..97caf18 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -18,6 +18,7 @@
 #include <linux/skbuff.h>
 #include <linux/timer.h>
 #include <linux/in.h>
+#include <linux/refcount.h>
 #include <uapi/linux/igmp.h>
 
 static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
@@ -84,7 +85,7 @@ struct ip_mc_list {
 	struct ip_mc_list __rcu *next_hash;
 	struct timer_list	timer;
 	int			users;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	spinlock_t		lock;
 	char			tm_running;
 	char			reporter;
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index ee971f3..5cd9671 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -11,6 +11,7 @@
 #include <linux/timer.h>
 #include <linux/sysctl.h>
 #include <linux/rtnetlink.h>
+#include <linux/refcount.h>
 
 struct ipv4_devconf {
 	void	*sysctl;
@@ -22,7 +23,7 @@ struct ipv4_devconf {
 
 struct in_device {
 	struct net_device	*dev;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	int			dead;
 	struct in_ifaddr	*ifa_list;	/* IP ifaddr chain		*/
 
@@ -212,7 +213,7 @@ static inline struct in_device *in_dev_get(const struct net_device *dev)
 	rcu_read_lock();
 	in_dev = __in_dev_get_rcu(dev);
 	if (in_dev)
-		atomic_inc(&in_dev->refcnt);
+		refcount_inc(&in_dev->refcnt);
 	rcu_read_unlock();
 	return in_dev;
 }
@@ -233,12 +234,12 @@ void in_dev_finish_destroy(struct in_device *idev);
 
 static inline void in_dev_put(struct in_device *idev)
 {
-	if (atomic_dec_and_test(&idev->refcnt))
+	if (refcount_dec_and_test(&idev->refcnt))
 		in_dev_finish_destroy(idev);
 }
 
-#define __in_dev_put(idev)  atomic_dec(&(idev)->refcnt)
-#define in_dev_hold(idev)   atomic_inc(&(idev)->refcnt)
+#define __in_dev_put(idev)  refcount_dec(&(idev)->refcnt)
+#define in_dev_hold(idev)   refcount_inc(&(idev)->refcnt)
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 1828900..27c0aaa 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/rcupdate.h>
 #include <linux/list.h>
+#include <linux/refcount.h>
 
 union inet_addr {
 	__u32		all[4];
@@ -34,7 +35,7 @@ struct netpoll {
 };
 
 struct netpoll_info {
-	atomic_t refcnt;
+	refcount_t refcnt;
 
 	struct semaphore dev_lock;
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b53c0cf..12b8444 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -24,6 +24,7 @@
 #include <linux/socket.h>
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <asm/types.h>
 #include <linux/spinlock.h>
 #include <linux/net.h>
@@ -243,13 +244,13 @@ struct napi_struct;
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 struct nf_conntrack {
-	atomic_t use;
+	refcount_t use;
 };
 #endif
 
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 struct nf_bridge_info {
-	atomic_t		use;
+	refcount_t		use;
 	enum {
 		BRNF_PROTO_UNCHANGED,
 		BRNF_PROTO_8021Q,
@@ -809,7 +810,7 @@ struct sk_buff {
 	unsigned char		*head,
 				*data;
 	unsigned int		truesize;
-	atomic_t		users;
+	refcount_t		users;
 };
 
 #ifdef __KERNEL__
@@ -938,7 +939,7 @@ struct sk_buff_fclones {
 
 	struct sk_buff	skb2;
 
-	atomic_t	fclone_ref;
+	refcount_t	fclone_ref;
 };
 
 /**
@@ -958,7 +959,7 @@ static inline bool skb_fclone_busy(const struct sock *sk,
 	fclones = container_of(skb, struct sk_buff_fclones, skb1);
 
 	return skb->fclone == SKB_FCLONE_ORIG &&
-	       atomic_read(&fclones->fclone_ref) > 1 &&
+	       refcount_read(&fclones->fclone_ref) > 1 &&
 	       fclones->skb2.sk == sk;
 }
 
@@ -1306,7 +1307,7 @@ static inline struct sk_buff *skb_queue_prev(const struct sk_buff_head *list,
  */
 static inline struct sk_buff *skb_get(struct sk_buff *skb)
 {
-	atomic_inc(&skb->users);
+	refcount_inc(&skb->users);
 	return skb;
 }
 
@@ -1407,7 +1408,7 @@ static inline void __skb_header_release(struct sk_buff *skb)
  */
 static inline int skb_shared(const struct sk_buff *skb)
 {
-	return atomic_read(&skb->users) != 1;
+	return refcount_read(&skb->users) != 1;
 }
 
 /**
@@ -3557,25 +3558,25 @@ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr,
 void nf_conntrack_destroy(struct nf_conntrack *nfct);
 static inline void nf_conntrack_put(struct nf_conntrack *nfct)
 {
-	if (nfct && atomic_dec_and_test(&nfct->use))
+	if (nfct && refcount_dec_and_test(&nfct->use))
 		nf_conntrack_destroy(nfct);
 }
 static inline void nf_conntrack_get(struct nf_conntrack *nfct)
 {
 	if (nfct)
-		atomic_inc(&nfct->use);
+		refcount_inc(&nfct->use);
 }
 #endif
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
 {
-	if (nf_bridge && atomic_dec_and_test(&nf_bridge->use))
+	if (nf_bridge && refcount_dec_and_test(&nf_bridge->use))
 		kfree(nf_bridge);
 }
 static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
 {
 	if (nf_bridge)
-		atomic_inc(&nf_bridge->use);
+		refcount_inc(&nf_bridge->use);
 }
 #endif /* CONFIG_BRIDGE_NETFILTER */
 static inline void nf_reset(struct sk_buff *skb)
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index b1bc62b..bd36e0b 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -15,7 +15,7 @@
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/xdr.h>
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/rcupdate.h>
 #include <linux/uidgid.h>
 #include <linux/utsname.h>
@@ -68,7 +68,7 @@ struct rpc_cred {
 #endif
 	unsigned long		cr_expire;	/* when to gc */
 	unsigned long		cr_flags;	/* various flags */
-	atomic_t		cr_count;	/* ref count */
+	refcount_t		cr_count;	/* ref count */
 
 	kuid_t			cr_uid;
 
@@ -209,7 +209,7 @@ static inline
 struct rpc_cred *	get_rpccred(struct rpc_cred *cred)
 {
 	if (cred != NULL)
-		atomic_inc(&cred->cr_count);
+		refcount_inc(&cred->cr_count);
 	return cred;
 }
 
@@ -226,7 +226,7 @@ struct rpc_cred *	get_rpccred(struct rpc_cred *cred)
 static inline struct rpc_cred *
 get_rpccred_rcu(struct rpc_cred *cred)
 {
-	if (atomic_inc_not_zero(&cred->cr_count))
+	if (refcount_inc_not_zero(&cred->cr_count))
 		return cred;
 	return NULL;
 }
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 36eebc4..cebdf87 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -13,6 +13,7 @@
 #define _LINUX_SUNRPC_AUTH_GSS_H
 
 #ifdef __KERNEL__
+#include <linux/refcount.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/gss_api.h>
@@ -65,7 +66,7 @@ struct rpc_gss_init_res {
  * the wire when communicating with a server. */
 
 struct gss_cl_ctx {
-	atomic_t		count;
+	refcount_t		count;
 	enum rpc_gss_proc	gc_proc;
 	u32			gc_seq;
 	spinlock_t		gc_seq_lock;
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 8f998af..7caa848 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -294,7 +294,7 @@ static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
 	rcu_read_lock();
 	idev = rcu_dereference(dev->ip6_ptr);
 	if (idev)
-		atomic_inc(&idev->refcnt);
+		refcount_inc(&idev->refcnt);
 	rcu_read_unlock();
 	return idev;
 }
@@ -310,36 +310,36 @@ void in6_dev_finish_destroy(struct inet6_dev *idev);
 
 static inline void in6_dev_put(struct inet6_dev *idev)
 {
-	if (atomic_dec_and_test(&idev->refcnt))
+	if (refcount_dec_and_test(&idev->refcnt))
 		in6_dev_finish_destroy(idev);
 }
 
 static inline void __in6_dev_put(struct inet6_dev *idev)
 {
-	atomic_dec(&idev->refcnt);
+	refcount_dec(&idev->refcnt);
 }
 
 static inline void in6_dev_hold(struct inet6_dev *idev)
 {
-	atomic_inc(&idev->refcnt);
+	refcount_inc(&idev->refcnt);
 }
 
 void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
 
 static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
 {
-	if (atomic_dec_and_test(&ifp->refcnt))
+	if (refcount_dec_and_test(&ifp->refcnt))
 		inet6_ifa_finish_destroy(ifp);
 }
 
 static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
 {
-	atomic_dec(&ifp->refcnt);
+	refcount_dec(&ifp->refcnt);
 }
 
 static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
 {
-	atomic_inc(&ifp->refcnt);
+	refcount_inc(&ifp->refcnt);
 }
 
 
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index fd60ecc..3a385e4 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -4,6 +4,7 @@
 #include <linux/socket.h>
 #include <linux/un.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <net/sock.h>
 
 void unix_inflight(struct user_struct *user, struct file *fp);
@@ -21,7 +22,7 @@ extern spinlock_t unix_table_lock;
 extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
 
 struct unix_address {
-	atomic_t	refcnt;
+	refcount_t	refcnt;
 	int		len;
 	unsigned int	hash;
 	struct sockaddr_un name[0];
diff --git a/include/net/arp.h b/include/net/arp.h
index 5e0f891..95cfce4 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -28,7 +28,7 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32
 
 	rcu_read_lock_bh();
 	n = __ipv4_neigh_lookup_noref(dev, key);
-	if (n && !atomic_inc_not_zero(&n->refcnt))
+	if (n && !refcount_inc_not_zero(&n->refcnt))
 		n = NULL;
 	rcu_read_unlock_bh();
 
diff --git a/include/net/ax25.h b/include/net/ax25.h
index e602f81..c4a0cf6 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -11,7 +11,7 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <net/neighbour.h>
 #include <net/sock.h>
 
@@ -158,7 +158,7 @@ enum {
 
 typedef struct ax25_uid_assoc {
 	struct hlist_node	uid_node;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	kuid_t			uid;
 	ax25_address		call;
 } ax25_uid_assoc;
@@ -167,11 +167,11 @@ typedef struct ax25_uid_assoc {
 	hlist_for_each_entry(__ax25, list, uid_node)
 
 #define ax25_uid_hold(ax25) \
-	atomic_inc(&((ax25)->refcount))
+	refcount_inc(&((ax25)->refcount))
 
 static inline void ax25_uid_put(ax25_uid_assoc *assoc)
 {
-	if (atomic_dec_and_test(&assoc->refcount)) {
+	if (refcount_dec_and_test(&assoc->refcount)) {
 		kfree(assoc);
 	}
 }
@@ -185,7 +185,7 @@ typedef struct {
 
 typedef struct ax25_route {
 	struct ax25_route	*next;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	ax25_address		callsign;
 	struct net_device	*dev;
 	ax25_digi		*digipeat;
@@ -194,14 +194,14 @@ typedef struct ax25_route {
 
 static inline void ax25_hold_route(ax25_route *ax25_rt)
 {
-	atomic_inc(&ax25_rt->refcount);
+	refcount_inc(&ax25_rt->refcount);
 }
 
 void __ax25_put_route(ax25_route *ax25_rt);
 
 static inline void ax25_put_route(ax25_route *ax25_rt)
 {
-	if (atomic_dec_and_test(&ax25_rt->refcount))
+	if (refcount_dec_and_test(&ax25_rt->refcount))
 		__ax25_put_route(ax25_rt);
 }
 
@@ -244,7 +244,7 @@ typedef struct ax25_cb {
 	unsigned char		window;
 	struct timer_list	timer, dtimer;
 	struct sock		*sk;		/* Backlink to socket */
-	atomic_t		refcount;
+	refcount_t		refcount;
 } ax25_cb;
 
 struct ax25_sock {
@@ -266,11 +266,11 @@ static inline struct ax25_cb *sk_to_ax25(const struct sock *sk)
 	hlist_for_each_entry(__ax25, list, ax25_node)
 
 #define ax25_cb_hold(__ax25) \
-	atomic_inc(&((__ax25)->refcount))
+	refcount_inc(&((__ax25)->refcount))
 
 static __inline__ void ax25_cb_put(ax25_cb *ax25)
 {
-	if (atomic_dec_and_test(&ax25->refcount)) {
+	if (refcount_dec_and_test(&ax25->refcount)) {
 		kfree(ax25->digipeat);
 		kfree(ax25);
 	}
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 90708f6..3c228fa 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -422,7 +422,7 @@ struct hci_dev {
 struct hci_conn {
 	struct list_head list;
 
-	atomic_t	refcnt;
+	refcount_t	refcnt;
 
 	bdaddr_t	dst;
 	__u8		dst_type;
@@ -942,17 +942,17 @@ static inline void hci_conn_put(struct hci_conn *conn)
 
 static inline void hci_conn_hold(struct hci_conn *conn)
 {
-	BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
+	BT_DBG("hcon %p orig refcnt %d", conn, refcount_read(&conn->refcnt));
 
-	atomic_inc(&conn->refcnt);
+	refcount_inc(&conn->refcnt);
 	cancel_delayed_work(&conn->disc_work);
 }
 
 static inline void hci_conn_drop(struct hci_conn *conn)
 {
-	BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
+	BT_DBG("hcon %p orig refcnt %d", conn, refcount_read(&conn->refcnt));
 
-	if (atomic_dec_and_test(&conn->refcnt)) {
+	if (refcount_dec_and_test(&conn->refcnt)) {
 		unsigned long timeo;
 
 		switch (conn->type) {
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 4190af5..da4acef 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -21,6 +21,8 @@
    SOFTWARE IS DISCLAIMED.
 */
 
+#include <linux/refcount.h>
+
 #ifndef __RFCOMM_H
 #define __RFCOMM_H
 
@@ -174,7 +176,7 @@ struct rfcomm_dlc {
 	struct mutex  lock;
 	unsigned long state;
 	unsigned long flags;
-	atomic_t      refcnt;
+	refcount_t    refcnt;
 	u8            dlci;
 	u8            addr;
 	u8            priority;
@@ -247,12 +249,12 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
 
 static inline void rfcomm_dlc_hold(struct rfcomm_dlc *d)
 {
-	atomic_inc(&d->refcnt);
+	refcount_inc(&d->refcnt);
 }
 
 static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
 {
-	if (atomic_dec_and_test(&d->refcnt))
+	if (refcount_dec_and_test(&d->refcnt))
 		rfcomm_dlc_free(d);
 }
 
diff --git a/include/net/calipso.h b/include/net/calipso.h
index b1b30cd..5f95b11 100644
--- a/include/net/calipso.h
+++ b/include/net/calipso.h
@@ -38,7 +38,7 @@
 #include <linux/skbuff.h>
 #include <net/netlabel.h>
 #include <net/request_sock.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <asm/unaligned.h>
 
 /* known doi values */
@@ -57,7 +57,7 @@ struct calipso_doi {
 	u32 doi;
 	u32 type;
 
-	atomic_t refcount;
+	refcount_t refcount;
 	struct list_head list;
 	struct rcu_head rcu;
 };
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index 3ebb168..026c7a3 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -41,6 +41,7 @@
 #include <net/netlabel.h>
 #include <net/request_sock.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <asm/unaligned.h>
 
 /* known doi values */
@@ -85,7 +86,7 @@ struct cipso_v4_doi {
 	} map;
 	u8 tags[CIPSO_V4_TAG_MAXCNT];
 
-	atomic_t refcount;
+	refcount_t refcount;
 	struct list_head list;
 	struct rcu_head rcu;
 };
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index f2ca135..81210a8 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -2,6 +2,7 @@
 #define _NET_DN_FIB_H
 
 #include <linux/netlink.h>
+#include <linux/refcount.h>
 
 extern const struct nla_policy rtm_dn_policy[];
 
@@ -28,7 +29,7 @@ struct dn_fib_info {
 	struct dn_fib_info	*fib_next;
 	struct dn_fib_info	*fib_prev;
 	int 			fib_treeref;
-	atomic_t		fib_clntref;
+	refcount_t		fib_clntref;
 	int			fib_dead;
 	unsigned int		fib_flags;
 	int			fib_protocol;
@@ -130,7 +131,7 @@ void dn_fib_free_info(struct dn_fib_info *fi);
 
 static inline void dn_fib_info_put(struct dn_fib_info *fi)
 {
-	if (atomic_dec_and_test(&fi->fib_clntref))
+	if (refcount_dec_and_test(&fi->fib_clntref))
 		dn_fib_free_info(fi);
 }
 
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 8dbfdf7..26ae0ad 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -5,6 +5,7 @@
 #include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/fib_rules.h>
+#include <linux/refcount.h>
 #include <net/flow.h>
 #include <net/rtnetlink.h>
 
@@ -29,7 +30,7 @@ struct fib_rule {
 	struct fib_rule __rcu	*ctarget;
 	struct net		*fr_net;
 
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	u32			pref;
 	int			suppress_ifgroup;
 	int			suppress_prefixlen;
@@ -103,12 +104,12 @@ struct fib_rules_ops {
 
 static inline void fib_rule_get(struct fib_rule *rule)
 {
-	atomic_inc(&rule->refcnt);
+	refcount_inc(&rule->refcnt);
 }
 
 static inline void fib_rule_put(struct fib_rule *rule)
 {
-	if (atomic_dec_and_test(&rule->refcnt))
+	if (refcount_dec_and_test(&rule->refcnt))
 		kfree_rcu(rule, rcu);
 }
 
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 0fa4c32..96a0e6e 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -17,6 +17,7 @@
 
 #include <net/snmp.h>
 #include <linux/ipv6.h>
+#include <linux/refcount.h>
 
 /* inet6_dev.if_flags */
 
@@ -45,7 +46,7 @@ struct inet6_ifaddr {
 	/* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
 	__u32			valid_lft;
 	__u32			prefered_lft;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	spinlock_t		lock;
 
 	int			state;
@@ -126,7 +127,7 @@ struct ifmcaddr6 {
 	struct timer_list	mca_timer;
 	unsigned int		mca_flags;
 	int			mca_users;
-	atomic_t		mca_refcnt;
+	refcount_t		mca_refcnt;
 	spinlock_t		mca_lock;
 	unsigned long		mca_cstamp;
 	unsigned long		mca_tstamp;
@@ -146,7 +147,7 @@ struct ifacaddr6 {
 	struct rt6_info		*aca_rt;
 	struct ifacaddr6	*aca_next;
 	int			aca_users;
-	atomic_t		aca_refcnt;
+	refcount_t		aca_refcnt;
 	unsigned long		aca_cstamp;
 	unsigned long		aca_tstamp;
 };
@@ -187,7 +188,7 @@ struct inet6_dev {
 
 	struct ifacaddr6	*ac_list;
 	rwlock_t		lock;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	__u32			if_flags;
 	int			dead;
 
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 909972a..ed5cbba 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -50,7 +50,7 @@ struct inet_frag_queue {
 	spinlock_t		lock;
 	struct timer_list	timer;
 	struct hlist_node	list;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	struct sk_buff		*fragments;
 	struct sk_buff		*fragments_tail;
 	ktime_t			stamp;
@@ -129,7 +129,7 @@ void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
 
 static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
 {
-	if (atomic_dec_and_test(&q->refcnt))
+	if (refcount_dec_and_test(&q->refcnt))
 		inet_frag_destroy(q, f);
 }
 
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 0574493..08d0d57 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -32,7 +32,7 @@
 #include <net/tcp_states.h>
 #include <net/netns/hash.h>
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <asm/byteorder.h>
 
 /* This is for all connections with a full identity, no wildcards.
@@ -329,7 +329,7 @@ static inline struct sock *inet_lookup(struct net *net,
 	sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
 			   dport, dif, &refcounted);
 
-	if (sk && !refcounted && !atomic_inc_not_zero(&sk->sk_refcnt))
+	if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
 		sk = NULL;
 	return sk;
 }
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 235c781..f2a215f 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -46,7 +46,7 @@ struct inet_peer {
 		struct rcu_head     gc_rcu;
 	};
 	/*
-	 * Once inet_peer is queued for deletion (refcnt == -1), following field
+	 * Once inet_peer is queued for deletion (refcnt == 0), following field
 	 * is not available: rid
 	 * We can share memory with rcu_head to help keep inet_peer small.
 	 */
@@ -60,7 +60,7 @@ struct inet_peer {
 
 	/* following fields might be frequently dirtied */
 	__u32			dtime;	/* the time of last use of not referenced entries */
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 struct inet_peer_base {
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 5f376af..cdf077b 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -23,6 +23,7 @@
 #include <net/inetpeer.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
+#include <linux/refcount.h>
 
 struct fib_config {
 	u8			fc_dst_len;
@@ -105,7 +106,7 @@ struct fib_info {
 	struct hlist_node	fib_lhash;
 	struct net		*fib_net;
 	int			fib_treeref;
-	atomic_t		fib_clntref;
+	refcount_t		fib_clntref;
 	unsigned int		fib_flags;
 	unsigned char		fib_dead;
 	unsigned char		fib_protocol;
@@ -400,12 +401,12 @@ void free_fib_info(struct fib_info *fi);
 
 static inline void fib_info_hold(struct fib_info *fi)
 {
-	atomic_inc(&fi->fib_clntref);
+	refcount_inc(&fi->fib_clntref);
 }
 
 static inline void fib_info_put(struct fib_info *fi)
 {
-	if (atomic_dec_and_test(&fi->fib_clntref))
+	if (refcount_dec_and_test(&fi->fib_clntref))
 		free_fib_info(fi);
 }
 
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index cd6018a..95e1c5d 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -12,6 +12,8 @@
 #include <linux/list.h>                 /* for struct list_head */
 #include <linux/spinlock.h>             /* for struct rwlock_t */
 #include <linux/atomic.h>               /* for struct atomic_t */
+#include <linux/refcount.h>             /* for struct refcount_t */
+
 #include <linux/compiler.h>
 #include <linux/timer.h>
 #include <linux/bug.h>
@@ -525,7 +527,7 @@ struct ip_vs_conn {
 	struct netns_ipvs	*ipvs;
 
 	/* counter and timer */
-	atomic_t		refcnt;		/* reference count */
+	refcount_t		refcnt;		/* reference count */
 	struct timer_list	timer;		/* Expiration timer */
 	volatile unsigned long	timeout;	/* timeout */
 
@@ -618,7 +620,7 @@ struct ip_vs_dest_user_kern {
 struct ip_vs_service {
 	struct hlist_node	s_list;   /* for normal service table */
 	struct hlist_node	f_list;   /* for fwmark-based service table */
-	atomic_t		refcnt;   /* reference counter */
+	refcount_t		refcnt;   /* reference counter */
 
 	u16			af;       /* address family */
 	__u16			protocol; /* which protocol (TCP/UDP) */
@@ -667,7 +669,7 @@ struct ip_vs_dest {
 	atomic_t		conn_flags;	/* flags to copy to conn */
 	atomic_t		weight;		/* server weight */
 
-	atomic_t		refcnt;		/* reference counter */
+	refcount_t		refcnt;		/* reference counter */
 	struct ip_vs_stats      stats;          /* statistics */
 	unsigned long		idle_start;	/* start time, jiffies */
 
@@ -697,7 +699,7 @@ struct ip_vs_dest {
 struct ip_vs_scheduler {
 	struct list_head	n_list;		/* d-linked list head */
 	char			*name;		/* scheduler name */
-	atomic_t		refcnt;		/* reference counter */
+	refcount_t		refcnt;		/* reference counter */
 	struct module		*module;	/* THIS_MODULE/NULL */
 
 	/* scheduler initializing service */
@@ -721,7 +723,7 @@ struct ip_vs_scheduler {
 struct ip_vs_pe {
 	struct list_head	n_list;		/* d-linked list head */
 	char			*name;		/* scheduler name */
-	atomic_t		refcnt;		/* reference counter */
+	refcount_t		refcnt;		/* reference counter */
 	struct module		*module;	/* THIS_MODULE/NULL */
 
 	/* get the connection template, if any */
@@ -1211,14 +1213,14 @@ struct ip_vs_conn * ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af,
  */
 static inline bool __ip_vs_conn_get(struct ip_vs_conn *cp)
 {
-	return atomic_inc_not_zero(&cp->refcnt);
+	return refcount_inc_not_zero(&cp->refcnt);
 }
 
 /* put back the conn without restarting its timer */
 static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
 {
 	smp_mb__before_atomic();
-	atomic_dec(&cp->refcnt);
+	refcount_dec(&cp->refcnt);
 }
 void ip_vs_conn_put(struct ip_vs_conn *cp);
 void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
@@ -1410,19 +1412,21 @@ void ip_vs_try_bind_dest(struct ip_vs_conn *cp);
 
 static inline void ip_vs_dest_hold(struct ip_vs_dest *dest)
 {
-	atomic_inc(&dest->refcnt);
+	refcount_inc(&dest->refcnt);
 }
 
 static inline void ip_vs_dest_put(struct ip_vs_dest *dest)
 {
 	smp_mb__before_atomic();
-	atomic_dec(&dest->refcnt);
+	refcount_dec(&dest->refcnt);
 }
 
 static inline void ip_vs_dest_put_and_free(struct ip_vs_dest *dest)
 {
-	if (atomic_dec_return(&dest->refcnt) < 0)
+	if (refcount_read(&dest->refcnt) == 0)
 		kfree(dest);
+	else
+		refcount_dec(&dest->refcnt);
 }
 
 /* IPVS sync daemon data and function prototypes
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 487e573..f23dc0b 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -16,6 +16,7 @@
 #include <linux/ipv6.h>
 #include <linux/hardirq.h>
 #include <linux/jhash.h>
+#include <linux/refcount.h>
 #include <net/if_inet6.h>
 #include <net/ndisc.h>
 #include <net/flow.h>
@@ -203,7 +204,7 @@ extern rwlock_t ip6_ra_lock;
  */
 
 struct ipv6_txoptions {
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	/* Length of this structure */
 	int			tot_len;
 
@@ -265,7 +266,7 @@ static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
 	rcu_read_lock();
 	opt = rcu_dereference(np->opt);
 	if (opt) {
-		if (!atomic_inc_not_zero(&opt->refcnt))
+		if (!refcount_inc_not_zero(&opt->refcnt))
 			opt = NULL;
 		else
 			opt = rcu_pointer_handoff(opt);
@@ -276,7 +277,7 @@ static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
 
 static inline void txopt_put(struct ipv6_txoptions *opt)
 {
-	if (opt && atomic_dec_and_test(&opt->refcnt))
+	if (opt && refcount_dec_and_test(&opt->refcnt))
 		kfree_rcu(opt, rcu);
 }
 
diff --git a/include/net/ipx.h b/include/net/ipx.h
index e5cff68..af32b97 100644
--- a/include/net/ipx.h
+++ b/include/net/ipx.h
@@ -14,6 +14,7 @@
 #include <linux/ipx.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 struct ipx_address {
 	__be32  net;
@@ -54,7 +55,7 @@ struct ipx_interface {
 	/* IPX address */
 	__be32			if_netnum;
 	unsigned char		if_node[IPX_NODE_LEN];
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 
 	/* physical device info */
 	struct net_device	*if_dev;
@@ -80,7 +81,7 @@ struct ipx_route {
 	unsigned char		ir_routed;
 	unsigned char		ir_router_node[IPX_NODE_LEN];
 	struct list_head	node; /* node in ipx_routes list */
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 struct ipx_cb {
@@ -139,7 +140,7 @@ const char *ipx_device_name(struct ipx_interface *intrfc);
 
 static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
 {
-	atomic_inc(&intrfc->refcnt);
+	refcount_inc(&intrfc->refcnt);
 }
 
 void ipxitf_down(struct ipx_interface *intrfc);
@@ -157,18 +158,18 @@ int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
 
 static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
 {
-	if (atomic_dec_and_test(&intrfc->refcnt))
+	if (refcount_dec_and_test(&intrfc->refcnt))
 		ipxitf_down(intrfc);
 }
 
 static __inline__ void ipxrtr_hold(struct ipx_route *rt)
 {
-	        atomic_inc(&rt->refcnt);
+	        refcount_inc(&rt->refcnt);
 }
 
 static __inline__ void ipxrtr_put(struct ipx_route *rt)
 {
-	        if (atomic_dec_and_test(&rt->refcnt))
+	        if (refcount_dec_and_test(&rt->refcnt))
 			                kfree(rt);
 }
 #endif /* _NET_INET_IPX_H_ */
diff --git a/include/net/lapb.h b/include/net/lapb.h
index 9510f87..85e7737 100644
--- a/include/net/lapb.h
+++ b/include/net/lapb.h
@@ -1,6 +1,7 @@
 #ifndef _LAPB_H
 #define _LAPB_H 
 #include <linux/lapb.h>
+#include <linux/refcount.h>
 
 #define	LAPB_HEADER_LEN	20		/* LAPB over Ethernet + a bit more */
 
@@ -101,7 +102,7 @@ struct lapb_cb {
 	struct lapb_frame	frmr_data;
 	unsigned char		frmr_type;
 
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 /* lapb_iface.c */
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
index aab0f42..9fd9042 100644
--- a/include/net/lib80211.h
+++ b/include/net/lib80211.h
@@ -93,7 +93,7 @@ struct lib80211_crypt_data {
 	struct list_head list;	/* delayed deletion list */
 	struct lib80211_crypto_ops *ops;
 	void *priv;
-	atomic_t refcnt;
+	refcount_t refcnt;
 };
 
 struct lib80211_crypt_info {
diff --git a/include/net/llc.h b/include/net/llc.h
index e8e61d4..dc35f25 100644
--- a/include/net/llc.h
+++ b/include/net/llc.h
@@ -55,7 +55,7 @@ struct llc_sap {
 	unsigned char	 state;
 	unsigned char	 p_bit;
 	unsigned char	 f_bit;
-	atomic_t         refcnt;
+	refcount_t		 refcnt;
 	int		 (*rcv_func)(struct sk_buff *skb,
 				     struct net_device *dev,
 				     struct packet_type *pt,
@@ -113,14 +113,14 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
 					struct net_device *orig_dev));
 static inline void llc_sap_hold(struct llc_sap *sap)
 {
-	atomic_inc(&sap->refcnt);
+	refcount_inc(&sap->refcnt);
 }
 
 void llc_sap_close(struct llc_sap *sap);
 
 static inline void llc_sap_put(struct llc_sap *sap)
 {
-	if (atomic_dec_and_test(&sap->refcnt))
+	if (refcount_dec_and_test(&sap->refcnt))
 		llc_sap_close(sap);
 }
 
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
index d4c1c75..932ff0c 100644
--- a/include/net/lwtunnel.h
+++ b/include/net/lwtunnel.h
@@ -5,6 +5,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
+#include <linux/refcount.h>
 #include <net/route.h>
 
 #define LWTUNNEL_HASH_BITS   7
@@ -25,7 +26,7 @@ struct lwtunnel_state {
 	__u16		type;
 	__u16		flags;
 	__u16		headroom;
-	atomic_t	refcnt;
+	refcount_t	refcnt;
 	int		(*orig_output)(struct net *net, struct sock *sk, struct sk_buff *skb);
 	int		(*orig_input)(struct sk_buff *);
 	struct		rcu_head rcu;
@@ -53,7 +54,7 @@ static inline struct lwtunnel_state *
 lwtstate_get(struct lwtunnel_state *lws)
 {
 	if (lws)
-		atomic_inc(&lws->refcnt);
+		refcount_inc(&lws->refcnt);
 
 	return lws;
 }
@@ -63,7 +64,7 @@ static inline void lwtstate_put(struct lwtunnel_state *lws)
 	if (!lws)
 		return;
 
-	if (atomic_dec_and_test(&lws->refcnt))
+	if (refcount_dec_and_test(&lws->refcnt))
 		lwtstate_free(lws);
 }
 
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index d562a2f..0224bce 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -384,7 +384,7 @@ static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, cons
 
 	rcu_read_lock_bh();
 	n = __ipv6_neigh_lookup_noref(dev, pkey);
-	if (n && !atomic_inc_not_zero(&n->refcnt))
+	if (n && !refcount_inc_not_zero(&n->refcnt))
 		n = NULL;
 	rcu_read_unlock_bh();
 
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 8b68384..33e534a 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -17,6 +17,7 @@
  */
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rcupdate.h>
@@ -76,7 +77,7 @@ struct neigh_parms {
 	void	*sysctl_table;
 
 	int dead;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	struct rcu_head rcu_head;
 
 	int	reachable_time;
@@ -137,7 +138,7 @@ struct neighbour {
 	unsigned long		confirmed;
 	unsigned long		updated;
 	rwlock_t		lock;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	struct sk_buff_head	arp_queue;
 	unsigned int		arp_queue_len_bytes;
 	struct timer_list	timer;
@@ -393,12 +394,12 @@ void neigh_sysctl_unregister(struct neigh_parms *p);
 
 static inline void __neigh_parms_put(struct neigh_parms *parms)
 {
-	atomic_dec(&parms->refcnt);
+	refcount_dec(&parms->refcnt);
 }
 
 static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
 {
-	atomic_inc(&parms->refcnt);
+	refcount_inc(&parms->refcnt);
 	return parms;
 }
 
@@ -408,18 +409,18 @@ static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
 
 static inline void neigh_release(struct neighbour *neigh)
 {
-	if (atomic_dec_and_test(&neigh->refcnt))
+	if (refcount_dec_and_test(&neigh->refcnt))
 		neigh_destroy(neigh);
 }
 
 static inline struct neighbour * neigh_clone(struct neighbour *neigh)
 {
 	if (neigh)
-		atomic_inc(&neigh->refcnt);
+		refcount_inc(&neigh->refcnt);
 	return neigh;
 }
 
-#define neigh_hold(n)	atomic_inc(&(n)->refcnt)
+#define neigh_hold(n)	refcount_inc(&(n)->refcnt)
 
 static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index af8fe8a..ec6dcaf 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -5,6 +5,7 @@
 #define __NET_NET_NAMESPACE_H
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/workqueue.h>
 #include <linux/list.h>
 #include <linux/sysctl.h>
@@ -45,7 +46,7 @@ struct netns_ipvs;
 #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
 
 struct net {
-	atomic_t		passive;	/* To decided when the network
+	refcount_t		passive;	/* To decided when the network
 						 * namespace should be freed.
 						 */
 	atomic_t		count;		/* To decided when the network
diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h
index 0b0c35c..925524e 100644
--- a/include/net/netfilter/br_netfilter.h
+++ b/include/net/netfilter/br_netfilter.h
@@ -8,7 +8,7 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
 	skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC);
 
 	if (likely(skb->nf_bridge))
-		atomic_set(&(skb->nf_bridge->use), 1);
+		refcount_set(&(skb->nf_bridge->use), 1);
 
 	return skb->nf_bridge;
 }
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 5ed33ea..65cc2cb 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -5,6 +5,8 @@
 #ifndef _NF_CONNTRACK_EXPECT_H
 #define _NF_CONNTRACK_EXPECT_H
 
+#include <linux/refcount.h>
+
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 
@@ -37,7 +39,7 @@ struct nf_conntrack_expect {
 	struct timer_list timeout;
 
 	/* Usage count. */
-	atomic_t use;
+	refcount_t use;
 
 	/* Flags */
 	unsigned int flags;
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
index 5cc5e9e..d40b893 100644
--- a/include/net/netfilter/nf_conntrack_timeout.h
+++ b/include/net/netfilter/nf_conntrack_timeout.h
@@ -4,6 +4,7 @@
 #include <net/net_namespace.h>
 #include <linux/netfilter/nf_conntrack_common.h>
 #include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <linux/refcount.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_extend.h>
 
@@ -12,7 +13,7 @@
 struct ctnl_timeout {
 	struct list_head	head;
 	struct rcu_head		rcu_head;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	char			name[CTNL_TIMEOUT_NAME_MAX];
 	__u16			l3num;
 	struct nf_conntrack_l4proto *l4proto;
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index efe9806..72d6435 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -37,7 +37,7 @@
 #include <linux/in6.h>
 #include <net/netlink.h>
 #include <net/request_sock.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct cipso_v4_doi;
 struct calipso_doi;
@@ -136,7 +136,7 @@ struct netlbl_audit {
  *
  */
 struct netlbl_lsm_cache {
-	atomic_t refcount;
+	refcount_t refcount;
 	void (*free) (const void *data);
 	void *data;
 };
@@ -295,7 +295,7 @@ static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
 
 	cache = kzalloc(sizeof(*cache), flags);
 	if (cache)
-		atomic_set(&cache->refcount, 1);
+		refcount_set(&cache->refcount, 1);
 	return cache;
 }
 
@@ -309,7 +309,7 @@ static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
  */
 static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
 {
-	if (!atomic_dec_and_test(&cache->refcount))
+	if (!refcount_dec_and_test(&cache->refcount))
 		return;
 
 	if (cache->free)
diff --git a/include/net/netrom.h b/include/net/netrom.h
index 110350a..443a4ff 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -11,6 +11,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <net/sock.h>
+#include <linux/refcount.h>
 
 #define	NR_NETWORK_LEN			15
 #define	NR_TRANSPORT_LEN		5
@@ -93,7 +94,7 @@ struct nr_neigh {
 	unsigned short		count;
 	unsigned int		number;
 	unsigned char		failed;
-	atomic_t		refcount;
+	refcount_t		refcount;
 };
 
 struct nr_route {
@@ -109,7 +110,7 @@ struct nr_node {
 	unsigned char		which;
 	unsigned char		count;
 	struct nr_route		routes[3];
-	atomic_t		refcount;
+	refcount_t		refcount;
 	spinlock_t		node_lock;
 };
 
@@ -118,21 +119,21 @@ struct nr_node {
  *********************************************************************/
 
 #define nr_node_hold(__nr_node) \
-	atomic_inc(&((__nr_node)->refcount))
+	refcount_inc(&((__nr_node)->refcount))
 
 static __inline__ void nr_node_put(struct nr_node *nr_node)
 {
-	if (atomic_dec_and_test(&nr_node->refcount)) {
+	if (refcount_dec_and_test(&nr_node->refcount)) {
 		kfree(nr_node);
 	}
 }
 
 #define nr_neigh_hold(__nr_neigh) \
-	atomic_inc(&((__nr_neigh)->refcount))
+	refcount_inc(&((__nr_neigh)->refcount))
 
 static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
 {
-	if (atomic_dec_and_test(&nr_neigh->refcount)) {
+	if (refcount_dec_and_test(&nr_neigh->refcount)) {
 		if (nr_neigh->ax25)
 			ax25_cb_put(nr_neigh->ax25);
 		kfree(nr_neigh->digipeat);
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 6ebe13e..696a53d 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -19,6 +19,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/bug.h>
+#include <linux/refcount.h>
 
 #include <net/sock.h>
 
@@ -89,7 +90,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
 		return NULL;
 	req->rsk_listener = NULL;
 	if (attach_listener) {
-		if (unlikely(!atomic_inc_not_zero(&sk_listener->sk_refcnt))) {
+		if (unlikely(!refcount_inc_not_zero(&sk_listener->sk_refcnt))) {
 			kmem_cache_free(ops->slab, req);
 			return NULL;
 		}
@@ -100,7 +101,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
 	sk_node_init(&req_to_sk(req)->sk_node);
 	sk_tx_queue_clear(req_to_sk(req));
 	req->saved_syn = NULL;
-	atomic_set(&req->rsk_refcnt, 0);
+	refcount_set(&req->rsk_refcnt, 0);
 
 	return req;
 }
@@ -108,7 +109,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
 static inline void reqsk_free(struct request_sock *req)
 {
 	/* temporary debugging */
-	WARN_ON_ONCE(atomic_read(&req->rsk_refcnt) != 0);
+	WARN_ON_ONCE(refcount_read(&req->rsk_refcnt) != 0);
 
 	req->rsk_ops->destructor(req);
 	if (req->rsk_listener)
@@ -119,7 +120,7 @@ static inline void reqsk_free(struct request_sock *req)
 
 static inline void reqsk_put(struct request_sock *req)
 {
-	if (atomic_dec_and_test(&req->rsk_refcnt))
+	if (refcount_dec_and_test(&req->rsk_refcnt))
 		reqsk_free(req);
 }
 
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 498f81b..fbcdd64 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -8,6 +8,7 @@
 #include <linux/pkt_cls.h>
 #include <linux/percpu.h>
 #include <linux/dynamic_queue_limits.h>
+#include <linux/refcount.h>
 #include <net/gen_stats.h>
 #include <net/rtnetlink.h>
 
@@ -93,7 +94,7 @@ struct Qdisc {
 	struct sk_buff		*skb_bad_txq;
 	struct rcu_head		rcu_head;
 	int			padded;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 
 	spinlock_t		busylock ____cacheline_aligned_in_smp;
 };
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 9b9fb12..328fccc 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -31,6 +31,7 @@
 #define __sctp_auth_h__
 
 #include <linux/list.h>
+#include <linux/refcount.h>
 
 struct sctp_endpoint;
 struct sctp_association;
@@ -53,7 +54,7 @@ struct sctp_hmac {
  * over SCTP-AUTH
  */
 struct sctp_auth_bytes {
-	atomic_t refcnt;
+	refcount_t refcnt;
 	__u32 len;
 	__u8  data[];
 };
@@ -76,7 +77,7 @@ static inline void sctp_auth_key_hold(struct sctp_auth_bytes *key)
 	if (!key)
 		return;
 
-	atomic_inc(&key->refcnt);
+	refcount_inc(&key->refcnt);
 }
 
 void sctp_auth_key_put(struct sctp_auth_bytes *key);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 92daabd..07d514d 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -524,7 +524,7 @@ struct sctp_datamsg {
 	/* Chunks waiting to be submitted to lower layer. */
 	struct list_head chunks;
 	/* Reference counting. */
-	atomic_t refcnt;
+	refcount_t refcnt;
 	/* When is this message no longer interesting to the peer? */
 	unsigned long expires_at;
 	/* Did the messenge fail to send? */
@@ -552,7 +552,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *);
 struct sctp_chunk {
 	struct list_head list;
 
-	atomic_t refcnt;
+	refcount_t refcnt;
 
 	/* How many times this chunk have been sent, for prsctp RTX policy */
 	int sent_count;
@@ -764,7 +764,7 @@ struct sctp_transport {
 	struct rhlist_head node;
 
 	/* Reference counting. */
-	atomic_t refcnt;
+	refcount_t refcnt;
 		/* RTO-Pending : A flag used to track if one of the DATA
 		 *		chunks sent to this address is currently being
 		 *		used to compute a RTT. If this flag is 0,
@@ -1195,7 +1195,7 @@ struct sctp_ep_common {
 	 *   refcnt   - Reference count access to this object.
 	 *   dead     - Do not attempt to use this object.
 	 */
-	atomic_t    refcnt;
+	refcount_t    refcnt;
 	bool	    dead;
 
 	/* What socket does this endpoint belong to?  */
diff --git a/include/net/sock.h b/include/net/sock.h
index f0e867f..3b646eb 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -66,6 +66,7 @@
 #include <linux/poll.h>
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <net/dst.h>
 #include <net/checksum.h>
 #include <net/tcp_states.h>
@@ -218,7 +219,7 @@ struct sock_common {
 		u32		skc_tw_rcv_nxt; /* struct tcp_timewait_sock  */
 	};
 
-	atomic_t		skc_refcnt;
+	refcount_t		skc_refcnt;
 	/* private: */
 	int                     skc_dontcopy_end[0];
 	union {
@@ -386,7 +387,7 @@ struct sock {
 
 	/* ===== cache line for TX ===== */
 	int			sk_wmem_queued;
-	atomic_t		sk_wmem_alloc;
+	refcount_t		sk_wmem_alloc;
 	unsigned long		sk_tsq_flags;
 	struct sk_buff		*sk_send_head;
 	struct sk_buff_head	sk_write_queue;
@@ -599,7 +600,7 @@ static inline bool __sk_del_node_init(struct sock *sk)
 
 static __always_inline void sock_hold(struct sock *sk)
 {
-	atomic_inc(&sk->sk_refcnt);
+	refcount_inc(&sk->sk_refcnt);
 }
 
 /* Ungrab socket in the context, which assumes that socket refcnt
@@ -607,7 +608,7 @@ static __always_inline void sock_hold(struct sock *sk)
  */
 static __always_inline void __sock_put(struct sock *sk)
 {
-	atomic_dec(&sk->sk_refcnt);
+	refcount_dec(&sk->sk_refcnt);
 }
 
 static inline bool sk_del_node_init(struct sock *sk)
@@ -616,7 +617,7 @@ static inline bool sk_del_node_init(struct sock *sk)
 
 	if (rc) {
 		/* paranoid for a while -acme */
-		WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
+		WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
 		__sock_put(sk);
 	}
 	return rc;
@@ -638,7 +639,7 @@ static inline bool sk_nulls_del_node_init_rcu(struct sock *sk)
 
 	if (rc) {
 		/* paranoid for a while -acme */
-		WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
+		WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
 		__sock_put(sk);
 	}
 	return rc;
@@ -1124,9 +1125,9 @@ static inline void sk_refcnt_debug_dec(struct sock *sk)
 
 static inline void sk_refcnt_debug_release(const struct sock *sk)
 {
-	if (atomic_read(&sk->sk_refcnt) != 1)
+	if (refcount_read(&sk->sk_refcnt) != 1)
 		printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n",
-		       sk->sk_prot->name, sk, atomic_read(&sk->sk_refcnt));
+		       sk->sk_prot->name, sk, refcount_read(&sk->sk_refcnt));
 }
 #else /* SOCK_REFCNT_DEBUG */
 #define sk_refcnt_debug_inc(sk) do { } while (0)
@@ -1634,7 +1635,7 @@ void sock_init_data(struct socket *sock, struct sock *sk);
 /* Ungrab socket and destroy it, if it was the last reference. */
 static inline void sock_put(struct sock *sk)
 {
-	if (atomic_dec_and_test(&sk->sk_refcnt))
+	if (refcount_dec_and_test(&sk->sk_refcnt))
 		sk_free(sk);
 }
 /* Generic version of sock_put(), dealing with all sockets
@@ -1889,7 +1890,7 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, struct iov_iter *fro
  */
 static inline int sk_wmem_alloc_get(const struct sock *sk)
 {
-	return atomic_read(&sk->sk_wmem_alloc) - 1;
+	return refcount_read(&sk->sk_wmem_alloc) - 1;
 }
 
 /**
@@ -2031,7 +2032,7 @@ static inline unsigned long sock_wspace(struct sock *sk)
 	int amt = 0;
 
 	if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
-		amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
+		amt = sk->sk_sndbuf - refcount_read(&sk->sk_wmem_alloc);
 		if (amt < 0)
 			amt = 0;
 	}
@@ -2112,7 +2113,7 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag);
  */
 static inline bool sock_writeable(const struct sock *sk)
 {
-	return atomic_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1);
+	return refcount_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1);
 }
 
 static inline gfp_t gfp_any(void)
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 49a5920..5c117b4 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -183,7 +183,7 @@ struct vxlan_sock {
 	struct hlist_node hlist;
 	struct socket	 *sock;
 	struct hlist_head vni_list[VNI_HASH_SIZE];
-	atomic_t	  refcnt;
+	refcount_t	  refcnt;
 	u32		  flags;
 };
 
diff --git a/include/net/x25.h b/include/net/x25.h
index c383aa4..6219daf 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -11,6 +11,7 @@
 #define _X25_H 
 #include <linux/x25.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 #include <net/sock.h>
 
 #define	X25_ADDR_LEN			16
@@ -129,7 +130,7 @@ struct x25_route {
 	struct x25_address	address;
 	unsigned int		sigdigits;
 	struct net_device	*dev;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 struct x25_neigh {
@@ -141,7 +142,7 @@ struct x25_neigh {
 	unsigned long		t20;
 	struct timer_list	t20timer;
 	unsigned long		global_facil_mask;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 struct x25_sock {
@@ -171,7 +172,7 @@ struct x25_forward {
 	unsigned int		lci;
 	struct net_device	*dev1;
 	struct net_device	*dev2;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 static inline struct x25_sock *x25_sk(const struct sock *sk)
@@ -242,12 +243,12 @@ void x25_link_free(void);
 /* x25_neigh.c */
 static __inline__ void x25_neigh_hold(struct x25_neigh *nb)
 {
-	atomic_inc(&nb->refcnt);
+	refcount_inc(&nb->refcnt);
 }
 
 static __inline__ void x25_neigh_put(struct x25_neigh *nb)
 {
-	if (atomic_dec_and_test(&nb->refcnt))
+	if (refcount_dec_and_test(&nb->refcnt))
 		kfree(nb);
 }
 
@@ -265,12 +266,12 @@ void x25_route_free(void);
 
 static __inline__ void x25_route_hold(struct x25_route *rt)
 {
-	atomic_inc(&rt->refcnt);
+	refcount_inc(&rt->refcnt);
 }
 
 static __inline__ void x25_route_put(struct x25_route *rt)
 {
-	if (atomic_dec_and_test(&rt->refcnt))
+	if (refcount_dec_and_test(&rt->refcnt))
 		kfree(rt);
 }
 
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 31947b9..54a8967 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -13,6 +13,7 @@
 #include <linux/mutex.h>
 #include <linux/audit.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 #include <net/sock.h>
 #include <net/dst.h>
@@ -130,7 +131,7 @@ struct xfrm_state {
 	struct hlist_node	bysrc;
 	struct hlist_node	byspi;
 
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	spinlock_t		lock;
 
 	struct xfrm_id		id;
@@ -524,7 +525,7 @@ struct xfrm_policy {
 
 	/* This lock only affects elements except for entry. */
 	rwlock_t		lock;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	struct timer_list	timer;
 
 	struct flow_cache_object flo;
@@ -779,14 +780,14 @@ static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
 {
 	if (likely(policy != NULL))
-		atomic_inc(&policy->refcnt);
+		refcount_inc(&policy->refcnt);
 }
 
 void xfrm_policy_destroy(struct xfrm_policy *policy);
 
 static inline void xfrm_pol_put(struct xfrm_policy *policy)
 {
-	if (atomic_dec_and_test(&policy->refcnt))
+	if (refcount_dec_and_test(&policy->refcnt))
 		xfrm_policy_destroy(policy);
 }
 
@@ -801,18 +802,18 @@ void __xfrm_state_destroy(struct xfrm_state *);
 
 static inline void __xfrm_state_put(struct xfrm_state *x)
 {
-	atomic_dec(&x->refcnt);
+	refcount_dec(&x->refcnt);
 }
 
 static inline void xfrm_state_put(struct xfrm_state *x)
 {
-	if (atomic_dec_and_test(&x->refcnt))
+	if (refcount_dec_and_test(&x->refcnt))
 		__xfrm_state_destroy(x);
 }
 
 static inline void xfrm_state_hold(struct xfrm_state *x)
 {
-	atomic_inc(&x->refcnt);
+	refcount_inc(&x->refcnt);
 }
 
 static inline bool addr_match(const void *token1, const void *token2,
@@ -975,7 +976,7 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
 void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
 
 struct sec_path {
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	int			len;
 	struct xfrm_state	*xvec[XFRM_MAX_DEPTH];
 };
@@ -993,7 +994,7 @@ static inline struct sec_path *
 secpath_get(struct sec_path *sp)
 {
 	if (sp)
-		atomic_inc(&sp->refcnt);
+		refcount_inc(&sp->refcnt);
 	return sp;
 }
 
@@ -1002,7 +1003,7 @@ void __secpath_destroy(struct sec_path *sp);
 static inline void
 secpath_put(struct sec_path *sp)
 {
-	if (sp && atomic_dec_and_test(&sp->refcnt))
+	if (sp && refcount_dec_and_test(&sp->refcnt))
 		__secpath_destroy(sp);
 }
 
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index fca84e1..4e11119 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -252,7 +252,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
 
 	ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
 	pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
-	atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = atmvcc->atm_options;
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 53b4ac0..e2e1318 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -137,11 +137,11 @@ static int neigh_check_cb(struct neighbour *n)
 	if (entry->vccs || time_before(jiffies, entry->expires))
 		return 0;
 
-	if (atomic_read(&n->refcnt) > 1) {
+	if (refcount_read(&n->refcnt) > 1) {
 		struct sk_buff *skb;
 
 		pr_debug("destruction postponed with ref %d\n",
-			 atomic_read(&n->refcnt));
+			 refcount_read(&n->refcnt));
 
 		while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
 			dev_kfree_skb(skb);
@@ -381,7 +381,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
 		memcpy(here, llc_oui, sizeof(llc_oui));
 		((__be16 *) here)[3] = skb->protocol;
 	}
-	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 	entry->vccs->last_use = jiffies;
 	pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
@@ -767,7 +767,7 @@ static void atmarp_info(struct seq_file *seq, struct neighbour *n,
 			seq_printf(seq, "(resolving)\n");
 		else
 			seq_printf(seq, "(expired, ref %d)\n",
-				   atomic_read(&entry->neigh->refcnt));
+				   refcount_read(&entry->neigh->refcnt));
 	} else if (!svc) {
 		seq_printf(seq, "%d.%d.%d\n",
 			   clip_vcc->vcc->dev->number,
diff --git a/net/atm/common.c b/net/atm/common.c
index a3ca922..16b2c25 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -75,7 +75,7 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
 	while (!(skb = alloc_skb(size, GFP_KERNEL)))
 		schedule();
 	pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
-	atomic_add(skb->truesize, &sk->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk->sk_wmem_alloc);
 	return skb;
 }
 
@@ -85,9 +85,9 @@ static void vcc_sock_destruct(struct sock *sk)
 		printk(KERN_DEBUG "%s: rmem leakage (%d bytes) detected.\n",
 		       __func__, atomic_read(&sk->sk_rmem_alloc));
 
-	if (atomic_read(&sk->sk_wmem_alloc))
+	if (refcount_read(&sk->sk_wmem_alloc))
 		printk(KERN_DEBUG "%s: wmem leakage (%d bytes) detected.\n",
-		       __func__, atomic_read(&sk->sk_wmem_alloc));
+		       __func__, refcount_read(&sk->sk_wmem_alloc));
 }
 
 static void vcc_def_wakeup(struct sock *sk)
@@ -106,7 +106,7 @@ static inline int vcc_writable(struct sock *sk)
 	struct atm_vcc *vcc = atm_sk(sk);
 
 	return (vcc->qos.txtp.max_sdu +
-		atomic_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
+		refcount_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
 }
 
 static void vcc_write_space(struct sock *sk)
@@ -161,7 +161,7 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family, i
 	memset(&vcc->local, 0, sizeof(struct sockaddr_atmsvc));
 	memset(&vcc->remote, 0, sizeof(struct sockaddr_atmsvc));
 	vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
-	atomic_set(&sk->sk_wmem_alloc, 1);
+	refcount_set(&sk->sk_wmem_alloc, 1);
 	atomic_set(&sk->sk_rmem_alloc, 0);
 	vcc->push = NULL;
 	vcc->pop = NULL;
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 019557d..1bc6722 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -101,12 +101,12 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
 /* must be done under lec_arp_lock */
 static inline void lec_arp_hold(struct lec_arp_table *entry)
 {
-	atomic_inc(&entry->usage);
+	refcount_inc(&entry->usage);
 }
 
 static inline void lec_arp_put(struct lec_arp_table *entry)
 {
-	if (atomic_dec_and_test(&entry->usage))
+	if (refcount_dec_and_test(&entry->usage))
 		kfree(entry);
 }
 
@@ -181,7 +181,7 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
 	ATM_SKB(skb)->vcc = vcc;
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 
-	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 	if (vcc->send(vcc, skb) < 0) {
 		dev->stats.tx_dropped++;
 		return;
@@ -345,7 +345,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 	int i;
 	char *tmp;		/* FIXME */
 
-	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+	WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
 	mesg = (struct atmlec_msg *)skb->data;
 	tmp = skb->data;
 	tmp += sizeof(struct atmlec_msg);
@@ -1216,6 +1216,7 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
 #include <linux/timer.h>
 #include <linux/param.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/inetdevice.h>
 #include <net/route.h>
 
@@ -1562,7 +1563,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv,
 	to_return->last_used = jiffies;
 	to_return->priv = priv;
 	skb_queue_head_init(&to_return->tx_wait);
-	atomic_set(&to_return->usage, 1);
+	refcount_set(&to_return->usage, 1);
 	return to_return;
 }
 
diff --git a/net/atm/lec_arpc.h b/net/atm/lec_arpc.h
index ec67435..7ff4e7c 100644
--- a/net/atm/lec_arpc.h
+++ b/net/atm/lec_arpc.h
@@ -47,7 +47,7 @@ struct lec_arp_table {
 					 * the length of the tlvs array
 					 */
 	struct sk_buff_head tx_wait;	/* wait queue for outgoing packets */
-	atomic_t usage;			/* usage count */
+	refcount_t usage;				/* usage count */
 };
 
 /*
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 3b3b1a2..5741820 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -555,7 +555,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
 					sizeof(struct llc_snap_hdr));
 	}
 
-	atomic_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
 	entry->shortcut->send(entry->shortcut, skb);
 	entry->packets_fwded++;
@@ -911,7 +911,7 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
 
 	struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
 	struct k_message *mesg = (struct k_message *)skb->data;
-	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+	WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
 
 	if (mpc == NULL) {
 		pr_info("no mpc found\n");
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index a89fdeb..4ccaa16 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -40,7 +40,7 @@ static in_cache_entry *in_cache_get(__be32 dst_ip,
 	entry = client->in_cache;
 	while (entry != NULL) {
 		if (entry->ctrl_info.in_dst_ip == dst_ip) {
-			atomic_inc(&entry->use);
+			refcount_inc(&entry->use);
 			read_unlock_bh(&client->ingress_lock);
 			return entry;
 		}
@@ -61,7 +61,7 @@ static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip,
 	entry = client->in_cache;
 	while (entry != NULL) {
 		if ((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask)) {
-			atomic_inc(&entry->use);
+			refcount_inc(&entry->use);
 			read_unlock_bh(&client->ingress_lock);
 			return entry;
 		}
@@ -82,7 +82,7 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
 	entry = client->in_cache;
 	while (entry != NULL) {
 		if (entry->shortcut == vcc) {
-			atomic_inc(&entry->use);
+			refcount_inc(&entry->use);
 			read_unlock_bh(&client->ingress_lock);
 			return entry;
 		}
@@ -105,7 +105,7 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
 
 	dprintk("adding an ingress entry, ip = %pI4\n", &dst_ip);
 
-	atomic_set(&entry->use, 1);
+	refcount_set(&entry->use, 1);
 	dprintk("new_in_cache_entry: about to lock\n");
 	write_lock_bh(&client->ingress_lock);
 	entry->next = client->in_cache;
@@ -121,7 +121,7 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
 	entry->count = 1;
 	entry->entry_state = INGRESS_INVALID;
 	entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
-	atomic_inc(&entry->use);
+	refcount_inc(&entry->use);
 
 	write_unlock_bh(&client->ingress_lock);
 	dprintk("new_in_cache_entry: unlocked\n");
@@ -178,7 +178,7 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
 
 static void in_cache_put(in_cache_entry *entry)
 {
-	if (atomic_dec_and_test(&entry->use)) {
+	if (refcount_dec_and_test(&entry->use)) {
 		memset(entry, 0, sizeof(in_cache_entry));
 		kfree(entry);
 	}
@@ -339,7 +339,7 @@ static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id,
 	entry = mpc->eg_cache;
 	while (entry != NULL) {
 		if (entry->ctrl_info.cache_id == cache_id) {
-			atomic_inc(&entry->use);
+			refcount_inc(&entry->use);
 			read_unlock_irq(&mpc->egress_lock);
 			return entry;
 		}
@@ -360,7 +360,7 @@ static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc)
 	entry = mpc->eg_cache;
 	while (entry != NULL) {
 		if (entry->ctrl_info.tag == tag) {
-			atomic_inc(&entry->use);
+			refcount_inc(&entry->use);
 			read_unlock_irqrestore(&mpc->egress_lock, flags);
 			return entry;
 		}
@@ -382,7 +382,7 @@ static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc,
 	entry = mpc->eg_cache;
 	while (entry != NULL) {
 		if (entry->shortcut == vcc) {
-			atomic_inc(&entry->use);
+			refcount_inc(&entry->use);
 			read_unlock_irqrestore(&mpc->egress_lock, flags);
 			return entry;
 		}
@@ -402,7 +402,7 @@ static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr,
 	entry = mpc->eg_cache;
 	while (entry != NULL) {
 		if (entry->latest_ip_addr == ipaddr) {
-			atomic_inc(&entry->use);
+			refcount_inc(&entry->use);
 			read_unlock_irq(&mpc->egress_lock);
 			return entry;
 		}
@@ -415,7 +415,7 @@ static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr,
 
 static void eg_cache_put(eg_cache_entry *entry)
 {
-	if (atomic_dec_and_test(&entry->use)) {
+	if (refcount_dec_and_test(&entry->use)) {
 		memset(entry, 0, sizeof(eg_cache_entry));
 		kfree(entry);
 	}
@@ -468,7 +468,7 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
 	dprintk("adding an egress entry, ip = %pI4, this should be our IP\n",
 		&msg->content.eg_info.eg_dst_ip);
 
-	atomic_set(&entry->use, 1);
+	refcount_set(&entry->use, 1);
 	dprintk("new_eg_cache_entry: about to lock\n");
 	write_lock_irq(&client->egress_lock);
 	entry->next = client->eg_cache;
@@ -484,7 +484,7 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
 	dprintk("new_eg_cache_entry cache_id %u\n",
 		ntohl(entry->ctrl_info.cache_id));
 	dprintk("mps_ip = %pI4\n", &entry->ctrl_info.mps_ip);
-	atomic_inc(&entry->use);
+	refcount_inc(&entry->use);
 
 	write_unlock_irq(&client->egress_lock);
 	dprintk("new_eg_cache_entry: unlocked\n");
diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h
index 8e5f78c..30fe348 100644
--- a/net/atm/mpoa_caches.h
+++ b/net/atm/mpoa_caches.h
@@ -6,6 +6,7 @@
 #include <linux/atm.h>
 #include <linux/atmdev.h>
 #include <linux/atmmpc.h>
+#include <linux/refcount.h>
 
 struct mpoa_client;
 
@@ -25,7 +26,7 @@ typedef struct in_cache_entry {
 	struct   atm_vcc *shortcut;
 	uint8_t  MPS_ctrl_ATM_addr[ATM_ESA_LEN];
 	struct   in_ctrl_info ctrl_info;
-	atomic_t use;
+	refcount_t use;
 } in_cache_entry;
 
 struct in_cache_ops{
@@ -58,7 +59,7 @@ typedef struct eg_cache_entry{
 	uint16_t             entry_state;
 	__be32             latest_ip_addr;    /* The src IP address of the last packet */
 	struct eg_ctrl_info  ctrl_info;
-	atomic_t             use;
+	refcount_t             use;
 } eg_cache_entry;
 
 struct eg_cache_ops{
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index c4e0984..21d9d34 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -350,7 +350,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
 		return 1;
 	}
 
-	atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
 	pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
 		 skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
diff --git a/net/atm/proc.c b/net/atm/proc.c
index bbb6461..4caca2a 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -61,7 +61,7 @@ static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev)
 	add_stats(seq, "0", &dev->stats.aal0);
 	seq_puts(seq, "  ");
 	add_stats(seq, "5", &dev->stats.aal5);
-	seq_printf(seq, "\t[%d]", atomic_read(&dev->refcnt));
+	seq_printf(seq, "\t[%d]", refcount_read(&dev->refcnt));
 	seq_putc(seq, '\n');
 }
 
@@ -211,7 +211,7 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
 		   vcc->flags, sk->sk_err,
 		   sk_wmem_alloc_get(sk), sk->sk_sndbuf,
 		   sk_rmem_alloc_get(sk), sk->sk_rcvbuf,
-		   atomic_read(&sk->sk_refcnt));
+		   refcount_read(&sk->sk_refcnt));
 }
 
 static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
diff --git a/net/atm/raw.c b/net/atm/raw.c
index 2e17e97..821c079 100644
--- a/net/atm/raw.c
+++ b/net/atm/raw.c
@@ -35,7 +35,7 @@ static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb)
 
 	pr_debug("(%d) %d -= %d\n",
 		 vcc->vci, sk_wmem_alloc_get(sk), skb->truesize);
-	atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
+	WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc));
 	dev_kfree_skb_any(skb);
 	sk->sk_write_space(sk);
 }
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 0447d5d..9182447 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -109,7 +109,7 @@ struct atm_dev *atm_dev_register(const char *type, struct device *parent,
 	else
 		memset(&dev->flags, 0, sizeof(dev->flags));
 	memset(&dev->stats, 0, sizeof(dev->stats));
-	atomic_set(&dev->refcnt, 1);
+	refcount_set(&dev->refcnt, 1);
 
 	if (atm_proc_dev_register(dev) < 0) {
 		pr_err("atm_proc_dev_register failed for dev %s\n", type);
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
index adb6e3d..ca59496 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -67,7 +67,7 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb)
 	struct sock *sk;
 
 	msg = (struct atmsvc_msg *) skb->data;
-	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+	WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
 	vcc = *(struct atm_vcc **) &msg->vcc;
 	pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc);
 	sk = sk_atm(vcc);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 90fcf5f..163e81f 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -510,7 +510,7 @@ ax25_cb *ax25_create_cb(void)
 	if ((ax25 = kzalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
 		return NULL;
 
-	atomic_set(&ax25->refcount, 1);
+	refcount_set(&ax25->refcount, 1);
 
 	skb_queue_head_init(&ax25->write_queue);
 	skb_queue_head_init(&ax25->frag_queue);
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index e1fda27..0446b89 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -114,7 +114,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
 		return -ENOMEM;
 	}
 
-	atomic_set(&ax25_rt->refcount, 1);
+	refcount_set(&ax25_rt->refcount, 1);
 	ax25_rt->callsign     = route->dest_addr;
 	ax25_rt->dev          = ax25_dev->dev;
 	ax25_rt->digipeat     = NULL;
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 0403b0d..83b035f 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -107,7 +107,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
 		if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
 			return -ENOMEM;
 
-		atomic_set(&ax25_uid->refcount, 1);
+		refcount_set(&ax25_uid->refcount, 1);
 		ax25_uid->uid  = sax25_kuid;
 		ax25_uid->call = sax->sax25_call;
 
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 5f123c3..d6c68c2 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -810,7 +810,7 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
 /* AMP Manager functions */
 struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr)
 {
-	BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount));
+	BT_DBG("mgr %p orig refcnt %d", mgr, refcount_read(&mgr->kref.refcount));
 
 	kref_get(&mgr->kref);
 
@@ -833,7 +833,7 @@ static void amp_mgr_destroy(struct kref *kref)
 
 int amp_mgr_put(struct amp_mgr *mgr)
 {
-	BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount));
+	BT_DBG("mgr %p orig refcnt %d", mgr, refcount_read(&mgr->kref.refcount));
 
 	return kref_put(&mgr->kref, &amp_mgr_destroy);
 }
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 1aff2da..8196f6f 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -629,7 +629,7 @@ static int bt_seq_show(struct seq_file *seq, void *v)
 		seq_printf(seq,
 			   "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu",
 			   sk,
-			   atomic_read(&sk->sk_refcnt),
+			   refcount_read(&sk->sk_refcnt),
 			   sk_rmem_alloc_get(sk),
 			   sk_wmem_alloc_get(sk),
 			   from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index dc59eae..1102858 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -397,7 +397,7 @@ static void hci_conn_timeout(struct work_struct *work)
 {
 	struct hci_conn *conn = container_of(work, struct hci_conn,
 					     disc_work.work);
-	int refcnt = atomic_read(&conn->refcnt);
+	int refcnt = refcount_read(&conn->refcnt);
 
 	BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
 
@@ -553,7 +553,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
 	INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout);
 	INIT_WORK(&conn->le_scan_cleanup, le_scan_cleanup);
 
-	atomic_set(&conn->refcnt, 0);
+	refcount_set(&conn->refcnt, 0);
 
 	hci_dev_hold(hdev);
 
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index f7eb02f..8ebca90 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -311,7 +311,7 @@ struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio)
 
 	skb_queue_head_init(&d->tx_queue);
 	mutex_init(&d->lock);
-	atomic_set(&d->refcnt, 1);
+	refcount_set(&d->refcnt, 1);
 
 	rfcomm_dlc_clear_state(d);
 
@@ -342,7 +342,7 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
 {
 	struct rfcomm_session *s = d->session;
 
-	BT_DBG("dlc %p refcnt %d session %p", d, atomic_read(&d->refcnt), s);
+	BT_DBG("dlc %p refcnt %d session %p", d, refcount_read(&d->refcnt), s);
 
 	list_del(&d->list);
 	d->session = NULL;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 7511df7..55d07a9 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -196,7 +196,7 @@ static void rfcomm_sock_kill(struct sock *sk)
 	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
 		return;
 
-	BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, atomic_read(&sk->sk_refcnt));
+	BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
 
 	/* Kill poor orphan */
 	bt_sock_unlink(&rfcomm_sk_list, sk);
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 8ca6a92..89a857c 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -149,12 +149,12 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
 {
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
 
-	if (atomic_read(&nf_bridge->use) > 1) {
+	if (refcount_read(&nf_bridge->use) > 1) {
 		struct nf_bridge_info *tmp = nf_bridge_alloc(skb);
 
 		if (tmp) {
 			memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info));
-			atomic_set(&tmp->use, 1);
+			refcount_set(&tmp->use, 1);
 		}
 		nf_bridge_put(nf_bridge);
 		nf_bridge = tmp;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e..050ce1d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -21,6 +21,7 @@
 #include <net/ip6_fib.h>
 #include <linux/if_vlan.h>
 #include <linux/rhashtable.h>
+#include <linux/refcount.h>
 
 #define BR_HASH_BITS 8
 #define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -121,7 +122,7 @@ struct net_bridge_vlan {
 		struct net_bridge_port	*port;
 	};
 	union {
-		atomic_t		refcnt;
+		refcount_t		refcnt;
 		struct net_bridge_vlan	*brvlan;
 	};
 	struct list_head		vlist;
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index b6de4f4..0a0ef24 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -157,7 +157,7 @@ static struct net_bridge_vlan *br_vlan_get_master(struct net_bridge *br, u16 vid
 		if (WARN_ON(!masterv))
 			return NULL;
 	}
-	atomic_inc(&masterv->refcnt);
+	refcount_inc(&masterv->refcnt);
 
 	return masterv;
 }
@@ -181,7 +181,7 @@ static void br_vlan_put_master(struct net_bridge_vlan *masterv)
 		return;
 
 	vg = br_vlan_group(masterv->br);
-	if (atomic_dec_and_test(&masterv->refcnt)) {
+	if (refcount_dec_and_test(&masterv->refcnt)) {
 		rhashtable_remove_fast(&vg->vlan_hash,
 				       &masterv->vnode, br_vlan_rht_params);
 		__vlan_del_list(masterv);
@@ -563,7 +563,7 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
 				br_err(br, "failed insert local address into bridge forwarding table\n");
 				return ret;
 			}
-			atomic_inc(&vlan->refcnt);
+			refcount_inc(&vlan->refcnt);
 			vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY;
 			vg->num_vlans++;
 		}
@@ -585,7 +585,7 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
 	vlan->flags &= ~BRIDGE_VLAN_INFO_PVID;
 	vlan->br = br;
 	if (flags & BRIDGE_VLAN_INFO_BRENTRY)
-		atomic_set(&vlan->refcnt, 1);
+		refcount_set(&vlan->refcnt, 1);
 	ret = __vlan_add(vlan, flags);
 	if (ret) {
 		free_percpu(vlan->stats);
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 92cbbd2..a21eea9 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -1009,7 +1009,7 @@ static const struct proto_ops caif_stream_ops = {
 static void caif_sock_destructor(struct sock *sk)
 {
 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
-	caif_assert(!atomic_read(&sk->sk_wmem_alloc));
+	caif_assert(!refcount_read(&sk->sk_wmem_alloc));
 	caif_assert(sk_unhashed(sk));
 	caif_assert(!sk->sk_socket);
 	if (!sock_flag(sk, SOCK_DEAD)) {
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index b490e74..88a324e 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1005,7 +1005,7 @@ static bool osd_registered(struct ceph_osd *osd)
  */
 static void osd_init(struct ceph_osd *osd)
 {
-	atomic_set(&osd->o_ref, 1);
+	refcount_set(&osd->o_ref, 1);
 	RB_CLEAR_NODE(&osd->o_node);
 	osd->o_requests = RB_ROOT;
 	osd->o_linger_requests = RB_ROOT;
@@ -1050,9 +1050,9 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
 
 static struct ceph_osd *get_osd(struct ceph_osd *osd)
 {
-	if (atomic_inc_not_zero(&osd->o_ref)) {
-		dout("get_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref)-1,
-		     atomic_read(&osd->o_ref));
+	if (refcount_inc_not_zero(&osd->o_ref)) {
+		dout("get_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref)-1,
+		     refcount_read(&osd->o_ref));
 		return osd;
 	} else {
 		dout("get_osd %p FAIL\n", osd);
@@ -1062,9 +1062,9 @@ static struct ceph_osd *get_osd(struct ceph_osd *osd)
 
 static void put_osd(struct ceph_osd *osd)
 {
-	dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
-	     atomic_read(&osd->o_ref) - 1);
-	if (atomic_dec_and_test(&osd->o_ref)) {
+	dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
+	     refcount_read(&osd->o_ref) - 1);
+	if (refcount_dec_and_test(&osd->o_ref)) {
 		osd_cleanup(osd);
 		kfree(osd);
 	}
@@ -4149,7 +4149,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
 		close_osd(osd);
 	}
 	up_write(&osdc->lock);
-	WARN_ON(atomic_read(&osdc->homeless_osd.o_ref) != 1);
+	WARN_ON(refcount_read(&osdc->homeless_osd.o_ref) != 1);
 	osd_cleanup(&osdc->homeless_osd);
 
 	WARN_ON(!list_empty(&osdc->osd_lru));
diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c
index 6864007..ce09f73 100644
--- a/net/ceph/pagelist.c
+++ b/net/ceph/pagelist.c
@@ -16,7 +16,7 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
 
 void ceph_pagelist_release(struct ceph_pagelist *pl)
 {
-	if (!atomic_dec_and_test(&pl->refcnt))
+	if (!refcount_dec_and_test(&pl->refcnt))
 		return;
 	ceph_pagelist_unmap_tail(pl);
 	while (!list_empty(&pl->head)) {
diff --git a/net/ceph/snapshot.c b/net/ceph/snapshot.c
index 154683f..46db6f7 100644
--- a/net/ceph/snapshot.c
+++ b/net/ceph/snapshot.c
@@ -51,7 +51,7 @@ struct ceph_snap_context *ceph_create_snap_context(u32 snap_count,
 	if (!snapc)
 		return NULL;
 
-	atomic_set(&snapc->nref, 1);
+	refcount_set(&snapc->nref, 1);
 	snapc->num_snaps = snap_count;
 
 	return snapc;
@@ -61,7 +61,7 @@ EXPORT_SYMBOL(ceph_create_snap_context);
 struct ceph_snap_context *ceph_get_snap_context(struct ceph_snap_context *sc)
 {
 	if (sc)
-		atomic_inc(&sc->nref);
+		refcount_inc(&sc->nref);
 	return sc;
 }
 EXPORT_SYMBOL(ceph_get_snap_context);
@@ -70,7 +70,7 @@ void ceph_put_snap_context(struct ceph_snap_context *sc)
 {
 	if (!sc)
 		return;
-	if (atomic_dec_and_test(&sc->nref)) {
+	if (refcount_dec_and_test(&sc->nref)) {
 		/*printk(" deleting snap_context %p\n", sc);*/
 		kfree(sc);
 	}
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 662bea5..0595e9b 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -244,7 +244,7 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
 					}
 				}
 				*peeked = 1;
-				atomic_inc(&skb->users);
+				refcount_inc(&skb->users);
 			} else {
 				__skb_unlink(skb, queue);
 				if (destructor)
@@ -313,9 +313,9 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
 {
 	bool slow;
 
-	if (likely(atomic_read(&skb->users) == 1))
+	if (likely(refcount_read(&skb->users) == 1))
 		smp_rmb();
-	else if (likely(!atomic_dec_and_test(&skb->users))) {
+	else if (likely(!refcount_dec_and_test(&skb->users))) {
 		sk_peek_offset_bwd(sk, len);
 		return;
 	}
@@ -341,7 +341,7 @@ int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
 		spin_lock_bh(&sk->sk_receive_queue.lock);
 		if (skb == skb_peek(&sk->sk_receive_queue)) {
 			__skb_unlink(skb, &sk->sk_receive_queue);
-			atomic_dec(&skb->users);
+			refcount_dec(&skb->users);
 			err = 0;
 		}
 		spin_unlock_bh(&sk->sk_receive_queue.lock);
@@ -591,7 +591,7 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
 		skb->data_len += copied;
 		skb->len += copied;
 		skb->truesize += truesize;
-		atomic_add(truesize, &skb->sk->sk_wmem_alloc);
+		refcount_add(truesize, &skb->sk->sk_wmem_alloc);
 		while (copied) {
 			int size = min_t(int, copied, PAGE_SIZE - start);
 			skb_fill_page_desc(skb, frag++, pages[n], start, size);
diff --git a/net/core/dev.c b/net/core/dev.c
index 8db5a0b..2661354 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1806,7 +1806,7 @@ static inline int deliver_skb(struct sk_buff *skb,
 {
 	if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
 		return -ENOMEM;
-	atomic_inc(&skb->users);
+	refcount_inc(&skb->users);
 	return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
 }
 
@@ -2447,10 +2447,10 @@ void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason)
 {
 	unsigned long flags;
 
-	if (likely(atomic_read(&skb->users) == 1)) {
+	if (likely(refcount_read(&skb->users) == 1)) {
 		smp_rmb();
-		atomic_set(&skb->users, 0);
-	} else if (likely(!atomic_dec_and_test(&skb->users))) {
+		refcount_set(&skb->users, 0);
+	} else if (likely(!refcount_dec_and_test(&skb->users))) {
 		return;
 	}
 	get_kfree_skb_cb(skb)->reason = reason;
@@ -3845,7 +3845,7 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
 			struct sk_buff *skb = clist;
 			clist = clist->next;
 
-			WARN_ON(atomic_read(&skb->users));
+			WARN_ON(refcount_read(&skb->users));
 			if (likely(get_kfree_skb_cb(skb)->reason == SKB_REASON_CONSUMED))
 				trace_consume_skb(skb);
 			else
diff --git a/net/core/dst.c b/net/core/dst.c
index b5cbbe0..6d11cbe 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -300,14 +300,9 @@ static void dst_destroy_rcu(struct rcu_head *head)
 void dst_release(struct dst_entry *dst)
 {
 	if (dst) {
-		int newrefcnt;
 		unsigned short nocache = dst->flags & DST_NOCACHE;
 
-		newrefcnt = atomic_dec_return(&dst->__refcnt);
-		if (unlikely(newrefcnt < 0))
-			net_warn_ratelimited("%s: dst:%p refcnt:%d\n",
-					     __func__, dst, newrefcnt);
-		if (!newrefcnt && unlikely(nocache))
+		if (!atomic_dec_and_test(&dst->__refcnt) && unlikely(nocache))
 			call_rcu(&dst->rcu_head, dst_destroy_rcu);
 	}
 }
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index b6791d9..53d55d5 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -32,7 +32,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
 	if (r == NULL)
 		return -ENOMEM;
 
-	atomic_set(&r->refcnt, 1);
+	refcount_set(&r->refcnt, 1);
 	r->action = FR_ACT_TO_TBL;
 	r->pref = pref;
 	r->table = table;
@@ -269,7 +269,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
 
 		if (err != -EAGAIN) {
 			if ((arg->flags & FIB_LOOKUP_NOREF) ||
-			    likely(atomic_inc_not_zero(&rule->refcnt))) {
+			    likely(refcount_inc_not_zero(&rule->refcnt))) {
 				arg->rule = rule;
 				goto out;
 			}
diff --git a/net/core/filter.c b/net/core/filter.c
index 1969b3f..fce4f06 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -927,7 +927,7 @@ static void sk_filter_release_rcu(struct rcu_head *rcu)
  */
 static void sk_filter_release(struct sk_filter *fp)
 {
-	if (atomic_dec_and_test(&fp->refcnt))
+	if (refcount_dec_and_test(&fp->refcnt))
 		call_rcu(&fp->rcu, sk_filter_release_rcu);
 }
 
@@ -949,7 +949,7 @@ bool sk_filter_charge(struct sock *sk, struct sk_filter *fp)
 	/* same check as in sock_kmalloc() */
 	if (filter_size <= sysctl_optmem_max &&
 	    atomic_read(&sk->sk_omem_alloc) + filter_size < sysctl_optmem_max) {
-		atomic_inc(&fp->refcnt);
+		refcount_set(&fp->refcnt, 1);
 		atomic_add(filter_size, &sk->sk_omem_alloc);
 		return true;
 	}
@@ -1178,7 +1178,7 @@ static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk)
 		return -ENOMEM;
 
 	fp->prog = prog;
-	atomic_set(&fp->refcnt, 0);
+	refcount_set(&fp->refcnt, 0);
 
 	if (!sk_filter_charge(sk, fp)) {
 		kfree(fp);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 7bb12e0..dee2486 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -140,7 +140,7 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 			 * - it is not permanent
 			 */
 			write_lock(&n->lock);
-			if (atomic_read(&n->refcnt) == 1 &&
+			if (refcount_read(&n->refcnt) == 1 &&
 			    !(n->nud_state & NUD_PERMANENT)) {
 				rcu_assign_pointer(*np,
 					rcu_dereference_protected(n->next,
@@ -218,7 +218,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
 			neigh_del_timer(n);
 			n->dead = 1;
 
-			if (atomic_read(&n->refcnt) != 1) {
+			if (refcount_read(&n->refcnt) != 1) {
 				/* The most unpleasant situation.
 				   We must destroy neighbour entry,
 				   but someone still uses it.
@@ -299,7 +299,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device
 
 	NEIGH_CACHE_STAT_INC(tbl, allocs);
 	n->tbl		  = tbl;
-	atomic_set(&n->refcnt, 1);
+	refcount_set(&n->refcnt, 1);
 	n->dead		  = 1;
 out:
 	return n;
@@ -408,7 +408,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
 	rcu_read_lock_bh();
 	n = __neigh_lookup_noref(tbl, pkey, dev);
 	if (n) {
-		if (!atomic_inc_not_zero(&n->refcnt))
+		if (!refcount_inc_not_zero(&n->refcnt))
 			n = NULL;
 		NEIGH_CACHE_STAT_INC(tbl, hits);
 	}
@@ -437,7 +437,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
 	     n = rcu_dereference_bh(n->next)) {
 		if (!memcmp(n->primary_key, pkey, key_len) &&
 		    net_eq(dev_net(n->dev), net)) {
-			if (!atomic_inc_not_zero(&n->refcnt))
+			if (!refcount_inc_not_zero(&n->refcnt))
 				n = NULL;
 			NEIGH_CACHE_STAT_INC(tbl, hits);
 			break;
@@ -673,7 +673,7 @@ static void neigh_parms_destroy(struct neigh_parms *parms);
 
 static inline void neigh_parms_put(struct neigh_parms *parms)
 {
-	if (atomic_dec_and_test(&parms->refcnt))
+	if (refcount_dec_and_test(&parms->refcnt))
 		neigh_parms_destroy(parms);
 }
 
@@ -785,7 +785,7 @@ static void neigh_periodic_work(struct work_struct *work)
 			if (time_before(n->used, n->confirmed))
 				n->used = n->confirmed;
 
-			if (atomic_read(&n->refcnt) == 1 &&
+			if (refcount_read(&n->refcnt) == 1 &&
 			    (state == NUD_FAILED ||
 			     time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
 				*np = n->next;
@@ -1436,7 +1436,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
 	p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
 	if (p) {
 		p->tbl		  = tbl;
-		atomic_set(&p->refcnt, 1);
+		refcount_set(&p->refcnt, 1);
 		p->reachable_time =
 				neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
 		dev_hold(dev);
@@ -1499,7 +1499,7 @@ void neigh_table_init(int index, struct neigh_table *tbl)
 	INIT_LIST_HEAD(&tbl->parms_list);
 	list_add(&tbl->parms.list, &tbl->parms_list);
 	write_pnet(&tbl->parms.net, &init_net);
-	atomic_set(&tbl->parms.refcnt, 1);
+	refcount_set(&tbl->parms.refcnt, 1);
 	tbl->parms.reachable_time =
 			  neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
 
@@ -1746,7 +1746,7 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
 
 	if ((parms->dev &&
 	     nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
-	    nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
+	    nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
 	    nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
 			NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
 	    /* approximative value for deprecated QUEUE_LEN (in packets) */
@@ -2183,7 +2183,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
 	ci.ndm_used	 = jiffies_to_clock_t(now - neigh->used);
 	ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
 	ci.ndm_updated	 = jiffies_to_clock_t(now - neigh->updated);
-	ci.ndm_refcnt	 = atomic_read(&neigh->refcnt) - 1;
+	ci.ndm_refcnt	 = refcount_read(&neigh->refcnt) - 1;
 	read_unlock_bh(&neigh->lock);
 
 	if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b0c04cf..cc3c21a 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1443,7 +1443,7 @@ static void *net_grab_current_ns(void)
 	struct net *ns = current->nsproxy->net_ns;
 #ifdef CONFIG_NET_NS
 	if (ns)
-		atomic_inc(&ns->passive);
+		refcount_inc(&ns->passive);
 #endif
 	return ns;
 }
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 3c4bbec..a0eb969 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -281,7 +281,7 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
 	LIST_HEAD(net_exit_list);
 
 	atomic_set(&net->count, 1);
-	atomic_set(&net->passive, 1);
+	refcount_set(&net->passive, 1);
 	net->dev_base_seq = 1;
 	net->user_ns = user_ns;
 	idr_init(&net->netns_ids);
@@ -358,7 +358,7 @@ static void net_free(struct net *net)
 void net_drop_ns(void *p)
 {
 	struct net *ns = p;
-	if (ns && atomic_dec_and_test(&ns->passive))
+	if (ns && refcount_dec_and_test(&ns->passive))
 		net_free(ns);
 }
 
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 9424673..8b9083d 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -271,7 +271,7 @@ static void zap_completion_queue(void)
 			struct sk_buff *skb = clist;
 			clist = clist->next;
 			if (!skb_irq_freeable(skb)) {
-				atomic_inc(&skb->users);
+				refcount_inc(&skb->users);
 				dev_kfree_skb_any(skb); /* put this one back */
 			} else {
 				__kfree_skb(skb);
@@ -303,7 +303,7 @@ static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
 		return NULL;
 	}
 
-	atomic_set(&skb->users, 1);
+	refcount_set(&skb->users, 1);
 	skb_reserve(skb, reserve);
 	return skb;
 }
@@ -626,7 +626,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
 		skb_queue_head_init(&npinfo->txq);
 		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
 
-		atomic_set(&npinfo->refcnt, 1);
+		refcount_set(&npinfo->refcnt, 1);
 
 		ops = np->dev->netdev_ops;
 		if (ops->ndo_netpoll_setup) {
@@ -636,7 +636,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
 		}
 	} else {
 		npinfo = rtnl_dereference(ndev->npinfo);
-		atomic_inc(&npinfo->refcnt);
+		refcount_inc(&npinfo->refcnt);
 	}
 
 	npinfo->netpoll = np;
@@ -815,7 +815,7 @@ void __netpoll_cleanup(struct netpoll *np)
 
 	synchronize_srcu(&netpoll_srcu);
 
-	if (atomic_dec_and_test(&npinfo->refcnt)) {
+	if (refcount_dec_and_test(&npinfo->refcnt)) {
 		const struct net_device_ops *ops;
 
 		ops = np->dev->netdev_ops;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 8e69ce4..787d624 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3361,7 +3361,7 @@ static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
 {
 	ktime_t idle_start = ktime_get();
 
-	while (atomic_read(&(pkt_dev->skb->users)) != 1) {
+	while (refcount_read(&(pkt_dev->skb->users)) != 1) {
 		if (signal_pending(current))
 			break;
 
@@ -3418,7 +3418,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 	if (pkt_dev->xmit_mode == M_NETIF_RECEIVE) {
 		skb = pkt_dev->skb;
 		skb->protocol = eth_type_trans(skb, skb->dev);
-		atomic_add(burst, &skb->users);
+		refcount_add(burst, &skb->users);
 		local_bh_disable();
 		do {
 			ret = netif_receive_skb(skb);
@@ -3426,11 +3426,11 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 				pkt_dev->errors++;
 			pkt_dev->sofar++;
 			pkt_dev->seq_num++;
-			if (atomic_read(&skb->users) != burst) {
+			if (refcount_read(&skb->users) != burst) {
 				/* skb was queued by rps/rfs or taps,
 				 * so cannot reuse this skb
 				 */
-				atomic_sub(burst - 1, &skb->users);
+				WARN_ON(refcount_sub_and_test(burst - 1, &skb->users));
 				/* get out of the loop and wait
 				 * until skb is consumed
 				 */
@@ -3446,7 +3446,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 		goto out; /* Skips xmit_mode M_START_XMIT */
 	} else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) {
 		local_bh_disable();
-		atomic_inc(&pkt_dev->skb->users);
+		refcount_inc(&pkt_dev->skb->users);
 
 		ret = dev_queue_xmit(pkt_dev->skb);
 		switch (ret) {
@@ -3487,7 +3487,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 		pkt_dev->last_ok = 0;
 		goto unlock;
 	}
-	atomic_add(burst, &pkt_dev->skb->users);
+	refcount_add(burst, &pkt_dev->skb->users);
 
 xmit_more:
 	ret = netdev_start_xmit(pkt_dev->skb, odev, txq, --burst > 0);
@@ -3513,11 +3513,11 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 		/* fallthru */
 	case NETDEV_TX_BUSY:
 		/* Retry it next time */
-		atomic_dec(&(pkt_dev->skb->users));
+		refcount_dec(&(pkt_dev->skb->users));
 		pkt_dev->last_ok = 0;
 	}
 	if (unlikely(burst))
-		atomic_sub(burst, &pkt_dev->skb->users);
+		WARN_ON(refcount_sub_and_test(burst, &pkt_dev->skb->users));
 unlock:
 	HARD_TX_UNLOCK(odev, txq);
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 18b5aae..b2d9035 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -647,7 +647,7 @@ int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int g
 
 	NETLINK_CB(skb).dst_group = group;
 	if (echo)
-		atomic_inc(&skb->users);
+		refcount_inc(&skb->users);
 	netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL);
 	if (echo)
 		err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5a03730..ac86c66 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -176,7 +176,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node)
 	memset(skb, 0, offsetof(struct sk_buff, tail));
 	skb->head = NULL;
 	skb->truesize = sizeof(struct sk_buff);
-	atomic_set(&skb->users, 1);
+	refcount_set(&skb->users, 1);
 
 	skb->mac_header = (typeof(skb->mac_header))~0U;
 out:
@@ -247,7 +247,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
 	/* Account for allocated memory : skb + skb->head */
 	skb->truesize = SKB_TRUESIZE(size);
 	skb->pfmemalloc = pfmemalloc;
-	atomic_set(&skb->users, 1);
+	refcount_set(&skb->users, 1);
 	skb->head = data;
 	skb->data = data;
 	skb_reset_tail_pointer(skb);
@@ -268,7 +268,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
 
 		kmemcheck_annotate_bitfield(&fclones->skb2, flags1);
 		skb->fclone = SKB_FCLONE_ORIG;
-		atomic_set(&fclones->fclone_ref, 1);
+		refcount_set(&fclones->fclone_ref, 1);
 
 		fclones->skb2.fclone = SKB_FCLONE_CLONE;
 		fclones->skb2.pfmemalloc = pfmemalloc;
@@ -315,7 +315,7 @@ struct sk_buff *__build_skb(void *data, unsigned int frag_size)
 
 	memset(skb, 0, offsetof(struct sk_buff, tail));
 	skb->truesize = SKB_TRUESIZE(size);
-	atomic_set(&skb->users, 1);
+	refcount_set(&skb->users, 1);
 	skb->head = data;
 	skb->data = data;
 	skb_reset_tail_pointer(skb);
@@ -630,7 +630,7 @@ static void kfree_skbmem(struct sk_buff *skb)
 		 * This test would have no chance to be true for the clone,
 		 * while here, branch prediction will be good.
 		 */
-		if (atomic_read(&fclones->fclone_ref) == 1)
+		if (refcount_read(&fclones->fclone_ref) == 1)
 			goto fastpath;
 		break;
 
@@ -638,7 +638,7 @@ static void kfree_skbmem(struct sk_buff *skb)
 		fclones = container_of(skb, struct sk_buff_fclones, skb2);
 		break;
 	}
-	if (!atomic_dec_and_test(&fclones->fclone_ref))
+	if (!refcount_dec_and_test(&fclones->fclone_ref))
 		return;
 fastpath:
 	kmem_cache_free(skbuff_fclone_cache, fclones);
@@ -697,9 +697,9 @@ void kfree_skb(struct sk_buff *skb)
 {
 	if (unlikely(!skb))
 		return;
-	if (likely(atomic_read(&skb->users) == 1))
+	if (likely(refcount_read(&skb->users) == 1))
 		smp_rmb();
-	else if (likely(!atomic_dec_and_test(&skb->users)))
+	else if (likely(!refcount_dec_and_test(&skb->users)))
 		return;
 	trace_kfree_skb(skb, __builtin_return_address(0));
 	__kfree_skb(skb);
@@ -749,9 +749,9 @@ void consume_skb(struct sk_buff *skb)
 {
 	if (unlikely(!skb))
 		return;
-	if (likely(atomic_read(&skb->users) == 1))
+	if (likely(refcount_read(&skb->users) == 1))
 		smp_rmb();
-	else if (likely(!atomic_dec_and_test(&skb->users)))
+	else if (likely(!refcount_dec_and_test(&skb->users)))
 		return;
 	trace_consume_skb(skb);
 	__kfree_skb(skb);
@@ -808,9 +808,9 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
 		return;
 	}
 
-	if (likely(atomic_read(&skb->users) == 1))
+	if (likely(refcount_read(&skb->users) == 1))
 		smp_rmb();
-	else if (likely(!atomic_dec_and_test(&skb->users)))
+	else if (likely(!refcount_dec_and_test(&skb->users)))
 		return;
 	/* if reaching here SKB is ready to free */
 	trace_consume_skb(skb);
@@ -910,7 +910,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
 	C(head_frag);
 	C(data);
 	C(truesize);
-	atomic_set(&n->users, 1);
+	refcount_set(&n->users, 1);
 
 	atomic_inc(&(skb_shinfo(skb)->dataref));
 	skb->cloned = 1;
@@ -1022,9 +1022,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
 		return NULL;
 
 	if (skb->fclone == SKB_FCLONE_ORIG &&
-	    atomic_read(&fclones->fclone_ref) == 1) {
+	    refcount_read(&fclones->fclone_ref) == 1) {
 		n = &fclones->skb2;
-		atomic_set(&fclones->fclone_ref, 2);
+		refcount_set(&fclones->fclone_ref, 2);
 	} else {
 		if (skb_pfmemalloc(skb))
 			gfp_mask |= __GFP_MEMALLOC;
@@ -2983,7 +2983,7 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 		get_page(pfrag->page);
 
 		skb->truesize += copy;
-		atomic_add(copy, &sk->sk_wmem_alloc);
+		refcount_add(copy, &sk->sk_wmem_alloc);
 		skb->len += copy;
 		skb->data_len += copy;
 		offset += copy;
@@ -3761,7 +3761,7 @@ struct sk_buff *skb_clone_sk(struct sk_buff *skb)
 	struct sock *sk = skb->sk;
 	struct sk_buff *clone;
 
-	if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt))
+	if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
 		return NULL;
 
 	clone = skb_clone(skb, GFP_ATOMIC);
diff --git a/net/core/sock.c b/net/core/sock.c
index f560e08..b11edc1 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1406,7 +1406,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
 		if (likely(sk->sk_net_refcnt))
 			get_net(net);
 		sock_net_set(sk, net);
-		atomic_set(&sk->sk_wmem_alloc, 1);
+		refcount_set(&sk->sk_wmem_alloc, 1);
 
 		mem_cgroup_sk_alloc(sk);
 		cgroup_sk_alloc(&sk->sk_cgrp_data);
@@ -1430,7 +1430,7 @@ static void __sk_destruct(struct rcu_head *head)
 		sk->sk_destruct(sk);
 
 	filter = rcu_dereference_check(sk->sk_filter,
-				       atomic_read(&sk->sk_wmem_alloc) == 0);
+				       refcount_read(&sk->sk_wmem_alloc) == 0);
 	if (filter) {
 		sk_filter_uncharge(sk, filter);
 		RCU_INIT_POINTER(sk->sk_filter, NULL);
@@ -1475,7 +1475,7 @@ void sk_free(struct sock *sk)
 	 * some packets are still in some tx queue.
 	 * If not null, sock_wfree() will call __sk_free(sk) later
 	 */
-	if (atomic_dec_and_test(&sk->sk_wmem_alloc))
+	if (refcount_dec_and_test(&sk->sk_wmem_alloc))
 		__sk_free(sk);
 }
 EXPORT_SYMBOL(sk_free);
@@ -1511,7 +1511,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
 		/*
 		 * sk_wmem_alloc set to one (see sk_free() and sock_wfree())
 		 */
-		atomic_set(&newsk->sk_wmem_alloc, 1);
+		refcount_set(&newsk->sk_wmem_alloc, 1);
 		atomic_set(&newsk->sk_omem_alloc, 0);
 		skb_queue_head_init(&newsk->sk_receive_queue);
 		skb_queue_head_init(&newsk->sk_write_queue);
@@ -1564,7 +1564,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
 		 * (Documentation/RCU/rculist_nulls.txt for details)
 		 */
 		smp_wmb();
-		atomic_set(&newsk->sk_refcnt, 2);
+		refcount_set(&newsk->sk_refcnt, 2);
 
 		/*
 		 * Increment the counter in the same struct proto as the master
@@ -1633,7 +1633,7 @@ void sock_wfree(struct sk_buff *skb)
 		 * Keep a reference on sk_wmem_alloc, this will be released
 		 * after sk_write_space() call
 		 */
-		atomic_sub(len - 1, &sk->sk_wmem_alloc);
+		WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
 		sk->sk_write_space(sk);
 		len = 1;
 	}
@@ -1641,7 +1641,7 @@ void sock_wfree(struct sk_buff *skb)
 	 * if sk_wmem_alloc reaches 0, we must finish what sk_free()
 	 * could not do because of in-flight packets
 	 */
-	if (atomic_sub_and_test(len, &sk->sk_wmem_alloc))
+	if (refcount_sub_and_test(len, &sk->sk_wmem_alloc))
 		__sk_free(sk);
 }
 EXPORT_SYMBOL(sock_wfree);
@@ -1653,7 +1653,7 @@ void __sock_wfree(struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
 
-	if (atomic_sub_and_test(skb->truesize, &sk->sk_wmem_alloc))
+	if (refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc))
 		__sk_free(sk);
 }
 
@@ -1675,7 +1675,7 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
 	 * is enough to guarantee sk_free() wont free this sock until
 	 * all in-flight packets are completed
 	 */
-	atomic_add(skb->truesize, &sk->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk->sk_wmem_alloc);
 }
 EXPORT_SYMBOL(skb_set_owner_w);
 
@@ -1703,7 +1703,7 @@ void skb_orphan_partial(struct sk_buff *skb)
 	    || skb->destructor == tcp_wfree
 #endif
 		) {
-		atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
+		WARN_ON(refcount_sub_and_test(skb->truesize - 1, &skb->sk->sk_wmem_alloc));
 		skb->truesize = 1;
 	} else {
 		skb_orphan(skb);
@@ -1762,7 +1762,7 @@ EXPORT_SYMBOL(sock_i_ino);
 struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
 			     gfp_t priority)
 {
-	if (force || atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
+	if (force || refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
 		struct sk_buff *skb = alloc_skb(size, priority);
 		if (skb) {
 			skb_set_owner_w(skb, sk);
@@ -1837,7 +1837,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo)
 			break;
 		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-		if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf)
+		if (refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf)
 			break;
 		if (sk->sk_shutdown & SEND_SHUTDOWN)
 			break;
@@ -2140,7 +2140,7 @@ int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
 		if (sk->sk_type == SOCK_STREAM) {
 			if (sk->sk_wmem_queued < prot->sysctl_wmem[0])
 				return 1;
-		} else if (atomic_read(&sk->sk_wmem_alloc) <
+		} else if (refcount_read(&sk->sk_wmem_alloc) <
 			   prot->sysctl_wmem[0])
 				return 1;
 	}
@@ -2406,7 +2406,7 @@ static void sock_def_write_space(struct sock *sk)
 	/* Do not wake up a writer until he can make "significant"
 	 * progress.  --DaveM
 	 */
-	if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
+	if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
 		wq = rcu_dereference(sk->sk_wq);
 		if (skwq_has_sleeper(wq))
 			wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
@@ -2512,7 +2512,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
 	 * (Documentation/RCU/rculist_nulls.txt for details)
 	 */
 	smp_wmb();
-	atomic_set(&sk->sk_refcnt, 1);
+	refcount_set(&sk->sk_refcnt, 1);
 	atomic_set(&sk->sk_drops, 0);
 }
 EXPORT_SYMBOL(sock_init_data);
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index adfc790..616bd53 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -351,7 +351,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) ||
 	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
 	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
-		atomic_inc(&skb->users);
+		refcount_inc(&skb->users);
 		ireq->pktopts = skb;
 	}
 	ireq->ir_iif = sk->sk_bound_dev_if;
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 7af0ba61..2e22484 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -389,7 +389,7 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct nlattr *att
 	}
 
 	fi->fib_treeref++;
-	atomic_inc(&fi->fib_clntref);
+	refcount_inc(&fi->fib_clntref);
 	spin_lock(&dn_fib_info_lock);
 	fi->fib_next = dn_fib_info_list;
 	fi->fib_prev = NULL;
@@ -425,7 +425,7 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn
 		switch (type) {
 		case RTN_NAT:
 			DN_FIB_RES_RESET(*res);
-			atomic_inc(&fi->fib_clntref);
+			refcount_inc(&fi->fib_clntref);
 			return 0;
 		case RTN_UNICAST:
 		case RTN_LOCAL:
@@ -438,7 +438,7 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn
 			}
 			if (nhsel < fi->fib_nhs) {
 				res->nh_sel = nhsel;
-				atomic_inc(&fi->fib_clntref);
+				refcount_inc(&fi->fib_clntref);
 				return 0;
 			}
 			endfor_nexthops(fi);
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 482730c..d8f7b6d 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -559,7 +559,7 @@ static inline void dn_neigh_format_entry(struct seq_file *seq,
 		   (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
 		   (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
 		   dn->n.nud_state,
-		   atomic_read(&dn->n.refcnt),
+		   refcount_read(&dn->n.refcnt),
 		   dn->blksize,
 		   (dn->n.dev) ? dn->n.dev->name : "?");
 	read_unlock(&n->lock);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f750698..e771346 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -150,7 +150,7 @@ void inet_sock_destruct(struct sock *sk)
 	}
 
 	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
-	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
 	WARN_ON(sk->sk_wmem_queued);
 	WARN_ON(sk->sk_forward_alloc);
 
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 72d6f05..55b5300 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -265,7 +265,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
 		    entry->key_len == key_len &&
 		    memcmp(entry->key, key, key_len) == 0) {
 			entry->activity += 1;
-			atomic_inc(&entry->lsm_data->refcount);
+			refcount_inc(&entry->lsm_data->refcount);
 			secattr->cache = entry->lsm_data;
 			secattr->flags |= NETLBL_SECATTR_CACHE;
 			secattr->type = NETLBL_NLTYPE_CIPSOV4;
@@ -332,7 +332,7 @@ int cipso_v4_cache_add(const unsigned char *cipso_ptr,
 	}
 	entry->key_len = cipso_ptr_len;
 	entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
-	atomic_inc(&secattr->cache->refcount);
+	refcount_inc(&secattr->cache->refcount);
 	entry->lsm_data = secattr->cache;
 
 	bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETS - 1);
@@ -375,7 +375,7 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
 	struct cipso_v4_doi *iter;
 
 	list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
-		if (iter->doi == doi && atomic_read(&iter->refcount))
+		if (iter->doi == doi && refcount_read(&iter->refcount))
 			return iter;
 	return NULL;
 }
@@ -429,7 +429,7 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
 		}
 	}
 
-	atomic_set(&doi_def->refcount, 1);
+	refcount_set(&doi_def->refcount, 1);
 
 	spin_lock(&cipso_v4_doi_list_lock);
 	if (cipso_v4_doi_search(doi_def->doi)) {
@@ -533,7 +533,7 @@ int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)
 		ret_val = -ENOENT;
 		goto doi_remove_return;
 	}
-	if (!atomic_dec_and_test(&doi_def->refcount)) {
+	if (!refcount_dec_and_test(&doi_def->refcount)) {
 		spin_unlock(&cipso_v4_doi_list_lock);
 		ret_val = -EBUSY;
 		goto doi_remove_return;
@@ -576,7 +576,7 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
 	doi_def = cipso_v4_doi_search(doi);
 	if (!doi_def)
 		goto doi_getdef_return;
-	if (!atomic_inc_not_zero(&doi_def->refcount))
+	if (!refcount_inc_not_zero(&doi_def->refcount))
 		doi_def = NULL;
 
 doi_getdef_return:
@@ -597,7 +597,7 @@ void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def)
 	if (!doi_def)
 		return;
 
-	if (!atomic_dec_and_test(&doi_def->refcount))
+	if (!refcount_dec_and_test(&doi_def->refcount))
 		return;
 	spin_lock(&cipso_v4_doi_list_lock);
 	list_del_rcu(&doi_def->list);
@@ -630,7 +630,7 @@ int cipso_v4_doi_walk(u32 *skip_cnt,
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
-		if (atomic_read(&iter_doi->refcount) > 0) {
+		if (refcount_read(&iter_doi->refcount) > 0) {
 			if (doi_cnt++ < *skip_cnt)
 				continue;
 			ret_val = callback(iter_doi, cb_arg);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 4cd2ee8..db5ba13 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -252,7 +252,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
 	/* Reference in_dev->dev */
 	dev_hold(dev);
 	/* Account for reference dev->ip_ptr (below) */
-	in_dev_hold(in_dev);
+	refcount_set(&in_dev->refcnt, 1);
 
 	err = devinet_sysctl_register(in_dev);
 	if (err) {
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 7a5b4c7..49ce888 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1185,7 +1185,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 	}
 
 	fi->fib_treeref++;
-	atomic_inc(&fi->fib_clntref);
+	refcount_set(&fi->fib_clntref, 1);
 	spin_lock_bh(&fib_info_lock);
 	hlist_add_head(&fi->fib_hash,
 		       &fib_info_hash[fib_info_hashfn(fi)]);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 2919d1a..77e51ca 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1542,7 +1542,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
 			}
 
 			if (!(fib_flags & FIB_LOOKUP_NOREF))
-				atomic_inc(&fi->fib_clntref);
+				refcount_inc(&fi->fib_clntref);
 
 			res->prefixlen = KEYLENGTH - fa->fa_slen;
 			res->nh_sel = nhsel;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 68d6221..3c675e3 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -173,7 +173,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
 
 static void ip_ma_put(struct ip_mc_list *im)
 {
-	if (atomic_dec_and_test(&im->refcnt)) {
+	if (refcount_dec_and_test(&im->refcnt)) {
 		in_dev_put(im->interface);
 		kfree_rcu(im, rcu);
 	}
@@ -199,7 +199,7 @@ static void igmp_stop_timer(struct ip_mc_list *im)
 {
 	spin_lock_bh(&im->lock);
 	if (del_timer(&im->timer))
-		atomic_dec(&im->refcnt);
+		refcount_dec(&im->refcnt);
 	im->tm_running = 0;
 	im->reporter = 0;
 	im->unsolicit_count = 0;
@@ -213,7 +213,7 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
 
 	im->tm_running = 1;
 	if (!mod_timer(&im->timer, jiffies+tv+2))
-		atomic_inc(&im->refcnt);
+		refcount_inc(&im->refcnt);
 }
 
 static void igmp_gq_start_timer(struct in_device *in_dev)
@@ -244,7 +244,7 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
 			spin_unlock_bh(&im->lock);
 			return;
 		}
-		atomic_dec(&im->refcnt);
+		refcount_dec(&im->refcnt);
 	}
 	igmp_start_timer(im, max_delay);
 	spin_unlock_bh(&im->lock);
@@ -1367,7 +1367,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
 	/* initial mode is (EX, empty) */
 	im->sfmode = MCAST_EXCLUDE;
 	im->sfcount[MCAST_EXCLUDE] = 1;
-	atomic_set(&im->refcnt, 1);
+	refcount_set(&im->refcnt, 1);
 	spin_lock_init(&im->lock);
 #ifdef CONFIG_IP_MULTICAST
 	setup_timer(&im->timer, igmp_timer_expire, (unsigned long)im);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 19ea045..edf004d 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -630,7 +630,7 @@ static void reqsk_queue_hash_req(struct request_sock *req,
 	 * are committed to memory and refcnt initialized.
 	 */
 	smp_wmb();
-	atomic_set(&req->rsk_refcnt, 2 + 1);
+	refcount_set(&req->rsk_refcnt, 2 + 1);
 }
 
 void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index b5e9317..96e95e8 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -276,11 +276,11 @@ static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f)
 void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
 {
 	if (del_timer(&fq->timer))
-		atomic_dec(&fq->refcnt);
+		refcount_dec(&fq->refcnt);
 
 	if (!(fq->flags & INET_FRAG_COMPLETE)) {
 		fq_unlink(fq, f);
-		atomic_dec(&fq->refcnt);
+		refcount_dec(&fq->refcnt);
 	}
 }
 EXPORT_SYMBOL(inet_frag_kill);
@@ -329,7 +329,7 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
 	 */
 	hlist_for_each_entry(qp, &hb->chain, list) {
 		if (qp->net == nf && f->match(qp, arg)) {
-			atomic_inc(&qp->refcnt);
+			refcount_inc(&qp->refcnt);
 			spin_unlock(&hb->chain_lock);
 			qp_in->flags |= INET_FRAG_COMPLETE;
 			inet_frag_put(qp_in, f);
@@ -339,9 +339,9 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
 #endif
 	qp = qp_in;
 	if (!mod_timer(&qp->timer, jiffies + nf->timeout))
-		atomic_inc(&qp->refcnt);
+		refcount_inc(&qp->refcnt);
 
-	atomic_inc(&qp->refcnt);
+	refcount_inc(&qp->refcnt);
 	hlist_add_head(&qp->list, &hb->chain);
 
 	spin_unlock(&hb->chain_lock);
@@ -370,7 +370,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
 
 	setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
 	spin_lock_init(&q->lock);
-	atomic_set(&q->refcnt, 1);
+	refcount_set(&q->refcnt, 1);
 
 	return q;
 }
@@ -405,7 +405,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
 	spin_lock(&hb->chain_lock);
 	hlist_for_each_entry(q, &hb->chain, list) {
 		if (q->net == nf && f->match(q, key)) {
-			atomic_inc(&q->refcnt);
+			refcount_inc(&q->refcnt);
 			spin_unlock(&hb->chain_lock);
 			return q;
 		}
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ca97835..e34f3bd 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -249,7 +249,7 @@ EXPORT_SYMBOL_GPL(__inet_lookup_listener);
 /* All sockets share common refcount, but have different destructors */
 void sock_gen_put(struct sock *sk)
 {
-	if (!atomic_dec_and_test(&sk->sk_refcnt))
+	if (!refcount_dec_and_test(&sk->sk_refcnt))
 		return;
 
 	if (sk->sk_state == TCP_TIME_WAIT)
@@ -290,7 +290,7 @@ struct sock *__inet_lookup_established(struct net *net,
 			continue;
 		if (likely(INET_MATCH(sk, net, acookie,
 				      saddr, daddr, ports, dif))) {
-			if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
+			if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
 				goto out;
 			if (unlikely(!INET_MATCH(sk, net, acookie,
 						 saddr, daddr, ports, dif))) {
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index ddcd56c..e0b6cc5 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -76,7 +76,7 @@ void inet_twsk_free(struct inet_timewait_sock *tw)
 
 void inet_twsk_put(struct inet_timewait_sock *tw)
 {
-	if (atomic_dec_and_test(&tw->tw_refcnt))
+	if (refcount_dec_and_test(&tw->tw_refcnt))
 		inet_twsk_free(tw);
 }
 EXPORT_SYMBOL_GPL(inet_twsk_put);
@@ -131,7 +131,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 	 * We can use atomic_set() because prior spin_lock()/spin_unlock()
 	 * committed into memory all tw fields.
 	 */
-	atomic_set(&tw->tw_refcnt, 4);
+	refcount_set(&tw->tw_refcnt, 4);
 	inet_twsk_add_node_rcu(tw, &ehead->chain);
 
 	/* Step 3: Remove SK from hash chain */
@@ -195,7 +195,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
 		 * to a non null value before everything is setup for this
 		 * timewait socket.
 		 */
-		atomic_set(&tw->tw_refcnt, 0);
+		refcount_set(&tw->tw_refcnt, 0);
 
 		__module_get(tw->tw_prot->owner);
 	}
@@ -279,7 +279,7 @@ void inet_twsk_purge(struct inet_hashinfo *hashinfo,
 				atomic_read(&twsk_net(tw)->count))
 				continue;
 
-			if (unlikely(!atomic_inc_not_zero(&tw->tw_refcnt)))
+			if (unlikely(!refcount_inc_not_zero(&tw->tw_refcnt)))
 				continue;
 
 			if (unlikely((tw->tw_family != family) ||
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 86fa458..c5a117c 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -115,7 +115,7 @@ static void inetpeer_gc_worker(struct work_struct *work)
 
 		n = list_entry(p->gc_list.next, struct inet_peer, gc_list);
 
-		if (!atomic_read(&p->refcnt)) {
+		if (refcount_read(&p->refcnt) == 1) {
 			list_del(&p->gc_list);
 			kmem_cache_free(peer_cachep, p);
 		}
@@ -202,10 +202,11 @@ static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
 		int cmp = inetpeer_addr_cmp(daddr, &u->daddr);
 		if (cmp == 0) {
 			/* Before taking a reference, check if this entry was
-			 * deleted (refcnt=-1)
+			 * deleted (refcnt=0)
 			 */
-			if (!atomic_add_unless(&u->refcnt, 1, -1))
+			if (!refcount_inc_not_zero(&u->refcnt)) {
 				u = NULL;
+			}
 			return u;
 		}
 		if (cmp == -1)
@@ -382,11 +383,10 @@ static int inet_peer_gc(struct inet_peer_base *base,
 	while (stackptr > stack) {
 		stackptr--;
 		p = rcu_deref_locked(**stackptr, base);
-		if (atomic_read(&p->refcnt) == 0) {
+		if (refcount_read(&p->refcnt) == 1) {
 			smp_rmb();
 			delta = (__u32)jiffies - p->dtime;
-			if (delta >= ttl &&
-			    atomic_cmpxchg(&p->refcnt, 0, -1) == 0) {
+			if (delta >= ttl && refcount_dec_if_one(&p->refcnt)) {
 				p->gc_next = gchead;
 				gchead = p;
 			}
@@ -432,7 +432,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
 relookup:
 	p = lookup(daddr, stack, base);
 	if (p != peer_avl_empty) {
-		atomic_inc(&p->refcnt);
+		refcount_inc(&p->refcnt);
 		write_sequnlock_bh(&base->lock);
 		return p;
 	}
@@ -444,7 +444,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
 	p = create ? kmem_cache_alloc(peer_cachep, GFP_ATOMIC) : NULL;
 	if (p) {
 		p->daddr = *daddr;
-		atomic_set(&p->refcnt, 1);
+		refcount_set(&p->refcnt, 2);
 		atomic_set(&p->rid, 0);
 		p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
 		p->rate_tokens = 0;
@@ -468,7 +468,7 @@ void inet_putpeer(struct inet_peer *p)
 {
 	p->dtime = (__u32)jiffies;
 	smp_mb__before_atomic();
-	atomic_dec(&p->refcnt);
+	refcount_dec(&p->refcnt);
 }
 EXPORT_SYMBOL_GPL(inet_putpeer);
 
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index bbe7f72..4fed6f6 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -303,7 +303,7 @@ static int ip_frag_reinit(struct ipq *qp)
 	unsigned int sum_truesize = 0;
 
 	if (!mod_timer(&qp->q.timer, jiffies + qp->q.net->timeout)) {
-		atomic_inc(&qp->q.refcnt);
+		refcount_inc(&qp->q.refcnt);
 		return -ETIMEDOUT;
 	}
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index fac275c4..4c611f2 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1030,7 +1030,7 @@ static int __ip_append_data(struct sock *sk,
 						(flags & MSG_DONTWAIT), &err);
 			} else {
 				skb = NULL;
-				if (atomic_read(&sk->sk_wmem_alloc) <=
+				if (refcount_read(&sk->sk_wmem_alloc) <=
 				    2 * sk->sk_sndbuf)
 					skb = sock_wmalloc(sk,
 							   alloclen + hh_len + 15, 1,
@@ -1135,7 +1135,7 @@ static int __ip_append_data(struct sock *sk,
 			skb->len += copy;
 			skb->data_len += copy;
 			skb->truesize += copy;
-			atomic_add(copy, &sk->sk_wmem_alloc);
+			refcount_add(copy, &sk->sk_wmem_alloc);
 		}
 		offset += copy;
 		length -= copy;
@@ -1359,7 +1359,7 @@ ssize_t	ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
 		skb->len += len;
 		skb->data_len += len;
 		skb->truesize += len;
-		atomic_add(len, &sk->sk_wmem_alloc);
+		refcount_add(len, &sk->sk_wmem_alloc);
 		offset += len;
 		size -= len;
 	}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 21db00d..9b8bb40 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -22,6 +22,7 @@
 #include <linux/icmp.h>
 #include <linux/if_arp.h>
 #include <linux/seq_file.h>
+#include <linux/refcount.h>
 #include <linux/netfilter_arp.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
@@ -40,8 +41,8 @@ MODULE_DESCRIPTION("Xtables: CLUSTERIP target");
 
 struct clusterip_config {
 	struct list_head list;			/* list of all configs */
-	atomic_t refcount;			/* reference count */
-	atomic_t entries;			/* number of entries/rules
+	refcount_t refcount;			/* reference count */
+	refcount_t entries;			/* number of entries/rules
 						 * referencing us */
 
 	__be32 clusterip;			/* the IP address */
@@ -77,7 +78,7 @@ struct clusterip_net {
 static inline void
 clusterip_config_get(struct clusterip_config *c)
 {
-	atomic_inc(&c->refcount);
+	refcount_inc(&c->refcount);
 }
 
 
@@ -89,7 +90,7 @@ static void clusterip_config_rcu_free(struct rcu_head *head)
 static inline void
 clusterip_config_put(struct clusterip_config *c)
 {
-	if (atomic_dec_and_test(&c->refcount))
+	if (refcount_dec_and_test(&c->refcount))
 		call_rcu_bh(&c->rcu, clusterip_config_rcu_free);
 }
 
@@ -103,7 +104,7 @@ clusterip_config_entry_put(struct clusterip_config *c)
 	struct clusterip_net *cn = net_generic(net, clusterip_net_id);
 
 	local_bh_disable();
-	if (atomic_dec_and_lock(&c->entries, &cn->lock)) {
+	if (refcount_dec_and_lock(&c->entries, &cn->lock)) {
 		list_del_rcu(&c->list);
 		spin_unlock(&cn->lock);
 		local_bh_enable();
@@ -144,10 +145,10 @@ clusterip_config_find_get(struct net *net, __be32 clusterip, int entry)
 	rcu_read_lock_bh();
 	c = __clusterip_config_find(net, clusterip);
 	if (c) {
-		if (unlikely(!atomic_inc_not_zero(&c->refcount)))
+		if (unlikely(!refcount_inc_not_zero(&c->refcount)))
 			c = NULL;
 		else if (entry)
-			atomic_inc(&c->entries);
+			refcount_inc(&c->entries);
 	}
 	rcu_read_unlock_bh();
 
@@ -182,8 +183,8 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
 	clusterip_config_init_nodelist(c, i);
 	c->hash_mode = i->hash_mode;
 	c->hash_initval = i->hash_initval;
-	atomic_set(&c->refcount, 1);
-	atomic_set(&c->entries, 1);
+	refcount_set(&c->refcount, 1);
+	refcount_set(&c->entries, 1);
 
 #ifdef CONFIG_PROC_FS
 	{
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 86cca61..4ecef05 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -289,7 +289,7 @@ void ping_close(struct sock *sk, long timeout)
 {
 	pr_debug("ping_close(sk=%p,sk->num=%u)\n",
 		 inet_sk(sk), inet_sk(sk)->inet_num);
-	pr_debug("isk->refcnt = %d\n", sk->sk_refcnt.counter);
+	pr_debug("isk->refcnt = %d\n", refcount_read(&sk->sk_refcnt));
 
 	sk_common_release(sk);
 }
@@ -1123,7 +1123,7 @@ static void ping_v4_format_sock(struct sock *sp, struct seq_file *f,
 		0, 0L, 0,
 		from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
 		0, sock_i_ino(sp),
-		atomic_read(&sp->sk_refcnt), sp,
+		refcount_read(&sp->sk_refcnt), sp,
 		atomic_read(&sp->sk_drops));
 }
 
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 4e49e5c..c772a96 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -1054,7 +1054,7 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
 		0, 0L, 0,
 		from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
 		0, sock_i_ino(sp),
-		atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
+		refcount_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
 }
 
 static int raw_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 3e88467..1f7b47e 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -223,7 +223,7 @@ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
 	child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst,
 						 NULL, &own_req);
 	if (child) {
-		atomic_set(&req->rsk_refcnt, 1);
+		refcount_set(&req->rsk_refcnt, 1);
 		sock_rps_save_rxhash(child, skb);
 		inet_csk_reqsk_queue_add(sk, req, child);
 	} else {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 4a04496..bb42a42 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -642,7 +642,7 @@ static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
 	return skb->len < size_goal &&
 	       sysctl_tcp_autocorking &&
 	       skb != tcp_write_queue_head(sk) &&
-	       atomic_read(&sk->sk_wmem_alloc) > skb->truesize;
+	       refcount_read(&sk->sk_wmem_alloc) > skb->truesize;
 }
 
 static void tcp_push(struct sock *sk, int flags, int mss_now,
@@ -670,7 +670,7 @@ static void tcp_push(struct sock *sk, int flags, int mss_now,
 		/* It is possible TX completion already happened
 		 * before we set TSQ_THROTTLED.
 		 */
-		if (atomic_read(&sk->sk_wmem_alloc) > skb->truesize)
+		if (refcount_read(&sk->sk_wmem_alloc) > skb->truesize)
 			return;
 	}
 
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
index 4e777a3..ca4a679 100644
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -213,7 +213,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
 	inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS,
 				  TCP_TIMEOUT_INIT, TCP_RTO_MAX);
 
-	atomic_set(&req->rsk_refcnt, 2);
+	refcount_set(&req->rsk_refcnt, 2);
 
 	/* Now finish processing the fastopen child socket. */
 	inet_csk(child)->icsk_af_ops->rebuild_header(child);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index fe9da4f..adcdcef 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2263,7 +2263,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
 		from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)),
 		icsk->icsk_probes_out,
 		sock_i_ino(sk),
-		atomic_read(&sk->sk_refcnt), sk,
+		refcount_read(&sk->sk_refcnt), sk,
 		jiffies_to_clock_t(icsk->icsk_rto),
 		jiffies_to_clock_t(icsk->icsk_ack.ato),
 		(icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
@@ -2289,7 +2289,7 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw,
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
 		i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
 		3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
-		atomic_read(&tw->tw_refcnt), tw);
+		refcount_read(&tw->tw_refcnt), tw);
 }
 
 #define TMPSZ 150
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index bc68da3..11f69bb 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -152,7 +152,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 		swap(gso_skb->sk, skb->sk);
 		swap(gso_skb->destructor, skb->destructor);
 		sum_truesize += skb->truesize;
-		atomic_add(sum_truesize - gso_skb->truesize,
+		refcount_add(sum_truesize - gso_skb->truesize,
 			   &skb->sk->sk_wmem_alloc);
 	}
 
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 1d5331a..91cdf1c 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -862,12 +862,11 @@ void tcp_wfree(struct sk_buff *skb)
 	struct sock *sk = skb->sk;
 	struct tcp_sock *tp = tcp_sk(sk);
 	unsigned long flags, nval, oval;
-	int wmem;
 
 	/* Keep one reference on sk_wmem_alloc.
 	 * Will be released by sk_free() from here or tcp_tasklet_func()
 	 */
-	wmem = atomic_sub_return(skb->truesize - 1, &sk->sk_wmem_alloc);
+	WARN_ON(refcount_sub_and_test(skb->truesize - 1, &sk->sk_wmem_alloc));
 
 	/* If this softirq is serviced by ksoftirqd, we are likely under stress.
 	 * Wait until our queues (qdisc + devices) are drained.
@@ -876,7 +875,7 @@ void tcp_wfree(struct sk_buff *skb)
 	 * - chance for incoming ACK (processed by another cpu maybe)
 	 *   to migrate this flow (skb->ooo_okay will be eventually set)
 	 */
-	if (wmem >= SKB_TRUESIZE(1) && this_cpu_ksoftirqd() == current)
+	if (refcount_read(&sk->sk_wmem_alloc) >= SKB_TRUESIZE(1) && this_cpu_ksoftirqd() == current)
 		goto out;
 
 	for (oval = READ_ONCE(sk->sk_tsq_flags);; oval = nval) {
@@ -973,7 +972,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
 	skb->sk = sk;
 	skb->destructor = skb_is_tcp_pure_ack(skb) ? __sock_wfree : tcp_wfree;
 	skb_set_hash_from_sk(skb, sk);
-	atomic_add(skb->truesize, &sk->sk_wmem_alloc);
+	refcount_add(skb->truesize, &sk->sk_wmem_alloc);
 
 	/* Build TCP header and checksum it. */
 	th = (struct tcphdr *)skb->data;
@@ -2091,7 +2090,7 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
 	limit = min_t(u32, limit, sysctl_tcp_limit_output_bytes);
 	limit <<= factor;
 
-	if (atomic_read(&sk->sk_wmem_alloc) > limit) {
+	if (refcount_read(&sk->sk_wmem_alloc) > limit) {
 		/* Always send the 1st or 2nd skb in write queue.
 		 * No need to wait for TX completion to call us back,
 		 * after softirq/tasklet schedule.
@@ -2107,7 +2106,7 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
 		 * test again the condition.
 		 */
 		smp_mb__after_atomic();
-		if (atomic_read(&sk->sk_wmem_alloc) > limit)
+		if (refcount_read(&sk->sk_wmem_alloc) > limit)
 			return true;
 	}
 	return false;
@@ -2724,7 +2723,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
 	/* Do not sent more than we queued. 1/4 is reserved for possible
 	 * copying overhead: fragmentation, tunneling, mangling etc.
 	 */
-	if (atomic_read(&sk->sk_wmem_alloc) >
+	if (refcount_read(&sk->sk_wmem_alloc) >
 	    min_t(u32, sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2),
 		  sk->sk_sndbuf))
 		return -EAGAIN;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1307a7c..9cf2697 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -589,7 +589,7 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
 
 	sk = __udp4_lib_lookup(net, saddr, sport, daddr, dport,
 			       dif, &udp_table, NULL);
-	if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+	if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
 		sk = NULL;
 	return sk;
 }
@@ -2093,7 +2093,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
 					     uh->source, iph->saddr, dif);
 	}
 
-	if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2))
+	if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
 		return;
 
 	skb->sk = sk;
@@ -2541,7 +2541,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
 		0, 0L, 0,
 		from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
 		0, sock_i_ino(sp),
-		atomic_read(&sp->sk_refcnt), sp,
+		refcount_read(&sp->sk_refcnt), sp,
 		atomic_read(&sp->sk_drops));
 }
 
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 9a89c10..4515836 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -55,7 +55,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 				req->id.idiag_dport,
 				req->id.idiag_if, tbl, NULL);
 #endif
-	if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+	if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
 		sk = NULL;
 	rcu_read_unlock();
 	err = -ENOENT;
@@ -206,7 +206,7 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
 		return -EINVAL;
 	}
 
-	if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+	if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
 		sk = NULL;
 
 	rcu_read_unlock();
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c1e124b..9db691e 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -419,7 +419,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 	}
 
 	/* One reference from device. */
-	in6_dev_hold(ndev);
+	refcount_set(&ndev->refcnt, 1);
 
 	if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
 		ndev->cnf.accept_dad = -1;
@@ -1009,7 +1009,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
 	ifa->idev = idev;
 	in6_dev_hold(idev);
 	/* For caller */
-	in6_ifa_hold(ifa);
+	refcount_set(&ifa->refcnt, 1);
 
 	/* Add to big hash table */
 	hash = inet6_addr_hash(addr);
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index a8f6986..9340804 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -18,6 +18,7 @@
 #include <linux/if_addrlabel.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
+#include <linux/refcount.h>
 
 #if 0
 #define ADDRLABEL(x...) printk(x)
@@ -36,7 +37,7 @@ struct ip6addrlbl_entry {
 	int addrtype;
 	u32 label;
 	struct hlist_node list;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	struct rcu_head rcu;
 };
 
@@ -137,12 +138,12 @@ static void ip6addrlbl_free_rcu(struct rcu_head *h)
 
 static bool ip6addrlbl_hold(struct ip6addrlbl_entry *p)
 {
-	return atomic_inc_not_zero(&p->refcnt);
+	return refcount_inc_not_zero(&p->refcnt);
 }
 
 static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p)
 {
-	if (atomic_dec_and_test(&p->refcnt))
+	if (refcount_dec_and_test(&p->refcnt))
 		call_rcu(&p->rcu, ip6addrlbl_free_rcu);
 }
 
@@ -236,7 +237,7 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net,
 	newp->label = label;
 	INIT_HLIST_NODE(&newp->list);
 	write_pnet(&newp->lbl_net, net);
-	atomic_set(&newp->refcnt, 1);
+	refcount_set(&newp->refcnt, 1);
 	return newp;
 }
 
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 514ac25..0bbab8a 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -203,12 +203,12 @@ void ipv6_sock_ac_close(struct sock *sk)
 
 static void aca_get(struct ifacaddr6 *aca)
 {
-	atomic_inc(&aca->aca_refcnt);
+	refcount_inc(&aca->aca_refcnt);
 }
 
 static void aca_put(struct ifacaddr6 *ac)
 {
-	if (atomic_dec_and_test(&ac->aca_refcnt)) {
+	if (refcount_dec_and_test(&ac->aca_refcnt)) {
 		in6_dev_put(ac->aca_idev);
 		dst_release(&ac->aca_rt->dst);
 		kfree(ac);
@@ -232,7 +232,7 @@ static struct ifacaddr6 *aca_alloc(struct rt6_info *rt,
 	aca->aca_users = 1;
 	/* aca_tstamp should be updated upon changes */
 	aca->aca_cstamp = aca->aca_tstamp = jiffies;
-	atomic_set(&aca->aca_refcnt, 1);
+	refcount_set(&aca->aca_refcnt, 1);
 
 	return aca;
 }
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index 37ac9de..a475564 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -227,7 +227,7 @@ static int calipso_cache_check(const unsigned char *key,
 		    entry->key_len == key_len &&
 		    memcmp(entry->key, key, key_len) == 0) {
 			entry->activity += 1;
-			atomic_inc(&entry->lsm_data->refcount);
+			refcount_inc(&entry->lsm_data->refcount);
 			secattr->cache = entry->lsm_data;
 			secattr->flags |= NETLBL_SECATTR_CACHE;
 			secattr->type = NETLBL_NLTYPE_CALIPSO;
@@ -296,7 +296,7 @@ static int calipso_cache_add(const unsigned char *calipso_ptr,
 	}
 	entry->key_len = calipso_ptr_len;
 	entry->hash = calipso_map_cache_hash(calipso_ptr, calipso_ptr_len);
-	atomic_inc(&secattr->cache->refcount);
+	refcount_inc(&secattr->cache->refcount);
 	entry->lsm_data = secattr->cache;
 
 	bkt = entry->hash & (CALIPSO_CACHE_BUCKETS - 1);
@@ -338,7 +338,7 @@ static struct calipso_doi *calipso_doi_search(u32 doi)
 	struct calipso_doi *iter;
 
 	list_for_each_entry_rcu(iter, &calipso_doi_list, list)
-		if (iter->doi == doi && atomic_read(&iter->refcount))
+		if (iter->doi == doi && refcount_read(&iter->refcount))
 			return iter;
 	return NULL;
 }
@@ -370,7 +370,7 @@ static int calipso_doi_add(struct calipso_doi *doi_def,
 	if (doi_def->doi == CALIPSO_DOI_UNKNOWN)
 		goto doi_add_return;
 
-	atomic_set(&doi_def->refcount, 1);
+	refcount_set(&doi_def->refcount, 1);
 
 	spin_lock(&calipso_doi_list_lock);
 	if (calipso_doi_search(doi_def->doi)) {
@@ -458,7 +458,7 @@ static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
 		ret_val = -ENOENT;
 		goto doi_remove_return;
 	}
-	if (!atomic_dec_and_test(&doi_def->refcount)) {
+	if (!refcount_dec_and_test(&doi_def->refcount)) {
 		spin_unlock(&calipso_doi_list_lock);
 		ret_val = -EBUSY;
 		goto doi_remove_return;
@@ -499,7 +499,7 @@ static struct calipso_doi *calipso_doi_getdef(u32 doi)
 	doi_def = calipso_doi_search(doi);
 	if (!doi_def)
 		goto doi_getdef_return;
-	if (!atomic_inc_not_zero(&doi_def->refcount))
+	if (!refcount_inc_not_zero(&doi_def->refcount))
 		doi_def = NULL;
 
 doi_getdef_return:
@@ -520,7 +520,7 @@ static void calipso_doi_putdef(struct calipso_doi *doi_def)
 	if (!doi_def)
 		return;
 
-	if (!atomic_dec_and_test(&doi_def->refcount))
+	if (!refcount_dec_and_test(&doi_def->refcount))
 		return;
 	spin_lock(&calipso_doi_list_lock);
 	list_del_rcu(&doi_def->list);
@@ -553,7 +553,7 @@ static int calipso_doi_walk(u32 *skip_cnt,
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(iter_doi, &calipso_doi_list, list)
-		if (atomic_read(&iter_doi->refcount) > 0) {
+		if (refcount_read(&iter_doi->refcount) > 0) {
 			if (doi_cnt++ < *skip_cnt)
 				continue;
 			ret_val = callback(iter_doi, cb_arg);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a3eaafd..0470d88 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -1039,6 +1039,6 @@ void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
 		   from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
 		   0,
 		   sock_i_ino(sp),
-		   atomic_read(&sp->sk_refcnt), sp,
+		   refcount_read(&sp->sk_refcnt), sp,
 		   atomic_read(&sp->sk_drops));
 }
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index e419850..51e04e6 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -995,7 +995,7 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
 			*((char **)&opt2->dst1opt) += dif;
 		if (opt2->srcrt)
 			*((char **)&opt2->srcrt) += dif;
-		atomic_set(&opt2->refcnt, 1);
+		refcount_set(&opt2->refcnt, 1);
 	}
 	return opt2;
 }
@@ -1080,7 +1080,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
 		return ERR_PTR(-ENOBUFS);
 
 	memset(opt2, 0, tot_len);
-	atomic_set(&opt2->refcnt, 1);
+	refcount_set(&opt2->refcnt, 1);
 	opt2->tot_len = tot_len;
 	p = (char *)(opt2 + 1);
 
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 02761c9..e707108 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -75,7 +75,7 @@ struct sock *__inet6_lookup_established(struct net *net,
 			continue;
 		if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif))
 			continue;
-		if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
+		if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
 			goto out;
 
 		if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports, dif))) {
@@ -172,7 +172,7 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
 
 	sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
 			    ntohs(dport), dif, &refcounted);
-	if (sk && !refcounted && !atomic_inc_not_zero(&sk->sk_refcnt))
+	if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
 		sk = NULL;
 	return sk;
 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 70d0de40..cf36fc2 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1455,7 +1455,7 @@ static int __ip6_append_data(struct sock *sk,
 						(flags & MSG_DONTWAIT), &err);
 			} else {
 				skb = NULL;
-				if (atomic_read(&sk->sk_wmem_alloc) <=
+				if (refcount_read(&sk->sk_wmem_alloc) <=
 				    2 * sk->sk_sndbuf)
 					skb = sock_wmalloc(sk,
 							   alloclen + hh_len, 1,
@@ -1565,7 +1565,7 @@ static int __ip6_append_data(struct sock *sk,
 			skb->len += copy;
 			skb->data_len += copy;
 			skb->truesize += copy;
-			atomic_add(copy, &sk->sk_wmem_alloc);
+			refcount_add(copy, &sk->sk_wmem_alloc);
 		}
 		offset += copy;
 		length -= copy;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index ee97c44..9c39746 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -505,7 +505,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
 			break;
 
 		memset(opt, 0, sizeof(*opt));
-		atomic_set(&opt->refcnt, 1);
+		refcount_set(&opt->refcnt, 1);
 		opt->tot_len = sizeof(*opt) + optlen;
 		retv = -EFAULT;
 		if (copy_from_user(opt+1, optval, optlen))
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 14a3903..4ae7a0b 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -701,7 +701,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
 
 	spin_lock_bh(&mc->mca_lock);
 	if (del_timer(&mc->mca_timer))
-		atomic_dec(&mc->mca_refcnt);
+		refcount_dec(&mc->mca_refcnt);
 done:
 	ip6_mc_clear_src(mc);
 	spin_unlock_bh(&mc->mca_lock);
@@ -813,12 +813,12 @@ static void mld_clear_delrec(struct inet6_dev *idev)
 
 static void mca_get(struct ifmcaddr6 *mc)
 {
-	atomic_inc(&mc->mca_refcnt);
+	refcount_inc(&mc->mca_refcnt);
 }
 
 static void ma_put(struct ifmcaddr6 *mc)
 {
-	if (atomic_dec_and_test(&mc->mca_refcnt)) {
+	if (refcount_dec_and_test(&mc->mca_refcnt)) {
 		in6_dev_put(mc->idev);
 		kfree(mc);
 	}
@@ -840,7 +840,7 @@ static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
 	mc->mca_users = 1;
 	/* mca_stamp should be updated upon changes */
 	mc->mca_cstamp = mc->mca_tstamp = jiffies;
-	atomic_set(&mc->mca_refcnt, 1);
+	refcount_set(&mc->mca_refcnt, 1);
 	spin_lock_init(&mc->mca_lock);
 
 	/* initial mode is (EX, empty) */
@@ -1058,7 +1058,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
 		return;
 
 	if (del_timer(&ma->mca_timer)) {
-		atomic_dec(&ma->mca_refcnt);
+		refcount_dec(&ma->mca_refcnt);
 		delay = ma->mca_timer.expires - jiffies;
 	}
 
@@ -1067,7 +1067,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
 
 	ma->mca_timer.expires = jiffies + delay;
 	if (!mod_timer(&ma->mca_timer, jiffies + delay))
-		atomic_inc(&ma->mca_refcnt);
+		refcount_inc(&ma->mca_refcnt);
 	ma->mca_flags |= MAF_TIMER_RUNNING;
 }
 
@@ -1462,7 +1462,7 @@ int igmp6_event_report(struct sk_buff *skb)
 		if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) {
 			spin_lock(&ma->mca_lock);
 			if (del_timer(&ma->mca_timer))
-				atomic_dec(&ma->mca_refcnt);
+				refcount_dec(&ma->mca_refcnt);
 			ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING);
 			spin_unlock(&ma->mca_lock);
 			break;
@@ -2385,12 +2385,12 @@ static void igmp6_join_group(struct ifmcaddr6 *ma)
 
 	spin_lock_bh(&ma->mca_lock);
 	if (del_timer(&ma->mca_timer)) {
-		atomic_dec(&ma->mca_refcnt);
+		refcount_dec(&ma->mca_refcnt);
 		delay = ma->mca_timer.expires - jiffies;
 	}
 
 	if (!mod_timer(&ma->mca_timer, jiffies + delay))
-		atomic_inc(&ma->mca_refcnt);
+		refcount_inc(&ma->mca_refcnt);
 	ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
 	spin_unlock_bh(&ma->mca_lock);
 }
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index a4d4976..8681837 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -188,7 +188,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 	if (ipv6_opt_accepted(sk, skb, &TCP_SKB_CB(skb)->header.h6) ||
 	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
 	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
-		atomic_inc(&skb->users);
+		refcount_inc(&skb->users);
 		ireq->pktopts = skb;
 	}
 
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 73bc8fc6..c88b5c9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -704,7 +704,7 @@ static void tcp_v6_init_req(struct request_sock *req,
 	     np->rxopt.bits.rxinfo ||
 	     np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim ||
 	     np->rxopt.bits.rxohlim || np->repflow)) {
-		atomic_inc(&skb->users);
+		refcount_inc(&skb->users);
 		ireq->pktopts = skb;
 	}
 }
@@ -1785,7 +1785,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
 		   from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
 		   icsk->icsk_probes_out,
 		   sock_i_ino(sp),
-		   atomic_read(&sp->sk_refcnt), sp,
+		   refcount_read(&sp->sk_refcnt), sp,
 		   jiffies_to_clock_t(icsk->icsk_rto),
 		   jiffies_to_clock_t(icsk->icsk_ack.ato),
 		   (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
@@ -1818,7 +1818,7 @@ static void get_timewait6_sock(struct seq_file *seq,
 		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
 		   tw->tw_substate, 0, 0,
 		   3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
-		   atomic_read(&tw->tw_refcnt), tw);
+		   refcount_read(&tw->tw_refcnt), tw);
 }
 
 static int tcp6_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 4d5c4ee..d2f5307 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -311,7 +311,7 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
 
 	sk =  __udp6_lib_lookup(net, saddr, sport, daddr, dport,
 				dif, &udp_table, NULL);
-	if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+	if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
 		sk = NULL;
 	return sk;
 }
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index b578956..c8594de 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -70,7 +70,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
 	int i = 0;
 
 	/* Allocate new secpath or COW existing one. */
-	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
+	if (!skb->sp || refcount_read(&skb->sp->refcnt) != 1) {
 		struct sec_path *sp;
 
 		sp = secpath_dup(skb->sp);
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index d7b731a..4e438bc 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -59,7 +59,7 @@ struct xfrm6_tunnel_spi {
 	struct hlist_node	list_byspi;
 	xfrm_address_t		addr;
 	u32			spi;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	struct rcu_head		rcu_head;
 };
 
@@ -160,7 +160,7 @@ static u32 __xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr)
 
 	memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr));
 	x6spi->spi = spi;
-	atomic_set(&x6spi->refcnt, 1);
+	refcount_set(&x6spi->refcnt, 1);
 
 	hlist_add_head_rcu(&x6spi->list_byspi, &xfrm6_tn->spi_byspi[index]);
 
@@ -178,7 +178,7 @@ __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr)
 	spin_lock_bh(&xfrm6_tunnel_spi_lock);
 	x6spi = __xfrm6_tunnel_spi_lookup(net, saddr);
 	if (x6spi) {
-		atomic_inc(&x6spi->refcnt);
+		refcount_inc(&x6spi->refcnt);
 		spi = x6spi->spi;
 	} else
 		spi = __xfrm6_tunnel_alloc_spi(net, saddr);
@@ -207,7 +207,7 @@ static void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr)
 				  list_byaddr)
 	{
 		if (xfrm6_addr_equal(&x6spi->addr, saddr)) {
-			if (atomic_dec_and_test(&x6spi->refcnt)) {
+			if (refcount_dec_and_test(&x6spi->refcnt)) {
 				hlist_del_rcu(&x6spi->list_byaddr);
 				hlist_del_rcu(&x6spi->list_byspi);
 				call_rcu(&x6spi->rcu_head, x6spi_destroy_rcu);
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 8a9219f..0675b4a 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -308,7 +308,7 @@ void ipxitf_down(struct ipx_interface *intrfc)
 
 static void __ipxitf_put(struct ipx_interface *intrfc)
 {
-	if (atomic_dec_and_test(&intrfc->refcnt))
+	if (refcount_dec_and_test(&intrfc->refcnt))
 		__ipxitf_down(intrfc);
 }
 
@@ -876,7 +876,7 @@ static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum,
 		intrfc->if_ipx_offset 	= ipx_offset;
 		intrfc->if_sknum 	= IPX_MIN_EPHEMERAL_SOCKET;
 		INIT_HLIST_HEAD(&intrfc->if_sklist);
-		atomic_set(&intrfc->refcnt, 1);
+		refcount_set(&intrfc->refcnt, 1);
 		spin_lock_init(&intrfc->if_sklist_lock);
 	}
 
@@ -1105,7 +1105,7 @@ static struct ipx_interface *ipxitf_auto_create(struct net_device *dev,
 		memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
 			dev->dev_addr, dev->addr_len);
 		spin_lock_init(&intrfc->if_sklist_lock);
-		atomic_set(&intrfc->refcnt, 1);
+		refcount_set(&intrfc->refcnt, 1);
 		ipxitf_insert(intrfc);
 		dev_hold(dev);
 	}
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index c1d247e..7d75e4c 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -53,7 +53,7 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v)
 	seq_printf(seq, "%-11s", ipx_device_name(i));
 	seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type));
 #ifdef IPX_REFCNT_DEBUG
-	seq_printf(seq, "%6d", atomic_read(&i->refcnt));
+	seq_printf(seq, "%6d", refcount_read(&i->refcnt));
 #endif
 	seq_puts(seq, "\n");
 out:
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index 3e2a32a..b5d9144 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -59,7 +59,7 @@ int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
 		if (!rt)
 			goto out;
 
-		atomic_set(&rt->refcnt, 1);
+		refcount_set(&rt->refcnt, 1);
 		ipxrtr_hold(rt);
 		write_lock_bh(&ipx_routes_lock);
 		list_add(&rt->node, &ipx_routes);
diff --git a/net/kcm/kcmproc.c b/net/kcm/kcmproc.c
index bf75c92..c343ac6 100644
--- a/net/kcm/kcmproc.c
+++ b/net/kcm/kcmproc.c
@@ -162,7 +162,7 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
 		   psock->sk->sk_receive_queue.qlen,
 		   atomic_read(&psock->sk->sk_rmem_alloc),
 		   psock->sk->sk_write_queue.qlen,
-		   atomic_read(&psock->sk->sk_wmem_alloc));
+		   refcount_read(&psock->sk->sk_wmem_alloc));
 
 	if (psock->done)
 		seq_puts(seq, "Done ");
diff --git a/net/key/af_key.c b/net/key/af_key.c
index c6252ed..b7b0d36 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -104,7 +104,7 @@ static void pfkey_sock_destruct(struct sock *sk)
 	}
 
 	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
-	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
 
 	atomic_dec(&net_pfkey->socks_nr);
 }
@@ -194,11 +194,11 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
 
 	sock_hold(sk);
 	if (*skb2 == NULL) {
-		if (atomic_read(&skb->users) != 1) {
+		if (refcount_read(&skb->users) != 1) {
 			*skb2 = skb_clone(skb, allocation);
 		} else {
 			*skb2 = skb;
-			atomic_inc(&skb->users);
+			refcount_inc(&skb->users);
 		}
 	}
 	if (*skb2 != NULL) {
@@ -2152,7 +2152,7 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy *
 	}
 
 	hdr->sadb_msg_len = size / sizeof(uint64_t);
-	hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
+	hdr->sadb_msg_reserved = refcount_read(&xp->refcnt);
 
 	return 0;
 }
@@ -3711,7 +3711,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
 	else
 		seq_printf(f, "%pK %-6d %-6u %-6u %-6u %-6lu\n",
 			       s,
-			       atomic_read(&s->sk_refcnt),
+			       refcount_read(&s->sk_refcnt),
 			       sk_rmem_alloc_get(s),
 			       sk_wmem_alloc_get(s),
 			       from_kuid_munged(seq_user_ns(f), sock_i_uid(s)),
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 85948c6..e273741 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -132,12 +132,12 @@ static inline struct l2tp_net *l2tp_pernet(struct net *net)
  */
 static inline void l2tp_tunnel_inc_refcount_1(struct l2tp_tunnel *tunnel)
 {
-	atomic_inc(&tunnel->ref_count);
+	refcount_inc(&tunnel->ref_count);
 }
 
 static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel)
 {
-	if (atomic_dec_and_test(&tunnel->ref_count))
+	if (refcount_dec_and_test(&tunnel->ref_count))
 		l2tp_tunnel_free(tunnel);
 }
 #ifdef L2TP_REFCNT_DEBUG
@@ -145,14 +145,14 @@ static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel)
 do {									\
 	pr_debug("l2tp_tunnel_inc_refcount: %s:%d %s: cnt=%d\n",	\
 		 __func__, __LINE__, (_t)->name,			\
-		 atomic_read(&_t->ref_count));				\
+		 refcount_read(&_t->ref_count));			\
 	l2tp_tunnel_inc_refcount_1(_t);					\
 } while (0)
 #define l2tp_tunnel_dec_refcount(_t)					\
 do {									\
 	pr_debug("l2tp_tunnel_dec_refcount: %s:%d %s: cnt=%d\n",	\
 		 __func__, __LINE__, (_t)->name,			\
-		 atomic_read(&_t->ref_count));				\
+		 refcount_read(&_t->ref_count));			\
 	l2tp_tunnel_dec_refcount_1(_t);					\
 } while (0)
 #else
@@ -1303,7 +1303,7 @@ static void l2tp_udp_encap_destroy(struct sock *sk)
  */
 static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
 {
-	BUG_ON(atomic_read(&tunnel->ref_count) != 0);
+	BUG_ON(refcount_read(&tunnel->ref_count) != 0);
 	BUG_ON(tunnel->sock != NULL);
 	l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: free...\n", tunnel->name);
 	kfree_rcu(tunnel, rcu);
@@ -1654,7 +1654,7 @@ void l2tp_session_free(struct l2tp_session *session)
 {
 	struct l2tp_tunnel *tunnel = session->tunnel;
 
-	BUG_ON(atomic_read(&session->ref_count) != 0);
+	BUG_ON(refcount_read(&session->ref_count) != 0);
 
 	if (tunnel) {
 		BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 8f560f7..f170e97 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -7,6 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/refcount.h>
 
 #ifndef _L2TP_CORE_H_
 #define _L2TP_CORE_H_
@@ -98,7 +99,7 @@ struct l2tp_session {
 	int			nr_oos_count;	/* For OOS recovery */
 	int			nr_oos_count_max;
 	struct hlist_node	hlist;		/* Hash list node */
-	atomic_t		ref_count;
+	refcount_t		ref_count;
 
 	char			name[32];	/* for logging */
 	char			ifname[IFNAMSIZ];
@@ -177,7 +178,7 @@ struct l2tp_tunnel {
 	struct list_head	list;		/* Keep a list of all tunnels */
 	struct net		*l2tp_net;	/* the net we belong to */
 
-	atomic_t		ref_count;
+	refcount_t		ref_count;
 #ifdef CONFIG_DEBUG_FS
 	void (*show)(struct seq_file *m, void *arg);
 #endif
@@ -269,12 +270,12 @@ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
  */
 static inline void l2tp_session_inc_refcount_1(struct l2tp_session *session)
 {
-	atomic_inc(&session->ref_count);
+	refcount_inc(&session->ref_count);
 }
 
 static inline void l2tp_session_dec_refcount_1(struct l2tp_session *session)
 {
-	if (atomic_dec_and_test(&session->ref_count))
+	if (refcount_dec_and_test(&session->ref_count))
 		l2tp_session_free(session);
 }
 
@@ -283,14 +284,14 @@ static inline void l2tp_session_dec_refcount_1(struct l2tp_session *session)
 do {									\
 	pr_debug("l2tp_session_inc_refcount: %s:%d %s: cnt=%d\n",	\
 		 __func__, __LINE__, (_s)->name,			\
-		 atomic_read(&_s->ref_count));				\
+		 refcount_read(&_s->ref_count));			\
 	l2tp_session_inc_refcount_1(_s);				\
 } while (0)
 #define l2tp_session_dec_refcount(_s)					\
 do {									\
 	pr_debug("l2tp_session_dec_refcount: %s:%d %s: cnt=%d\n",	\
 		 __func__, __LINE__, (_s)->name,			\
-		 atomic_read(&_s->ref_count));				\
+		 refcount_read(&_s->ref_count));			\
 	l2tp_session_dec_refcount_1(_s);				\
 } while (0)
 #else
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index 2d6760a..812ae61 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -144,8 +144,8 @@ static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)
 		   tunnel->encap == L2TP_ENCAPTYPE_IP ? "IP" :
 		   "");
 	seq_printf(m, " %d sessions, refcnt %d/%d\n", session_count,
-		   tunnel->sock ? atomic_read(&tunnel->sock->sk_refcnt) : 0,
-		   atomic_read(&tunnel->ref_count));
+		   tunnel->sock ? refcount_read(&tunnel->sock->sk_refcnt) : 0,
+		   refcount_read(&tunnel->ref_count));
 
 	seq_printf(m, " %08x rx %ld/%ld/%ld rx %ld/%ld/%ld\n",
 		   tunnel->debug,
@@ -171,7 +171,7 @@ static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
 		   "");
 	if (session->send_seq || session->recv_seq)
 		seq_printf(m, "   nr %hu, ns %hu\n", session->nr, session->ns);
-	seq_printf(m, "   refcnt %d\n", atomic_read(&session->ref_count));
+	seq_printf(m, "   refcnt %d\n", refcount_read(&session->ref_count));
 	seq_printf(m, "   config %d/%d/%c/%c/%s/%s %08x %u\n",
 		   session->mtu, session->mru,
 		   session->recv_seq ? 'R' : '-',
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 36cc56f..eb1a85a 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -1607,7 +1607,7 @@ static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
 	seq_printf(m, "\nTUNNEL '%s', %c %d\n",
 		   tunnel->name,
 		   (tunnel == tunnel->sock->sk_user_data) ? 'Y' : 'N',
-		   atomic_read(&tunnel->ref_count) - 1);
+		   refcount_read(&tunnel->ref_count) - 1);
 	seq_printf(m, " %08x %ld/%ld/%ld %ld/%ld/%ld\n",
 		   tunnel->debug,
 		   atomic_long_read(&tunnel->stats.tx_packets),
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index b50b64a..e15314e 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -54,12 +54,12 @@ static void lapb_free_cb(struct lapb_cb *lapb)
 
 static __inline__ void lapb_hold(struct lapb_cb *lapb)
 {
-	atomic_inc(&lapb->refcnt);
+	refcount_inc(&lapb->refcnt);
 }
 
 static __inline__ void lapb_put(struct lapb_cb *lapb)
 {
-	if (atomic_dec_and_test(&lapb->refcnt))
+	if (refcount_dec_and_test(&lapb->refcnt))
 		lapb_free_cb(lapb);
 }
 
@@ -136,7 +136,7 @@ static struct lapb_cb *lapb_create_cb(void)
 	lapb->mode    = LAPB_DEFAULT_MODE;
 	lapb->window  = LAPB_DEFAULT_WINDOW;
 	lapb->state   = LAPB_STATE_0;
-	atomic_set(&lapb->refcnt, 1);
+	refcount_set(&lapb->refcnt, 1);
 out:
 	return lapb;
 }
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 3e821da..9227bdf 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -507,7 +507,7 @@ static struct sock *__llc_lookup_established(struct llc_sap *sap,
 	sk_nulls_for_each_rcu(rc, node, laddr_hb) {
 		if (llc_estab_match(sap, daddr, laddr, rc)) {
 			/* Extra checks required by SLAB_DESTROY_BY_RCU */
-			if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
+			if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
 				goto again;
 			if (unlikely(llc_sk(rc)->sap != sap ||
 				     !llc_estab_match(sap, daddr, laddr, rc))) {
@@ -566,7 +566,7 @@ static struct sock *__llc_lookup_listener(struct llc_sap *sap,
 	sk_nulls_for_each_rcu(rc, node, laddr_hb) {
 		if (llc_listener_match(sap, laddr, rc)) {
 			/* Extra checks required by SLAB_DESTROY_BY_RCU */
-			if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
+			if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
 				goto again;
 			if (unlikely(llc_sk(rc)->sap != sap ||
 				     !llc_listener_match(sap, laddr, rc))) {
@@ -970,9 +970,9 @@ void llc_sk_free(struct sock *sk)
 	skb_queue_purge(&sk->sk_write_queue);
 	skb_queue_purge(&llc->pdu_unack_q);
 #ifdef LLC_REFCNT_DEBUG
-	if (atomic_read(&sk->sk_refcnt) != 1) {
+	if (refcount_read(&sk->sk_refcnt) != 1) {
 		printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
-			sk, __func__, atomic_read(&sk->sk_refcnt));
+			sk, __func__, refcount_read(&sk->sk_refcnt));
 		printk(KERN_DEBUG "%d LLC sockets are still alive\n",
 			atomic_read(&llc_sock_nr));
 	} else {
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
index 842851c..8904126 100644
--- a/net/llc/llc_core.c
+++ b/net/llc/llc_core.c
@@ -41,7 +41,7 @@ static struct llc_sap *llc_sap_alloc(void)
 		spin_lock_init(&sap->sk_lock);
 		for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++)
 			INIT_HLIST_NULLS_HEAD(&sap->sk_laddr_hash[i], i);
-		atomic_set(&sap->refcnt, 1);
+		refcount_set(&sap->refcnt, 1);
 	}
 	return sap;
 }
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index d0e1e80..0471114 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -326,7 +326,7 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap,
 	sk_nulls_for_each_rcu(rc, node, laddr_hb) {
 		if (llc_dgram_match(sap, laddr, rc)) {
 			/* Extra checks required by SLAB_DESTROY_BY_RCU */
-			if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
+			if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
 				goto again;
 			if (unlikely(llc_sk(rc)->sap != sap ||
 				     !llc_dgram_match(sap, laddr, rc))) {
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index 1b05d4a..b4af509 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -11,6 +11,7 @@
 #include <linux/rcupdate.h>
 #include <linux/jhash.h>
 #include <linux/types.h>
+#include <linux/refcount.h>
 #include <linux/netfilter/ipset/ip_set_timeout.h>
 
 #define __ipset_dereference_protected(p, c)	rcu_dereference_protected(p, c)
@@ -78,8 +79,8 @@ struct hbucket {
 
 /* The hash table: the table size stored here in order to make resizing easy */
 struct htable {
-	atomic_t ref;		/* References for resizing */
-	atomic_t uref;		/* References for dumping */
+	refcount_t ref;		/* References for resizing */
+	refcount_t uref;		/* References for dumping */
 	u8 htable_bits;		/* size of hash table == 2^htable_bits */
 	struct hbucket __rcu *bucket[0]; /* hashtable buckets */
 };
@@ -591,8 +592,8 @@ mtype_resize(struct ip_set *set, bool retried)
 	spin_lock_bh(&set->lock);
 	orig = __ipset_dereference_protected(h->table, 1);
 	/* There can't be another parallel resizing, but dumping is possible */
-	atomic_set(&orig->ref, 1);
-	atomic_inc(&orig->uref);
+	refcount_set(&orig->ref, 1);
+	refcount_inc(&orig->uref);
 	extsize = 0;
 	pr_debug("attempt to resize set %s from %u to %u, t %p\n",
 		 set->name, orig->htable_bits, htable_bits, orig);
@@ -668,7 +669,7 @@ mtype_resize(struct ip_set *set, bool retried)
 	pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
 		 orig->htable_bits, orig, t->htable_bits, t);
 	/* If there's nobody else dumping the table, destroy it */
-	if (atomic_dec_and_test(&orig->uref)) {
+	if (refcount_dec_and_test(&orig->uref)) {
 		pr_debug("Table destroy by resize %p\n", orig);
 		mtype_ahash_destroy(set, orig, false);
 	}
@@ -680,8 +681,8 @@ mtype_resize(struct ip_set *set, bool retried)
 	return ret;
 
 cleanup:
-	atomic_set(&orig->ref, 0);
-	atomic_dec(&orig->uref);
+	refcount_set(&orig->ref, 0);
+	refcount_dec(&orig->uref);
 	spin_unlock_bh(&set->lock);
 	mtype_ahash_destroy(set, t, false);
 	if (ret == -EAGAIN)
@@ -1092,12 +1093,12 @@ mtype_uref(struct ip_set *set, struct netlink_callback *cb, bool start)
 	if (start) {
 		rcu_read_lock_bh();
 		t = rcu_dereference_bh_nfnl(h->table);
-		atomic_inc(&t->uref);
+		refcount_inc(&t->uref);
 		cb->args[IPSET_CB_PRIVATE] = (unsigned long)t;
 		rcu_read_unlock_bh();
 	} else if (cb->args[IPSET_CB_PRIVATE]) {
 		t = (struct htable *)cb->args[IPSET_CB_PRIVATE];
-		if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+		if (refcount_dec_and_test(&t->uref) && refcount_read(&t->ref)) {
 			/* Resizing didn't destroy the hash table */
 			pr_debug("Table destroy by dump: %p\n", t);
 			mtype_ahash_destroy(set, t, false);
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 096a451..04e78d4 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -181,7 +181,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
 
 	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
 		cp->flags |= IP_VS_CONN_F_HASHED;
-		atomic_inc(&cp->refcnt);
+		refcount_inc(&cp->refcnt);
 		hlist_add_head_rcu(&cp->c_list, &ip_vs_conn_tab[hash]);
 		ret = 1;
 	} else {
@@ -215,7 +215,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
 	if (cp->flags & IP_VS_CONN_F_HASHED) {
 		hlist_del_rcu(&cp->c_list);
 		cp->flags &= ~IP_VS_CONN_F_HASHED;
-		atomic_dec(&cp->refcnt);
+		refcount_dec(&cp->refcnt);
 		ret = 1;
 	} else
 		ret = 0;
@@ -242,13 +242,13 @@ static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
 	if (cp->flags & IP_VS_CONN_F_HASHED) {
 		ret = false;
 		/* Decrease refcnt and unlink conn only if we are last user */
-		if (atomic_cmpxchg(&cp->refcnt, 1, 0) == 1) {
+		if (refcount_dec_if_one(&cp->refcnt)) {
 			hlist_del_rcu(&cp->c_list);
 			cp->flags &= ~IP_VS_CONN_F_HASHED;
 			ret = true;
 		}
 	} else
-		ret = atomic_read(&cp->refcnt) ? false : true;
+		ret = refcount_read(&cp->refcnt) ? false : true;
 
 	spin_unlock(&cp->lock);
 	ct_write_unlock_bh(hash);
@@ -475,7 +475,7 @@ static void __ip_vs_conn_put_timer(struct ip_vs_conn *cp)
 void ip_vs_conn_put(struct ip_vs_conn *cp)
 {
 	if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) &&
-	    (atomic_read(&cp->refcnt) == 1) &&
+	    (refcount_read(&cp->refcnt) == 1) &&
 	    !timer_pending(&cp->timer))
 		/* expire connection immediately */
 		__ip_vs_conn_put_notimer(cp);
@@ -617,8 +617,8 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
 		      IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
 		      IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
 		      ip_vs_fwd_tag(cp), cp->state,
-		      cp->flags, atomic_read(&cp->refcnt),
-		      atomic_read(&dest->refcnt));
+		      cp->flags, refcount_read(&cp->refcnt),
+		      refcount_read(&dest->refcnt));
 
 	/* Update the connection counters */
 	if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
@@ -714,8 +714,8 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
 		      IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
 		      IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
 		      ip_vs_fwd_tag(cp), cp->state,
-		      cp->flags, atomic_read(&cp->refcnt),
-		      atomic_read(&dest->refcnt));
+		      cp->flags, refcount_read(&cp->refcnt),
+		      refcount_read(&dest->refcnt));
 
 	/* Update the connection counters */
 	if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
@@ -863,10 +863,10 @@ static void ip_vs_conn_expire(unsigned long data)
 
   expire_later:
 	IP_VS_DBG(7, "delayed: conn->refcnt=%d conn->n_control=%d\n",
-		  atomic_read(&cp->refcnt),
+		  refcount_read(&cp->refcnt),
 		  atomic_read(&cp->n_control));
 
-	atomic_inc(&cp->refcnt);
+	refcount_inc(&cp->refcnt);
 	cp->timeout = 60*HZ;
 
 	if (ipvs->sync_state & IP_VS_STATE_MASTER)
@@ -941,7 +941,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
 	 * it in the table, so that other thread run ip_vs_random_dropentry
 	 * but cannot drop this entry.
 	 */
-	atomic_set(&cp->refcnt, 1);
+	refcount_set(&cp->refcnt, 1);
 
 	cp->control = NULL;
 	atomic_set(&cp->n_control, 0);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index db40050..a3e1b9c 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -542,7 +542,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
 		      IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
 		      IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
 		      IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
-		      cp->flags, atomic_read(&cp->refcnt));
+		      cp->flags, refcount_read(&cp->refcnt));
 
 	ip_vs_conn_stats(cp, svc);
 	return cp;
@@ -1193,7 +1193,7 @@ struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc,
 		      IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
 		      IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
 		      IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport),
-		      cp->flags, atomic_read(&cp->refcnt));
+		      cp->flags, refcount_read(&cp->refcnt));
 	LeaveFunction(12);
 	return cp;
 }
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 55e0169..3e6bb33 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -322,7 +322,7 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
 
 	svc->flags |= IP_VS_SVC_F_HASHED;
 	/* increase its refcnt because it is referenced by the svc table */
-	atomic_inc(&svc->refcnt);
+	refcount_inc(&svc->refcnt);
 	return 1;
 }
 
@@ -348,7 +348,7 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
 	}
 
 	svc->flags &= ~IP_VS_SVC_F_HASHED;
-	atomic_dec(&svc->refcnt);
+	refcount_dec(&svc->refcnt);
 	return 1;
 }
 
@@ -458,7 +458,7 @@ ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol
 static inline void
 __ip_vs_bind_svc(struct ip_vs_dest *dest, struct ip_vs_service *svc)
 {
-	atomic_inc(&svc->refcnt);
+	refcount_inc(&svc->refcnt);
 	rcu_assign_pointer(dest->svc, svc);
 }
 
@@ -478,7 +478,7 @@ static void ip_vs_service_rcu_free(struct rcu_head *head)
 
 static void __ip_vs_svc_put(struct ip_vs_service *svc, bool do_delay)
 {
-	if (atomic_dec_and_test(&svc->refcnt)) {
+	if (refcount_dec_and_test(&svc->refcnt)) {
 		IP_VS_DBG_BUF(3, "Removing service %u/%s:%u\n",
 			      svc->fwmark,
 			      IP_VS_DBG_ADDR(svc->af, &svc->addr),
@@ -700,7 +700,7 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, int dest_af,
 			      dest->vfwmark,
 			      IP_VS_DBG_ADDR(dest->af, &dest->addr),
 			      ntohs(dest->port),
-			      atomic_read(&dest->refcnt));
+			      refcount_read(&dest->refcnt));
 		if (dest->af == dest_af &&
 		    ip_vs_addr_equal(dest_af, &dest->addr, daddr) &&
 		    dest->port == dport &&
@@ -936,7 +936,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
 	atomic_set(&dest->activeconns, 0);
 	atomic_set(&dest->inactconns, 0);
 	atomic_set(&dest->persistconns, 0);
-	atomic_set(&dest->refcnt, 1);
+	refcount_set(&dest->refcnt, 1);
 
 	INIT_HLIST_NODE(&dest->d_list);
 	spin_lock_init(&dest->dst_lock);
@@ -1000,7 +1000,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
 		IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, "
 			      "dest->refcnt=%d, service %u/%s:%u\n",
 			      IP_VS_DBG_ADDR(udest->af, &daddr), ntohs(dport),
-			      atomic_read(&dest->refcnt),
+			      refcount_read(&dest->refcnt),
 			      dest->vfwmark,
 			      IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
 			      ntohs(dest->vport));
@@ -1076,7 +1076,7 @@ static void __ip_vs_del_dest(struct netns_ipvs *ipvs, struct ip_vs_dest *dest,
 	spin_lock_bh(&ipvs->dest_trash_lock);
 	IP_VS_DBG_BUF(3, "Moving dest %s:%u into trash, dest->refcnt=%d\n",
 		      IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
-		      atomic_read(&dest->refcnt));
+		      refcount_read(&dest->refcnt));
 	if (list_empty(&ipvs->dest_trash) && !cleanup)
 		mod_timer(&ipvs->dest_trash_timer,
 			  jiffies + (IP_VS_DEST_TRASH_PERIOD >> 1));
@@ -1160,7 +1160,7 @@ static void ip_vs_dest_trash_expire(unsigned long data)
 
 	spin_lock(&ipvs->dest_trash_lock);
 	list_for_each_entry_safe(dest, next, &ipvs->dest_trash, t_list) {
-		if (atomic_read(&dest->refcnt) > 0)
+		if (refcount_read(&dest->refcnt) > 0)
 			continue;
 		if (dest->idle_start) {
 			if (time_before(now, dest->idle_start +
@@ -1250,7 +1250,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
 
 
 	/* I'm the first user of the service */
-	atomic_set(&svc->refcnt, 0);
+	refcount_set(&svc->refcnt, 0);
 
 	svc->af = u->af;
 	svc->protocol = u->protocol;
@@ -1465,7 +1465,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
 static void ip_vs_unlink_service(struct ip_vs_service *svc, bool cleanup)
 {
 	/* Hold svc to avoid double release from dest_trash */
-	atomic_inc(&svc->refcnt);
+	refcount_inc(&svc->refcnt);
 	/*
 	 * Unhash it from the service table
 	 */
@@ -1548,7 +1548,7 @@ ip_vs_forget_dev(struct ip_vs_dest *dest, struct net_device *dev)
 			      dev->name,
 			      IP_VS_DBG_ADDR(dest->af, &dest->addr),
 			      ntohs(dest->port),
-			      atomic_read(&dest->refcnt));
+			      refcount_read(&dest->refcnt));
 		__ip_vs_dst_cache_reset(dest);
 	}
 	spin_unlock_bh(&dest->dst_lock);
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
index 6be5c53..6e31531 100644
--- a/net/netfilter/ipvs/ip_vs_dh.c
+++ b/net/netfilter/ipvs/ip_vs_dh.c
@@ -247,7 +247,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 static struct ip_vs_scheduler ip_vs_dh_scheduler =
 {
 	.name =			"dh",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_dh_scheduler.n_list),
 	.init_service =		ip_vs_dh_init_svc,
diff --git a/net/netfilter/ipvs/ip_vs_fo.c b/net/netfilter/ipvs/ip_vs_fo.c
index e09874d..211078e 100644
--- a/net/netfilter/ipvs/ip_vs_fo.c
+++ b/net/netfilter/ipvs/ip_vs_fo.c
@@ -57,7 +57,7 @@ ip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 
 static struct ip_vs_scheduler ip_vs_fo_scheduler = {
 	.name =			"fo",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list),
 	.schedule =		ip_vs_fo_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index cccf4d6..71898d8 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -448,7 +448,7 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc)
 		      IP_VS_DBG_ADDR(least->af, &least->addr),
 		      ntohs(least->port),
 		      atomic_read(&least->activeconns),
-		      atomic_read(&least->refcnt),
+		      refcount_read(&least->refcnt),
 		      atomic_read(&least->weight), loh);
 
 	return least;
@@ -537,7 +537,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
  */
 static struct ip_vs_scheduler ip_vs_lblc_scheduler = {
 	.name =			"lblc",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_lblc_scheduler.n_list),
 	.init_service =		ip_vs_lblc_init_svc,
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 796d70e..64fb222 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -204,7 +204,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
 		      IP_VS_DBG_ADDR(least->af, &least->addr),
 		      ntohs(least->port),
 		      atomic_read(&least->activeconns),
-		      atomic_read(&least->refcnt),
+		      refcount_read(&least->refcnt),
 		      atomic_read(&least->weight), loh);
 	return least;
 }
@@ -249,7 +249,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
 		      __func__,
 		      IP_VS_DBG_ADDR(most->af, &most->addr), ntohs(most->port),
 		      atomic_read(&most->activeconns),
-		      atomic_read(&most->refcnt),
+		      refcount_read(&most->refcnt),
 		      atomic_read(&most->weight), moh);
 	return most;
 }
@@ -612,7 +612,7 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc)
 		      IP_VS_DBG_ADDR(least->af, &least->addr),
 		      ntohs(least->port),
 		      atomic_read(&least->activeconns),
-		      atomic_read(&least->refcnt),
+		      refcount_read(&least->refcnt),
 		      atomic_read(&least->weight), loh);
 
 	return least;
@@ -723,7 +723,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 static struct ip_vs_scheduler ip_vs_lblcr_scheduler =
 {
 	.name =			"lblcr",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_lblcr_scheduler.n_list),
 	.init_service =		ip_vs_lblcr_init_svc,
diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c
index 19a0769..5fb3bb9 100644
--- a/net/netfilter/ipvs/ip_vs_lc.c
+++ b/net/netfilter/ipvs/ip_vs_lc.c
@@ -70,7 +70,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 
 static struct ip_vs_scheduler ip_vs_lc_scheduler = {
 	.name =			"lc",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
 	.schedule =		ip_vs_lc_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c
index a8b6340..9ec9cd0 100644
--- a/net/netfilter/ipvs/ip_vs_nq.c
+++ b/net/netfilter/ipvs/ip_vs_nq.c
@@ -110,7 +110,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 		      IP_VS_DBG_ADDR(least->af, &least->addr),
 		      ntohs(least->port),
 		      atomic_read(&least->activeconns),
-		      atomic_read(&least->refcnt),
+		      refcount_read(&least->refcnt),
 		      atomic_read(&least->weight), loh);
 
 	return least;
@@ -120,7 +120,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 static struct ip_vs_scheduler ip_vs_nq_scheduler =
 {
 	.name =			"nq",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_nq_scheduler.n_list),
 	.schedule =		ip_vs_nq_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_ovf.c b/net/netfilter/ipvs/ip_vs_ovf.c
index f7d62c3..fbcd826 100644
--- a/net/netfilter/ipvs/ip_vs_ovf.c
+++ b/net/netfilter/ipvs/ip_vs_ovf.c
@@ -64,7 +64,7 @@ ip_vs_ovf_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 
 static struct ip_vs_scheduler ip_vs_ovf_scheduler = {
 	.name =			"ovf",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_ovf_scheduler.n_list),
 	.schedule =		ip_vs_ovf_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
index d07ef9e..364156b 100644
--- a/net/netfilter/ipvs/ip_vs_pe_sip.c
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
@@ -160,7 +160,7 @@ ip_vs_sip_conn_out(struct ip_vs_service *svc,
 static struct ip_vs_pe ip_vs_sip_pe =
 {
 	.name =			"sip",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_sip_pe.n_list),
 	.fill_param =		ip_vs_sip_fill_param,
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index d952d67..56f8e4b 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -447,7 +447,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
 				ntohs(cp->cport),
 				sctp_state_name(cp->state),
 				sctp_state_name(next_state),
-				atomic_read(&cp->refcnt));
+				refcount_read(&cp->refcnt));
 		if (dest) {
 			if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
 				(next_state != IP_VS_SCTP_S_ESTABLISHED)) {
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index 5117bcb..12dc8d5 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -557,7 +557,7 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
 			      ntohs(cp->cport),
 			      tcp_state_name(cp->state),
 			      tcp_state_name(new_state),
-			      atomic_read(&cp->refcnt));
+			      refcount_read(&cp->refcnt));
 
 		if (dest) {
 			if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c
index 58bacfc..7d8f6cb 100644
--- a/net/netfilter/ipvs/ip_vs_rr.c
+++ b/net/netfilter/ipvs/ip_vs_rr.c
@@ -97,7 +97,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 		      "activeconns %d refcnt %d weight %d\n",
 		      IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
 		      atomic_read(&dest->activeconns),
-		      atomic_read(&dest->refcnt), atomic_read(&dest->weight));
+		      refcount_read(&dest->refcnt), atomic_read(&dest->weight));
 
 	return dest;
 }
@@ -105,7 +105,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 
 static struct ip_vs_scheduler ip_vs_rr_scheduler = {
 	.name =			"rr",			/* name */
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),
 	.init_service =		ip_vs_rr_init_svc,
diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c
index f8e2d00..9a1bdc0 100644
--- a/net/netfilter/ipvs/ip_vs_sed.c
+++ b/net/netfilter/ipvs/ip_vs_sed.c
@@ -111,7 +111,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 		      IP_VS_DBG_ADDR(least->af, &least->addr),
 		      ntohs(least->port),
 		      atomic_read(&least->activeconns),
-		      atomic_read(&least->refcnt),
+		      refcount_read(&least->refcnt),
 		      atomic_read(&least->weight), loh);
 
 	return least;
@@ -121,7 +121,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 static struct ip_vs_scheduler ip_vs_sed_scheduler =
 {
 	.name =			"sed",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_sed_scheduler.n_list),
 	.schedule =		ip_vs_sed_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 1e373a5..b7330cf 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -352,7 +352,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 static struct ip_vs_scheduler ip_vs_sh_scheduler =
 {
 	.name =			"sh",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list	 =		LIST_HEAD_INIT(ip_vs_sh_scheduler.n_list),
 	.init_service =		ip_vs_sh_init_svc,
diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c
index 6b366fd..3c19dac 100644
--- a/net/netfilter/ipvs/ip_vs_wlc.c
+++ b/net/netfilter/ipvs/ip_vs_wlc.c
@@ -83,7 +83,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 		      IP_VS_DBG_ADDR(least->af, &least->addr),
 		      ntohs(least->port),
 		      atomic_read(&least->activeconns),
-		      atomic_read(&least->refcnt),
+		      refcount_read(&least->refcnt),
 		      atomic_read(&least->weight), loh);
 
 	return least;
@@ -93,7 +93,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 static struct ip_vs_scheduler ip_vs_wlc_scheduler =
 {
 	.name =			"wlc",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list),
 	.schedule =		ip_vs_wlc_schedule,
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c
index 17e6d44..0704af3 100644
--- a/net/netfilter/ipvs/ip_vs_wrr.c
+++ b/net/netfilter/ipvs/ip_vs_wrr.c
@@ -218,7 +218,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 		      "activeconns %d refcnt %d weight %d\n",
 		      IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
 		      atomic_read(&dest->activeconns),
-		      atomic_read(&dest->refcnt),
+		      refcount_read(&dest->refcnt),
 		      atomic_read(&dest->weight));
 	mark->cl = dest;
 
@@ -243,7 +243,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
 
 static struct ip_vs_scheduler ip_vs_wrr_scheduler = {
 	.name =			"wrr",
-	.refcnt =		ATOMIC_INIT(0),
+	.refcnt =		REFCOUNT_INIT(0),
 	.module =		THIS_MODULE,
 	.n_list =		LIST_HEAD_INIT(ip_vs_wrr_scheduler.n_list),
 	.init_service =		ip_vs_wrr_init_svc,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3a073cd..04d5c7ec 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -364,7 +364,7 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
 	tmpl->status = IPS_TEMPLATE;
 	write_pnet(&tmpl->ct_net, net);
 	nf_ct_zone_add(tmpl, zone);
-	atomic_set(&tmpl->ct_general.use, 0);
+	refcount_set(&tmpl->ct_general.use, 0);
 
 	return tmpl;
 }
@@ -385,7 +385,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
 	struct nf_conntrack_l4proto *l4proto;
 
 	pr_debug("destroy_conntrack(%p)\n", ct);
-	NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
+	NF_CT_ASSERT(refcount_read(&nfct->use) == 0);
 
 	if (unlikely(nf_ct_is_template(ct))) {
 		nf_ct_tmpl_free(ct);
@@ -490,7 +490,7 @@ nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,
 /* caller must hold rcu readlock and none of the nf_conntrack_locks */
 static void nf_ct_gc_expired(struct nf_conn *ct)
 {
-	if (!atomic_inc_not_zero(&ct->ct_general.use))
+	if (!refcount_inc_not_zero(&ct->ct_general.use))
 		return;
 
 	if (nf_ct_should_gc(ct))
@@ -559,7 +559,7 @@ __nf_conntrack_find_get(struct net *net, const struct nf_conntrack_zone *zone,
 	if (h) {
 		ct = nf_ct_tuplehash_to_ctrack(h);
 		if (unlikely(nf_ct_is_dying(ct) ||
-			     !atomic_inc_not_zero(&ct->ct_general.use)))
+			     !refcount_inc_not_zero(&ct->ct_general.use)))
 			h = NULL;
 		else {
 			if (unlikely(!nf_ct_key_equal(h, tuple, zone, net))) {
@@ -626,7 +626,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
 
 	smp_wmb();
 	/* The caller holds a reference to this object */
-	atomic_set(&ct->ct_general.use, 2);
+	refcount_set(&ct->ct_general.use, 2);
 	__nf_conntrack_hash_insert(ct, hash, reply_hash);
 	nf_conntrack_double_unlock(hash, reply_hash);
 	NF_CT_STAT_INC(net, insert);
@@ -685,7 +685,7 @@ static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
 	if (l4proto->allow_clash &&
 	    !nfct_nat(ct) &&
 	    !nf_ct_is_dying(ct) &&
-	    atomic_inc_not_zero(&ct->ct_general.use)) {
+	    refcount_inc_not_zero(&ct->ct_general.use)) {
 		nf_ct_acct_merge(ct, ctinfo, (struct nf_conn *)skb->nfct);
 		nf_conntrack_put(skb->nfct);
 		/* Assign conntrack already in hashes to this skbuff. Don't
@@ -777,7 +777,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
 	   setting time, otherwise we'd get timer wrap in
 	   weird delay cases. */
 	ct->timeout += nfct_time_stamp;
-	atomic_inc(&ct->ct_general.use);
+	refcount_inc(&ct->ct_general.use);
 	ct->status |= IPS_CONFIRMED;
 
 	/* set conntrack timestamp, if enabled. */
@@ -891,7 +891,7 @@ static unsigned int early_drop_list(struct net *net,
 		    nf_ct_is_dying(tmp))
 			continue;
 
-		if (!atomic_inc_not_zero(&tmp->ct_general.use))
+		if (!refcount_inc_not_zero(&tmp->ct_general.use))
 			continue;
 
 		/* kill only if still in same netns -- might have moved due to
@@ -1075,7 +1075,7 @@ __nf_conntrack_alloc(struct net *net,
 	/* Because we use RCU lookups, we set ct_general.use to zero before
 	 * this is inserted in any list.
 	 */
-	atomic_set(&ct->ct_general.use, 0);
+	refcount_set(&ct->ct_general.use, 0);
 	return ct;
 out:
 	atomic_dec(&net->ct.count);
@@ -1099,7 +1099,7 @@ void nf_conntrack_free(struct nf_conn *ct)
 	/* A freed object has refcnt == 0, that's
 	 * the golden rule for SLAB_DESTROY_BY_RCU
 	 */
-	NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0);
+	NF_CT_ASSERT(refcount_read(&ct->ct_general.use) == 0);
 
 	nf_ct_ext_destroy(ct);
 	nf_ct_ext_free(ct);
@@ -1573,7 +1573,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
 	}
 	return NULL;
 found:
-	atomic_inc(&ct->ct_general.use);
+	refcount_inc(&ct->ct_general.use);
 	spin_unlock(lockp);
 	local_bh_enable();
 	return ct;
@@ -1623,7 +1623,7 @@ static int untrack_refs(void)
 	for_each_possible_cpu(cpu) {
 		struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu);
 
-		cnt += atomic_read(&ct->ct_general.use) - 1;
+		cnt += refcount_read(&ct->ct_general.use) - 1;
 	}
 	return cnt;
 }
@@ -1911,7 +1911,7 @@ int nf_conntrack_init_start(void)
 	for_each_possible_cpu(cpu) {
 		struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu);
 		write_pnet(&ct->ct_net, &init_net);
-		atomic_set(&ct->ct_general.use, 1);
+		refcount_set(&ct->ct_general.use, 1);
 	}
 	/*  - and look it like as a confirmed connection */
 	nf_ct_untracked_status_or(IPS_CONFIRMED | IPS_UNTRACKED);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index f8dbacf..5b2448f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -133,7 +133,7 @@ nf_ct_expect_find_get(struct net *net,
 
 	rcu_read_lock();
 	i = __nf_ct_expect_find(net, zone, tuple);
-	if (i && !atomic_inc_not_zero(&i->use))
+	if (i && !refcount_inc_not_zero(&i->use))
 		i = NULL;
 	rcu_read_unlock();
 
@@ -182,11 +182,11 @@ nf_ct_find_expectation(struct net *net,
 	 * can be sure the ct cannot disappear underneath.
 	 */
 	if (unlikely(nf_ct_is_dying(exp->master) ||
-		     !atomic_inc_not_zero(&exp->master->ct_general.use)))
+		     !refcount_inc_not_zero(&exp->master->ct_general.use)))
 		return NULL;
 
 	if (exp->flags & NF_CT_EXPECT_PERMANENT) {
-		atomic_inc(&exp->use);
+		refcount_inc(&exp->use);
 		return exp;
 	} else if (del_timer(&exp->timeout)) {
 		nf_ct_unlink_expect(exp);
@@ -275,7 +275,7 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
 		return NULL;
 
 	new->master = me;
-	atomic_set(&new->use, 1);
+	refcount_set(&new->use, 1);
 	return new;
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
@@ -348,7 +348,7 @@ static void nf_ct_expect_free_rcu(struct rcu_head *head)
 
 void nf_ct_expect_put(struct nf_conntrack_expect *exp)
 {
-	if (atomic_dec_and_test(&exp->use))
+	if (refcount_dec_and_test(&exp->use))
 		call_rcu(&exp->rcu, nf_ct_expect_free_rcu);
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_put);
@@ -361,7 +361,7 @@ static int nf_ct_expect_insert(struct nf_conntrack_expect *exp)
 	unsigned int h = nf_ct_expect_dst_hash(net, &exp->tuple);
 
 	/* two references : one for hash insert, one for the timer */
-	atomic_add(2, &exp->use);
+	refcount_add(2, &exp->use);
 
 	hlist_add_head(&exp->lnode, &master_help->expectations);
 	master_help->expecting[exp->class]++;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 2754045..7a7012a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -449,7 +449,7 @@ static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
 
 static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
 {
-	if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use))))
+	if (nla_put_be32(skb, CTA_USE, htonl(refcount_read(&ct->ct_general.use))))
 		goto nla_put_failure;
 	return 0;
 
@@ -845,7 +845,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 			ct = nf_ct_tuplehash_to_ctrack(h);
 			if (nf_ct_is_expired(ct)) {
 				if (i < ARRAY_SIZE(nf_ct_evict) &&
-				    atomic_inc_not_zero(&ct->ct_general.use))
+				    refcount_inc_not_zero(&ct->ct_general.use))
 					nf_ct_evict[i++] = ct;
 				continue;
 			}
@@ -1306,7 +1306,7 @@ ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying
 						  ct);
 			rcu_read_unlock();
 			if (res < 0) {
-				if (!atomic_inc_not_zero(&ct->ct_general.use))
+				if (!refcount_inc_not_zero(&ct->ct_general.use))
 					continue;
 				cb->args[0] = cpu;
 				cb->args[1] = (unsigned long)ct;
@@ -2660,7 +2660,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 						    cb->nlh->nlmsg_seq,
 						    IPCTNL_MSG_EXP_NEW,
 						    exp) < 0) {
-				if (!atomic_inc_not_zero(&exp->use))
+				if (!refcount_inc_not_zero(&exp->use))
 					continue;
 				cb->args[1] = (unsigned long)exp;
 				goto out;
@@ -2706,7 +2706,7 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 					    cb->nlh->nlmsg_seq,
 					    IPCTNL_MSG_EXP_NEW,
 					    exp) < 0) {
-			if (!atomic_inc_not_zero(&exp->use))
+			if (!refcount_inc_not_zero(&exp->use))
 				continue;
 			cb->args[1] = (unsigned long)exp;
 			goto out;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index d009ae6..c0a278f 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -209,7 +209,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
 	int ret = 0;
 
 	NF_CT_ASSERT(ct);
-	if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
+	if (unlikely(!refcount_inc_not_zero(&ct->ct_general.use)))
 		return 0;
 
 	if (nf_ct_should_gc(ct)) {
@@ -274,7 +274,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
 	ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR);
 	ct_show_delta_time(s, ct);
 
-	seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use));
+	seq_printf(s, "use=%u\n", refcount_read(&ct->ct_general.use));
 
 	if (seq_has_overflowed(s))
 		goto release;
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index d44d89b..f44cbd3 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/netlink.h>
 #include <linux/rculist.h>
 #include <linux/slab.h>
@@ -32,7 +33,7 @@ struct nf_acct {
 	atomic64_t		bytes;
 	unsigned long		flags;
 	struct list_head	head;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	char			name[NFACCT_NAME_MAX];
 	struct rcu_head		rcu_head;
 	char			data[0];
@@ -123,7 +124,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
 		atomic64_set(&nfacct->pkts,
 			     be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS])));
 	}
-	atomic_set(&nfacct->refcnt, 1);
+	refcount_set(&nfacct->refcnt, 1);
 	list_add_tail_rcu(&nfacct->head, &net->nfnl_acct_list);
 	return 0;
 }
@@ -166,7 +167,7 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
 			 NFACCT_PAD) ||
 	    nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes),
 			 NFACCT_PAD) ||
-	    nla_put_be32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt))))
+	    nla_put_be32(skb, NFACCT_USE, htonl(refcount_read(&acct->refcnt))))
 		goto nla_put_failure;
 	if (acct->flags & NFACCT_F_QUOTA) {
 		u64 *quota = (u64 *)acct->data;
@@ -325,11 +326,12 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
 static int nfnl_acct_try_del(struct nf_acct *cur)
 {
 	int ret = 0;
+	unsigned int refcount;
 
 	/* We want to avoid races with nfnl_acct_put. So only when the current
 	 * refcnt is 1, we decrease it to 0.
 	 */
-	if (atomic_cmpxchg(&cur->refcnt, 1, 0) == 1) {
+	if (refcount_dec_if_one(&cur->refcnt)) {
 		/* We are protected by nfnl mutex. */
 		list_del_rcu(&cur->head);
 		kfree_rcu(cur, rcu_head);
@@ -413,7 +415,7 @@ struct nf_acct *nfnl_acct_find_get(struct net *net, const char *acct_name)
 		if (!try_module_get(THIS_MODULE))
 			goto err;
 
-		if (!atomic_inc_not_zero(&cur->refcnt)) {
+		if (!refcount_inc_not_zero(&cur->refcnt)) {
 			module_put(THIS_MODULE);
 			goto err;
 		}
@@ -429,7 +431,7 @@ EXPORT_SYMBOL_GPL(nfnl_acct_find_get);
 
 void nfnl_acct_put(struct nf_acct *acct)
 {
-	if (atomic_dec_and_test(&acct->refcnt))
+	if (refcount_dec_and_test(&acct->refcnt))
 		kfree_rcu(acct, rcu_head);
 
 	module_put(THIS_MODULE);
@@ -502,7 +504,7 @@ static void __net_exit nfnl_acct_net_exit(struct net *net)
 	list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head) {
 		list_del_rcu(&cur->head);
 
-		if (atomic_dec_and_test(&cur->refcnt))
+		if (refcount_dec_and_test(&cur->refcnt))
 			kfree_rcu(cur, rcu_head);
 	}
 }
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 139e086..baa75f3 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -138,7 +138,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
 	strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
 	timeout->l3num = l3num;
 	timeout->l4proto = l4proto;
-	atomic_set(&timeout->refcnt, 1);
+	refcount_set(&timeout->refcnt, 1);
 	list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
 
 	return 0;
@@ -172,7 +172,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
 	    nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) ||
 	    nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
 	    nla_put_be32(skb, CTA_TIMEOUT_USE,
-			 htonl(atomic_read(&timeout->refcnt))))
+			 htonl(refcount_read(&timeout->refcnt))))
 		goto nla_put_failure;
 
 	if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
@@ -339,7 +339,7 @@ static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
 	/* We want to avoid races with ctnl_timeout_put. So only when the
 	 * current refcnt is 1, we decrease it to 0.
 	 */
-	if (atomic_cmpxchg(&timeout->refcnt, 1, 0) == 1) {
+	if (refcount_dec_if_one(&timeout->refcnt)) {
 		/* We are protected by nfnl mutex. */
 		list_del_rcu(&timeout->head);
 		nf_ct_l4proto_put(timeout->l4proto);
@@ -536,7 +536,7 @@ ctnl_timeout_find_get(struct net *net, const char *name)
 		if (!try_module_get(THIS_MODULE))
 			goto err;
 
-		if (!atomic_inc_not_zero(&timeout->refcnt)) {
+		if (!refcount_inc_not_zero(&timeout->refcnt)) {
 			module_put(THIS_MODULE);
 			goto err;
 		}
@@ -550,7 +550,7 @@ ctnl_timeout_find_get(struct net *net, const char *name)
 
 static void ctnl_timeout_put(struct ctnl_timeout *timeout)
 {
-	if (atomic_dec_and_test(&timeout->refcnt))
+	if (refcount_dec_and_test(&timeout->refcnt))
 		kfree_rcu(timeout, rcu_head);
 
 	module_put(THIS_MODULE);
@@ -601,7 +601,7 @@ static void __net_exit cttimeout_net_exit(struct net *net)
 		list_del_rcu(&cur->head);
 		nf_ct_l4proto_put(cur->l4proto);
 
-		if (atomic_dec_and_test(&cur->refcnt))
+		if (refcount_dec_and_test(&cur->refcnt))
 			kfree_rcu(cur, rcu_head);
 	}
 }
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 08247bf..ecd857b 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -40,6 +40,8 @@
 #include <net/netfilter/nfnetlink_log.h>
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
+
 
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 #include "../bridge/br_private.h"
@@ -57,7 +59,7 @@
 struct nfulnl_instance {
 	struct hlist_node hlist;	/* global list of instances */
 	spinlock_t lock;
-	atomic_t use;			/* use count */
+	refcount_t use;			/* use count */
 
 	unsigned int qlen;		/* number of nlmsgs in skb */
 	struct sk_buff *skb;		/* pre-allocatd skb */
@@ -115,7 +117,7 @@ __instance_lookup(struct nfnl_log_net *log, u_int16_t group_num)
 static inline void
 instance_get(struct nfulnl_instance *inst)
 {
-	atomic_inc(&inst->use);
+	refcount_inc(&inst->use);
 }
 
 static struct nfulnl_instance *
@@ -125,7 +127,7 @@ instance_lookup_get(struct nfnl_log_net *log, u_int16_t group_num)
 
 	rcu_read_lock_bh();
 	inst = __instance_lookup(log, group_num);
-	if (inst && !atomic_inc_not_zero(&inst->use))
+	if (inst && !refcount_inc_not_zero(&inst->use))
 		inst = NULL;
 	rcu_read_unlock_bh();
 
@@ -145,7 +147,7 @@ static void nfulnl_instance_free_rcu(struct rcu_head *head)
 static void
 instance_put(struct nfulnl_instance *inst)
 {
-	if (inst && atomic_dec_and_test(&inst->use))
+	if (inst && refcount_dec_and_test(&inst->use))
 		call_rcu_bh(&inst->rcu, nfulnl_instance_free_rcu);
 }
 
@@ -180,7 +182,7 @@ instance_create(struct net *net, u_int16_t group_num,
 	INIT_HLIST_NODE(&inst->hlist);
 	spin_lock_init(&inst->lock);
 	/* needs to be two, since we _put() after creation */
-	atomic_set(&inst->use, 2);
+	refcount_set(&inst->use, 2);
 
 	setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst);
 
@@ -1031,7 +1033,7 @@ static int seq_show(struct seq_file *s, void *v)
 		   inst->group_num,
 		   inst->peer_portid, inst->qlen,
 		   inst->copy_mode, inst->copy_range,
-		   inst->flushtimeout, atomic_read(&inst->use));
+		   inst->flushtimeout, refcount_read(&inst->use));
 
 	return 0;
 }
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index e6baeae..07ab24d 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -533,7 +533,7 @@ static void nft_notrack_eval(const struct nft_expr *expr,
 		return;
 
 	ct = nf_ct_untracked_get();
-	atomic_inc(&ct->ct_general.use);
+	refcount_inc(&ct->ct_general.use);
 	skb->nfct = &ct->ct_general;
 	skb->nfctinfo = IP_CT_NEW;
 }
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 95c7503..cc4a08f 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -29,7 +29,7 @@ static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
 	/* special case the untracked ct : we want the percpu object */
 	if (!ct)
 		ct = nf_ct_untracked_get();
-	atomic_inc(&ct->ct_general.use);
+	refcount_inc(&ct->ct_general.use);
 	skb->nfct = &ct->ct_general;
 	skb->nfctinfo = IP_CT_NEW;
 
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 80cb7ba..d51f1e8 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -127,7 +127,7 @@ nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp,
 						    daddr, dport,
 						    in->ifindex);
 
-			if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+			if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
 				sk = NULL;
 			/* NOTE: we return listeners even if bound to
 			 * 0.0.0.0, those are filtered out in
@@ -197,7 +197,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
 						   daddr, ntohs(dport),
 						   in->ifindex);
 
-			if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+			if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
 				sk = NULL;
 			/* NOTE: we return listeners even if bound to
 			 * 0.0.0.0, those are filtered out in
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 161b628..ed7c2fa 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -341,7 +341,7 @@ static void netlink_sock_destruct(struct sock *sk)
 	}
 
 	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
-	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
 	WARN_ON(nlk_sk(sk)->groups);
 }
 
@@ -544,7 +544,7 @@ static void netlink_remove(struct sock *sk)
 	table = &nl_table[sk->sk_protocol];
 	if (!rhashtable_remove_fast(&table->hash, &nlk_sk(sk)->node,
 				    netlink_rhashtable_params)) {
-		WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
+		WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
 		__sock_put(sk);
 	}
 
@@ -657,7 +657,7 @@ static void deferred_put_nlk_sk(struct rcu_head *head)
 	struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu);
 	struct sock *sk = &nlk->sk;
 
-	if (!atomic_dec_and_test(&sk->sk_refcnt))
+	if (!refcount_dec_and_test(&sk->sk_refcnt))
 		return;
 
 	if (nlk->cb_running && nlk->cb.done) {
@@ -1797,7 +1797,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	}
 
 	if (dst_group) {
-		atomic_inc(&skb->users);
+		refcount_inc(&skb->users);
 		netlink_broadcast(sk, skb, dst_portid, dst_group, GFP_KERNEL);
 	}
 	err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
@@ -2175,7 +2175,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 	struct netlink_sock *nlk;
 	int ret;
 
-	atomic_inc(&skb->users);
+	refcount_inc(&skb->users);
 
 	sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid);
 	if (sk == NULL) {
@@ -2332,7 +2332,7 @@ int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
 		int exclude_portid = 0;
 
 		if (report) {
-			atomic_inc(&skb->users);
+			refcount_inc(&skb->users);
 			exclude_portid = portid;
 		}
 
@@ -2469,7 +2469,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
 			   sk_rmem_alloc_get(s),
 			   sk_wmem_alloc_get(s),
 			   nlk->cb_running,
-			   atomic_read(&s->sk_refcnt),
+			   refcount_read(&s->sk_refcnt),
 			   atomic_read(&s->sk_drops),
 			   sock_i_ino(s)
 			);
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index d72a4f1..0c59354 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -149,7 +149,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 		nr_neigh->count    = 0;
 		nr_neigh->number   = nr_neigh_no++;
 		nr_neigh->failed   = 0;
-		atomic_set(&nr_neigh->refcount, 1);
+		refcount_set(&nr_neigh->refcount, 1);
 
 		if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
 			nr_neigh->digipeat = kmemdup(ax25_digi,
@@ -184,7 +184,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 
 		nr_node->which = 0;
 		nr_node->count = 1;
-		atomic_set(&nr_node->refcount, 1);
+		refcount_set(&nr_node->refcount, 1);
 		spin_lock_init(&nr_node->node_lock);
 
 		nr_node->routes[0].quality   = quality;
@@ -431,7 +431,7 @@ static int __must_check nr_add_neigh(ax25_address *callsign,
 	nr_neigh->count    = 0;
 	nr_neigh->number   = nr_neigh_no++;
 	nr_neigh->failed   = 0;
-	atomic_set(&nr_neigh->refcount, 1);
+	refcount_set(&nr_neigh->refcount, 1);
 
 	if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
 		nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index b9e1a13..e543e59 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1312,7 +1312,7 @@ static void packet_sock_destruct(struct sock *sk)
 	skb_queue_purge(&sk->sk_error_queue);
 
 	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
-	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
 
 	if (!sock_flag(sk, SOCK_DEAD)) {
 		pr_err("Attempt to release alive packet socket: %p\n", sk);
@@ -1680,7 +1680,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 		match->flags = flags;
 		INIT_LIST_HEAD(&match->list);
 		spin_lock_init(&match->lock);
-		atomic_set(&match->sk_ref, 0);
+		refcount_set(&match->sk_ref, 0);
 		fanout_init_data(match);
 		match->prot_hook.type = po->prot_hook.type;
 		match->prot_hook.dev = po->prot_hook.dev;
@@ -1695,10 +1695,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 	    match->prot_hook.type == po->prot_hook.type &&
 	    match->prot_hook.dev == po->prot_hook.dev) {
 		err = -ENOSPC;
-		if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
+		if (refcount_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
 			__dev_remove_pack(&po->prot_hook);
 			po->fanout = match;
-			atomic_inc(&match->sk_ref);
+			refcount_inc(&match->sk_ref);
 			__fanout_link(sk, po);
 			err = 0;
 		}
@@ -1724,7 +1724,7 @@ static void fanout_release(struct sock *sk)
 	mutex_lock(&fanout_mutex);
 	po->fanout = NULL;
 
-	if (atomic_dec_and_test(&f->sk_ref)) {
+	if (refcount_dec_and_test(&f->sk_ref)) {
 		list_del(&f->list);
 		dev_remove_pack(&f->prot_hook);
 		fanout_release_data(f);
@@ -2461,7 +2461,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 	skb->data_len = to_write;
 	skb->len += to_write;
 	skb->truesize += to_write;
-	atomic_add(to_write, &po->sk.sk_wmem_alloc);
+	refcount_add(to_write, &po->sk.sk_wmem_alloc);
 
 	while (likely(to_write)) {
 		nr_frags = skb_shinfo(skb)->nr_frags;
@@ -4401,7 +4401,7 @@ static int packet_seq_show(struct seq_file *seq, void *v)
 		seq_printf(seq,
 			   "%pK %-6d %-4d %04x   %-5d %1d %-6u %-6u %-6lu\n",
 			   s,
-			   atomic_read(&s->sk_refcnt),
+			   refcount_read(&s->sk_refcnt),
 			   s->sk_type,
 			   ntohs(po->num),
 			   po->ifindex,
diff --git a/net/packet/internal.h b/net/packet/internal.h
index 9ee4631..94d1d40 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -1,6 +1,8 @@
 #ifndef __PACKET_INTERNAL_H__
 #define __PACKET_INTERNAL_H__
 
+#include <linux/refcount.h>
+
 struct packet_mclist {
 	struct packet_mclist	*next;
 	int			ifindex;
@@ -86,7 +88,7 @@ struct packet_fanout {
 	struct list_head	list;
 	struct sock		*arr[PACKET_FANOUT_MAX];
 	spinlock_t		lock;
-	atomic_t		sk_ref;
+	refcount_t		sk_ref;
 	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
 };
 
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index ffd5f22..bf95d74 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -358,7 +358,7 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
 		return POLLHUP;
 
 	if (sk->sk_state == TCP_ESTABLISHED &&
-		atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf &&
+		refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf &&
 		atomic_read(&pn->tx_credits))
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 
@@ -612,7 +612,7 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v)
 			sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
 			from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
 			sock_i_ino(sk),
-			atomic_read(&sk->sk_refcnt), sk,
+			refcount_read(&sk->sk_refcnt), sk,
 			atomic_read(&sk->sk_drops));
 	}
 	seq_pad(seq, '\n');
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 5680d90..fd8ec93 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -116,8 +116,8 @@ static void rds_ib_dev_free(struct work_struct *work)
 
 void rds_ib_dev_put(struct rds_ib_device *rds_ibdev)
 {
-	BUG_ON(atomic_read(&rds_ibdev->refcount) <= 0);
-	if (atomic_dec_and_test(&rds_ibdev->refcount))
+	BUG_ON(refcount_read(&rds_ibdev->refcount) == 0);
+	if (refcount_dec_and_test(&rds_ibdev->refcount))
 		queue_work(rds_wq, &rds_ibdev->free_work);
 }
 
@@ -135,7 +135,7 @@ static void rds_ib_add_one(struct ib_device *device)
 		return;
 
 	spin_lock_init(&rds_ibdev->spinlock);
-	atomic_set(&rds_ibdev->refcount, 1);
+	refcount_set(&rds_ibdev->refcount, 1);
 	INIT_WORK(&rds_ibdev->free_work, rds_ib_dev_free);
 
 	rds_ibdev->max_wrs = device->attrs.max_qp_wr;
@@ -195,10 +195,10 @@ static void rds_ib_add_one(struct ib_device *device)
 	down_write(&rds_ib_devices_lock);
 	list_add_tail_rcu(&rds_ibdev->list, &rds_ib_devices);
 	up_write(&rds_ib_devices_lock);
-	atomic_inc(&rds_ibdev->refcount);
+	refcount_inc(&rds_ibdev->refcount);
 
 	ib_set_client_data(device, &rds_ib_client, rds_ibdev);
-	atomic_inc(&rds_ibdev->refcount);
+	refcount_inc(&rds_ibdev->refcount);
 
 	rds_ib_nodev_connect();
 
@@ -229,7 +229,7 @@ struct rds_ib_device *rds_ib_get_client_data(struct ib_device *device)
 	rcu_read_lock();
 	rds_ibdev = ib_get_client_data(device, &rds_ib_client);
 	if (rds_ibdev)
-		atomic_inc(&rds_ibdev->refcount);
+		refcount_inc(&rds_ibdev->refcount);
 	rcu_read_unlock();
 	return rds_ibdev;
 }
diff --git a/net/rds/ib.h b/net/rds/ib.h
index 45ac8e8..ddc97d7 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -219,7 +219,7 @@ struct rds_ib_device {
 	unsigned int		max_initiator_depth;
 	unsigned int		max_responder_resources;
 	spinlock_t		spinlock;	/* protect the above */
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct work_struct	free_work;
 };
 
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 977f698..9a3c54e 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -52,7 +52,7 @@ static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
 	list_for_each_entry_rcu(rds_ibdev, &rds_ib_devices, list) {
 		list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
 			if (i_ipaddr->ipaddr == ipaddr) {
-				atomic_inc(&rds_ibdev->refcount);
+				refcount_inc(&rds_ibdev->refcount);
 				rcu_read_unlock();
 				return rds_ibdev;
 			}
@@ -134,7 +134,7 @@ void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *con
 	spin_unlock_irq(&ib_nodev_conns_lock);
 
 	ic->rds_ibdev = rds_ibdev;
-	atomic_inc(&rds_ibdev->refcount);
+	refcount_inc(&rds_ibdev->refcount);
 }
 
 void rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn)
diff --git a/net/rds/message.c b/net/rds/message.c
index 49bfb51..4318cc9 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -48,8 +48,8 @@ static unsigned int	rds_exthdr_size[__RDS_EXTHDR_MAX] = {
 
 void rds_message_addref(struct rds_message *rm)
 {
-	rdsdebug("addref rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
-	atomic_inc(&rm->m_refcount);
+	rdsdebug("addref rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
+	refcount_inc(&rm->m_refcount);
 }
 EXPORT_SYMBOL_GPL(rds_message_addref);
 
@@ -83,9 +83,9 @@ static void rds_message_purge(struct rds_message *rm)
 
 void rds_message_put(struct rds_message *rm)
 {
-	rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
-	WARN(!atomic_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
-	if (atomic_dec_and_test(&rm->m_refcount)) {
+	rdsdebug("put rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
+	WARN(!refcount_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
+	if (refcount_dec_and_test(&rm->m_refcount)) {
 		BUG_ON(!list_empty(&rm->m_sock_item));
 		BUG_ON(!list_empty(&rm->m_conn_item));
 		rds_message_purge(rm);
@@ -206,7 +206,7 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)
 	rm->m_used_sgs = 0;
 	rm->m_total_sgs = extra_len / sizeof(struct scatterlist);
 
-	atomic_set(&rm->m_refcount, 1);
+	refcount_set(&rm->m_refcount, 1);
 	INIT_LIST_HEAD(&rm->m_sock_item);
 	INIT_LIST_HEAD(&rm->m_conn_item);
 	spin_lock_init(&rm->m_rs_lock);
diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index ea96114..1325c20 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -85,7 +85,7 @@ static struct rds_mr *rds_mr_tree_walk(struct rb_root *root, u64 key,
 	if (insert) {
 		rb_link_node(&insert->r_rb_node, parent, p);
 		rb_insert_color(&insert->r_rb_node, root);
-		atomic_inc(&insert->r_refcount);
+		refcount_inc(&insert->r_refcount);
 	}
 	return NULL;
 }
@@ -100,7 +100,7 @@ static void rds_destroy_mr(struct rds_mr *mr)
 	unsigned long flags;
 
 	rdsdebug("RDS: destroy mr key is %x refcnt %u\n",
-			mr->r_key, atomic_read(&mr->r_refcount));
+			mr->r_key, refcount_read(&mr->r_refcount));
 
 	if (test_and_set_bit(RDS_MR_DEAD, &mr->r_state))
 		return;
@@ -216,7 +216,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
 		goto out;
 	}
 
-	atomic_set(&mr->r_refcount, 1);
+	refcount_set(&mr->r_refcount, 1);
 	RB_CLEAR_NODE(&mr->r_rb_node);
 	mr->r_trans = rs->rs_transport;
 	mr->r_sock = rs;
@@ -300,7 +300,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
 
 	rdsdebug("RDS: get_mr key is %x\n", mr->r_key);
 	if (mr_ret) {
-		atomic_inc(&mr->r_refcount);
+		refcount_inc(&mr->r_refcount);
 		*mr_ret = mr;
 	}
 
@@ -738,7 +738,7 @@ int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
 	if (!mr)
 		err = -EINVAL;	/* invalid r_key */
 	else
-		atomic_inc(&mr->r_refcount);
+		refcount_inc(&mr->r_refcount);
 	spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
 
 	if (mr) {
diff --git a/net/rds/rds.h b/net/rds/rds.h
index ebbf909..3e410cd 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -8,6 +8,7 @@
 #include <linux/mutex.h>
 #include <linux/rds.h>
 #include <linux/rhashtable.h>
+#include <linux/refcount.h>
 
 #include "info.h"
 
@@ -252,7 +253,7 @@ struct rds_ext_header_rdma_dest {
 #define __RDS_EXTHDR_MAX	16 /* for now */
 
 struct rds_incoming {
-	atomic_t		i_refcount;
+	refcount_t		i_refcount;
 	struct list_head	i_item;
 	struct rds_connection	*i_conn;
 	struct rds_conn_path	*i_conn_path;
@@ -266,7 +267,7 @@ struct rds_incoming {
 
 struct rds_mr {
 	struct rb_node		r_rb_node;
-	atomic_t		r_refcount;
+	refcount_t		r_refcount;
 	u32			r_key;
 
 	/* A copy of the creation flags */
@@ -345,7 +346,7 @@ static inline u32 rds_rdma_cookie_offset(rds_rdma_cookie_t cookie)
 #define RDS_MSG_FLUSH		8
 
 struct rds_message {
-	atomic_t		m_refcount;
+	refcount_t		m_refcount;
 	struct list_head	m_sock_item;
 	struct list_head	m_conn_item;
 	struct rds_incoming	m_inc;
@@ -844,7 +845,7 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
 void __rds_put_mr_final(struct rds_mr *mr);
 static inline void rds_mr_put(struct rds_mr *mr)
 {
-	if (atomic_dec_and_test(&mr->r_refcount))
+	if (refcount_dec_and_test(&mr->r_refcount))
 		__rds_put_mr_final(mr);
 }
 
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 9d0666e..6858b71 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -43,7 +43,7 @@
 void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
 		  __be32 saddr)
 {
-	atomic_set(&inc->i_refcount, 1);
+	refcount_set(&inc->i_refcount, 1);
 	INIT_LIST_HEAD(&inc->i_item);
 	inc->i_conn = conn;
 	inc->i_saddr = saddr;
@@ -56,7 +56,7 @@ EXPORT_SYMBOL_GPL(rds_inc_init);
 void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp,
 		       __be32 saddr)
 {
-	atomic_set(&inc->i_refcount, 1);
+	refcount_set(&inc->i_refcount, 1);
 	INIT_LIST_HEAD(&inc->i_item);
 	inc->i_conn = cp->cp_conn;
 	inc->i_conn_path = cp;
@@ -69,14 +69,14 @@ EXPORT_SYMBOL_GPL(rds_inc_path_init);
 
 static void rds_inc_addref(struct rds_incoming *inc)
 {
-	rdsdebug("addref inc %p ref %d\n", inc, atomic_read(&inc->i_refcount));
-	atomic_inc(&inc->i_refcount);
+	rdsdebug("addref inc %p ref %d\n", inc, refcount_read(&inc->i_refcount));
+	refcount_inc(&inc->i_refcount);
 }
 
 void rds_inc_put(struct rds_incoming *inc)
 {
-	rdsdebug("put inc %p ref %d\n", inc, atomic_read(&inc->i_refcount));
-	if (atomic_dec_and_test(&inc->i_refcount)) {
+	rdsdebug("put inc %p ref %d\n", inc, refcount_read(&inc->i_refcount));
+	if (refcount_dec_and_test(&inc->i_refcount)) {
 		BUG_ON(!list_empty(&inc->i_item));
 
 		inc->i_conn->c_trans->inc_free(inc);
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c
index dcf4742..592e68b 100644
--- a/net/rds/tcp_send.c
+++ b/net/rds/tcp_send.c
@@ -208,7 +208,7 @@ void rds_tcp_write_space(struct sock *sk)
 	tc->t_last_seen_una = rds_tcp_snd_una(tc);
 	rds_send_path_drop_acked(cp, rds_tcp_snd_una(tc), rds_tcp_is_acked);
 
-	if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf)
+	if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf)
 		queue_delayed_work(rds_wq, &cp->cp_send_w, 0);
 
 out:
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 5f63f6d..c3990e9 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -56,7 +56,7 @@ static void rxrpc_sock_destructor(struct sock *);
  */
 static inline int rxrpc_writable(struct sock *sk)
 {
-	return atomic_read(&sk->sk_wmem_alloc) < (size_t) sk->sk_sndbuf;
+	return refcount_read(&sk->sk_wmem_alloc) < (size_t) sk->sk_sndbuf;
 }
 
 /*
@@ -651,7 +651,7 @@ static void rxrpc_sock_destructor(struct sock *sk)
 
 	rxrpc_purge_queue(&sk->sk_receive_queue);
 
-	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
 	WARN_ON(!sk_unhashed(sk));
 	WARN_ON(sk->sk_socket);
 
@@ -668,7 +668,7 @@ static int rxrpc_release_sock(struct sock *sk)
 {
 	struct rxrpc_sock *rx = rxrpc_sk(sk);
 
-	_enter("%p{%d,%d}", sk, sk->sk_state, atomic_read(&sk->sk_refcnt));
+	_enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
 
 	/* declare the socket closed for business */
 	sock_orphan(sk);
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index 67b02c4..b8985d0 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -27,7 +27,7 @@ void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
 	const void *here = __builtin_return_address(0);
 	int n = atomic_inc_return(select_skb_count(op));
-	trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 }
 
 /*
@@ -38,7 +38,7 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 	const void *here = __builtin_return_address(0);
 	if (skb) {
 		int n = atomic_read(select_skb_count(op));
-		trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 	}
 }
 
@@ -49,7 +49,7 @@ void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
 	const void *here = __builtin_return_address(0);
 	int n = atomic_inc_return(select_skb_count(op));
-	trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+	trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 	skb_get(skb);
 }
 
@@ -63,7 +63,7 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 		int n;
 		CHECK_SLAB_OKAY(&skb->users);
 		n = atomic_dec_return(select_skb_count(op));
-		trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 		kfree_skb(skb);
 	}
 }
@@ -78,7 +78,7 @@ void rxrpc_lose_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 		int n;
 		CHECK_SLAB_OKAY(&skb->users);
 		n = atomic_dec_return(select_skb_count(op));
-		trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+		trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
 		kfree_skb(skb);
 	}
 }
@@ -93,7 +93,7 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
 	while ((skb = skb_dequeue((list))) != NULL) {
 		int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged));
 		trace_rxrpc_skb(skb, rxrpc_skb_rx_purged,
-				atomic_read(&skb->users), n, here);
+				refcount_read(&skb->users), n, here);
 		kfree_skb(skb);
 	}
 }
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 41c80b6..47ac782 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -339,7 +339,7 @@ META_COLLECTOR(int_sk_refcnt)
 		*err = -1;
 		return;
 	}
-	dst->value = atomic_read(&skb->sk->sk_refcnt);
+	dst->value = refcount_read(&skb->sk->sk_refcnt);
 }
 
 META_COLLECTOR(int_sk_rcvbuf)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index d7b9342..5b49bb6 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -840,7 +840,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
 
 			old = dev_graft_qdisc(dev_queue, new);
 			if (new && i > 0)
-				atomic_inc(&new->refcnt);
+				refcount_inc(&new->refcnt);
 
 			if (!ingress)
 				qdisc_destroy(old);
@@ -851,7 +851,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
 			notify_and_destroy(net, skb, n, classid,
 					   dev->qdisc, new);
 			if (new && !new->ops->attach)
-				atomic_inc(&new->refcnt);
+				refcount_inc(&new->refcnt);
 			dev->qdisc = new ? : &noop_qdisc;
 
 			if (new && new->ops->attach)
@@ -1255,7 +1255,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
 				if (q == p ||
 				    (p && check_loop(q, p, 0)))
 					return -ELOOP;
-				atomic_inc(&q->refcnt);
+				refcount_inc(&q->refcnt);
 				goto graft;
 			} else {
 				if (!q)
@@ -1370,7 +1370,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
 	tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
 	tcm->tcm_parent = clid;
 	tcm->tcm_handle = q->handle;
-	tcm->tcm_info = atomic_read(&q->refcnt);
+	tcm->tcm_info = refcount_read(&q->refcnt);
 	if (nla_put_string(skb, TCA_KIND, q->ops->id))
 		goto nla_put_failure;
 	if (q->ops->dump && q->ops->dump(q, skb) < 0)
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 481e4f1..e99494e 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -490,7 +490,7 @@ static void sch_atm_dequeue(unsigned long data)
 			ATM_SKB(skb)->vcc = flow->vcc;
 			memcpy(skb_push(skb, flow->hdr_len), flow->hdr,
 			       flow->hdr_len);
-			atomic_add(skb->truesize,
+			refcount_add(skb->truesize,
 				   &sk_atm(flow->vcc)->sk_wmem_alloc);
 			/* atm.atm_options are already set by atm_tc_enqueue */
 			flow->vcc->send(flow->vcc, skb);
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 6eb9c8e..6a75581 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -633,7 +633,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 	sch->dequeue = ops->dequeue;
 	sch->dev_queue = dev_queue;
 	dev_hold(dev);
-	atomic_set(&sch->refcnt, 1);
+	refcount_set(&sch->refcnt, 1);
 
 	return sch;
 errout:
@@ -701,7 +701,7 @@ void qdisc_destroy(struct Qdisc *qdisc)
 	const struct Qdisc_ops  *ops = qdisc->ops;
 
 	if (qdisc->flags & TCQ_F_BUILTIN ||
-	    !atomic_dec_and_test(&qdisc->refcnt))
+	    !refcount_dec_and_test(&qdisc->refcnt))
 		return;
 
 #ifdef CONFIG_NET_SCHED
@@ -739,7 +739,7 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
 	spin_lock_bh(root_lock);
 
 	/* Prune old scheduler */
-	if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
+	if (oqdisc && refcount_read(&oqdisc->refcnt) <= 1)
 		qdisc_reset(oqdisc);
 
 	/* ... and graft new one */
@@ -785,7 +785,7 @@ static void attach_default_qdiscs(struct net_device *dev)
 	    dev->priv_flags & IFF_NO_QUEUE) {
 		netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);
 		dev->qdisc = txq->qdisc_sleeping;
-		atomic_inc(&dev->qdisc->refcnt);
+		refcount_inc(&dev->qdisc->refcnt);
 	} else {
 		qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT);
 		if (qdisc) {
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index d3cc30c..10ff17a 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -89,7 +89,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 	asoc->base.type = SCTP_EP_TYPE_ASSOCIATION;
 
 	/* Initialize the object handling fields.  */
-	atomic_set(&asoc->base.refcnt, 1);
+	refcount_set(&asoc->base.refcnt, 1);
 
 	/* Initialize the bind addr area.  */
 	sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
@@ -858,7 +858,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
 /* Hold a reference to an association. */
 void sctp_association_hold(struct sctp_association *asoc)
 {
-	atomic_inc(&asoc->base.refcnt);
+	refcount_inc(&asoc->base.refcnt);
 }
 
 /* Release a reference to an association and cleanup
@@ -866,7 +866,7 @@ void sctp_association_hold(struct sctp_association *asoc)
  */
 void sctp_association_put(struct sctp_association *asoc)
 {
-	if (atomic_dec_and_test(&asoc->base.refcnt))
+	if (refcount_dec_and_test(&asoc->base.refcnt))
 		sctp_association_destroy(asoc);
 }
 
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index f99d485..b6c98fe 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -63,7 +63,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key)
 	if (!key)
 		return;
 
-	if (atomic_dec_and_test(&key->refcnt)) {
+	if (refcount_dec_and_test(&key->refcnt)) {
 		kzfree(key);
 		SCTP_DBG_OBJCNT_DEC(keys);
 	}
@@ -84,7 +84,7 @@ static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp)
 		return NULL;
 
 	key->len = key_len;
-	atomic_set(&key->refcnt, 1);
+	refcount_set(&key->refcnt, 1);
 	SCTP_DBG_OBJCNT_INC(keys);
 
 	return key;
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 615f0dd..6c8087a 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -49,7 +49,7 @@
 /* Initialize datamsg from memory. */
 static void sctp_datamsg_init(struct sctp_datamsg *msg)
 {
-	atomic_set(&msg->refcnt, 1);
+	refcount_set(&msg->refcnt, 1);
 	msg->send_failed = 0;
 	msg->send_error = 0;
 	msg->can_delay = 1;
@@ -136,13 +136,13 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
 /* Hold a reference. */
 static void sctp_datamsg_hold(struct sctp_datamsg *msg)
 {
-	atomic_inc(&msg->refcnt);
+	refcount_inc(&msg->refcnt);
 }
 
 /* Release a reference. */
 void sctp_datamsg_put(struct sctp_datamsg *msg)
 {
-	if (atomic_dec_and_test(&msg->refcnt))
+	if (refcount_dec_and_test(&msg->refcnt))
 		sctp_datamsg_destroy(msg);
 }
 
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 410ddc1..019fe78 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -113,7 +113,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
 	ep->base.type = SCTP_EP_TYPE_SOCKET;
 
 	/* Initialize the basic object fields. */
-	atomic_set(&ep->base.refcnt, 1);
+	refcount_set(&ep->base.refcnt, 1);
 	ep->base.dead = false;
 
 	/* Create an input queue.  */
@@ -284,7 +284,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
 /* Hold a reference to an endpoint. */
 void sctp_endpoint_hold(struct sctp_endpoint *ep)
 {
-	atomic_inc(&ep->base.refcnt);
+	refcount_inc(&ep->base.refcnt);
 }
 
 /* Release a reference to an endpoint and clean up if there are
@@ -292,7 +292,7 @@ void sctp_endpoint_hold(struct sctp_endpoint *ep)
  */
 void sctp_endpoint_put(struct sctp_endpoint *ep)
 {
-	if (atomic_dec_and_test(&ep->base.refcnt))
+	if (refcount_dec_and_test(&ep->base.refcnt))
 		sctp_endpoint_destroy(ep);
 }
 
diff --git a/net/sctp/output.c b/net/sctp/output.c
index f5320a8..53210b5 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -396,7 +396,7 @@ static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
 	 * therefore only reserve a single byte to keep socket around until
 	 * the packet has been transmitted.
 	 */
-	atomic_inc(&sk->sk_wmem_alloc);
+	refcount_inc(&sk->sk_wmem_alloc);
 }
 
 static int sctp_packet_pack(struct sctp_packet *packet,
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index e540826..e8ae4a1 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1081,7 +1081,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
 				 sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) :
 				 "illegal chunk", ntohl(chunk->subh.data_hdr->tsn),
 				 chunk->skb ? chunk->skb->head : NULL, chunk->skb ?
-				 atomic_read(&chunk->skb->users) : -1);
+				 refcount_read(&chunk->skb->users) : -1);
 
 			/* Add the chunk to the packet.  */
 			status = sctp_packet_transmit_chunk(packet, chunk, 0, gfp);
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 206377f..25cd840 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -365,7 +365,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
 		assoc->c.sinit_num_ostreams, assoc->max_retrans,
 		assoc->init_retries, assoc->shutdown_retries,
 		assoc->rtx_data_chunks,
-		atomic_read(&sk->sk_wmem_alloc),
+		refcount_read(&sk->sk_wmem_alloc),
 		sk->sk_wmem_queued,
 		sk->sk_sndbuf,
 		sk->sk_rcvbuf);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 9e9690b..7eac4e9 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1336,7 +1336,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
 	INIT_LIST_HEAD(&retval->transmitted_list);
 	INIT_LIST_HEAD(&retval->frag_list);
 	SCTP_DBG_OBJCNT_INC(chunk);
-	atomic_set(&retval->refcnt, 1);
+	refcount_set(&retval->refcnt, 1);
 
 nodata:
 	return retval;
@@ -1449,13 +1449,13 @@ void sctp_chunk_free(struct sctp_chunk *chunk)
 /* Grab a reference to the chunk. */
 void sctp_chunk_hold(struct sctp_chunk *ch)
 {
-	atomic_inc(&ch->refcnt);
+	refcount_inc(&ch->refcnt);
 }
 
 /* Release a reference to the chunk. */
 void sctp_chunk_put(struct sctp_chunk *ch)
 {
-	if (atomic_dec_and_test(&ch->refcnt))
+	if (refcount_dec_and_test(&ch->refcnt))
 		sctp_chunk_destroy(ch);
 }
 
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 318c678..73a545b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -163,7 +163,7 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
 				sizeof(struct sk_buff) +
 				sizeof(struct sctp_chunk);
 
-	atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
+	refcount_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
 	sk->sk_wmem_queued += chunk->skb->truesize;
 	sk_mem_charge(sk, chunk->skb->truesize);
 }
@@ -7237,7 +7237,7 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
 		if (flags & MSG_PEEK) {
 			skb = skb_peek(&sk->sk_receive_queue);
 			if (skb)
-				atomic_inc(&skb->users);
+				refcount_inc(&skb->users);
 		} else {
 			skb = __skb_dequeue(&sk->sk_receive_queue);
 		}
@@ -7355,7 +7355,7 @@ static void sctp_wfree(struct sk_buff *skb)
 				sizeof(struct sk_buff) +
 				sizeof(struct sctp_chunk);
 
-	atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
+	WARN_ON(refcount_sub_and_test(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc));
 
 	/*
 	 * This undoes what is done via sctp_set_owner_w and sk_mem_charge
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index a1652ab..a082cd2 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -97,7 +97,7 @@ static struct sctp_transport *sctp_transport_init(struct net *net,
 	/* Initialize the 64-bit random nonce sent with heartbeat. */
 	get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
 
-	atomic_set(&peer->refcnt, 1);
+	refcount_set(&peer->refcnt, 1);
 
 	return peer;
 }
@@ -167,7 +167,7 @@ static void sctp_transport_destroy_rcu(struct rcu_head *head)
  */
 static void sctp_transport_destroy(struct sctp_transport *transport)
 {
-	if (unlikely(atomic_read(&transport->refcnt))) {
+	if (unlikely(refcount_read(&transport->refcnt))) {
 		WARN(1, "Attempt to destroy undead transport %p!\n", transport);
 		return;
 	}
@@ -303,7 +303,7 @@ void sctp_transport_route(struct sctp_transport *transport,
 /* Hold a reference to a transport.  */
 int sctp_transport_hold(struct sctp_transport *transport)
 {
-	return atomic_add_unless(&transport->refcnt, 1, 0);
+	return refcount_inc_not_zero(&transport->refcnt);
 }
 
 /* Release a reference to a transport and clean up
@@ -311,7 +311,7 @@ int sctp_transport_hold(struct sctp_transport *transport)
  */
 void sctp_transport_put(struct sctp_transport *transport)
 {
-	if (atomic_dec_and_test(&transport->refcnt))
+	if (refcount_dec_and_test(&transport->refcnt))
 		sctp_transport_destroy(transport);
 }
 
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 2bff63a..b6439b9 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -310,7 +310,7 @@ rpcauth_unhash_cred(struct rpc_cred *cred)
 
 	cache_lock = &cred->cr_auth->au_credcache->lock;
 	spin_lock(cache_lock);
-	ret = atomic_read(&cred->cr_count) == 0;
+	ret = refcount_read(&cred->cr_count) == 0;
 	if (ret)
 		rpcauth_unhash_cred_locked(cred);
 	spin_unlock(cache_lock);
@@ -470,12 +470,12 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 		list_del_init(&cred->cr_lru);
 		number_cred_unused--;
 		freed++;
-		if (atomic_read(&cred->cr_count) != 0)
+		if (refcount_read(&cred->cr_count) != 0)
 			continue;
 
 		cache_lock = &cred->cr_auth->au_credcache->lock;
 		spin_lock(cache_lock);
-		if (atomic_read(&cred->cr_count) == 0) {
+		if (refcount_read(&cred->cr_count) == 0) {
 			get_rpccred(cred);
 			list_add_tail(&cred->cr_lru, free);
 			rpcauth_unhash_cred_locked(cred);
@@ -642,7 +642,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
 {
 	INIT_HLIST_NODE(&cred->cr_hash);
 	INIT_LIST_HEAD(&cred->cr_lru);
-	atomic_set(&cred->cr_count, 1);
+	refcount_set(&cred->cr_count, 1);
 	cred->cr_auth = auth;
 	cred->cr_ops = ops;
 	cred->cr_expire = jiffies;
@@ -715,12 +715,12 @@ put_rpccred(struct rpc_cred *cred)
 		return;
 	/* Fast path for unhashed credentials */
 	if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
-		if (atomic_dec_and_test(&cred->cr_count))
+		if (refcount_dec_and_test(&cred->cr_count))
 			cred->cr_ops->crdestroy(cred);
 		return;
 	}
 
-	if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+	if (!refcount_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
 		return;
 	if (!list_empty(&cred->cr_lru)) {
 		number_cred_unused--;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index cdeb1d8..59b5860 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -52,6 +52,7 @@
 #include <linux/sunrpc/gss_api.h>
 #include <linux/uaccess.h>
 #include <linux/hashtable.h>
+#include <linux/refcount.h>
 
 #include "../netns.h"
 
@@ -117,14 +118,14 @@ static const struct rpc_pipe_ops gss_upcall_ops_v1;
 static inline struct gss_cl_ctx *
 gss_get_ctx(struct gss_cl_ctx *ctx)
 {
-	atomic_inc(&ctx->count);
+	refcount_inc(&ctx->count);
 	return ctx;
 }
 
 static inline void
 gss_put_ctx(struct gss_cl_ctx *ctx)
 {
-	if (atomic_dec_and_test(&ctx->count))
+	if (refcount_dec_and_test(&ctx->count))
 		gss_free_ctx(ctx);
 }
 
@@ -200,7 +201,7 @@ gss_alloc_context(void)
 		ctx->gc_proc = RPC_GSS_PROC_DATA;
 		ctx->gc_seq = 1;	/* NetApp 6.4R1 doesn't accept seq. no. 0 */
 		spin_lock_init(&ctx->gc_seq_lock);
-		atomic_set(&ctx->count,1);
+		refcount_set(&ctx->count,1);
 	}
 	return ctx;
 }
@@ -287,7 +288,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
 #define UPCALL_BUF_LEN 128
 
 struct gss_upcall_msg {
-	atomic_t count;
+	refcount_t count;
 	kuid_t	uid;
 	struct rpc_pipe_msg msg;
 	struct list_head list;
@@ -328,7 +329,7 @@ static void
 gss_release_msg(struct gss_upcall_msg *gss_msg)
 {
 	struct net *net = gss_msg->auth->net;
-	if (!atomic_dec_and_test(&gss_msg->count))
+	if (!refcount_dec_and_test(&gss_msg->count))
 		return;
 	put_pipe_version(net);
 	BUG_ON(!list_empty(&gss_msg->list));
@@ -348,7 +349,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth
 			continue;
 		if (auth && pos->auth->service != auth->service)
 			continue;
-		atomic_inc(&pos->count);
+		refcount_inc(&pos->count);
 		dprintk("RPC:       %s found msg %p\n", __func__, pos);
 		return pos;
 	}
@@ -369,7 +370,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg)
 	spin_lock(&pipe->lock);
 	old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth);
 	if (old == NULL) {
-		atomic_inc(&gss_msg->count);
+		refcount_inc(&gss_msg->count);
 		list_add(&gss_msg->list, &pipe->in_downcall);
 	} else
 		gss_msg = old;
@@ -383,7 +384,7 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
 	list_del_init(&gss_msg->list);
 	rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
 	wake_up_all(&gss_msg->waitqueue);
-	atomic_dec(&gss_msg->count);
+	WARN_ON(refcount_dec_and_test(&gss_msg->count));
 }
 
 static void
@@ -506,7 +507,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
 	INIT_LIST_HEAD(&gss_msg->list);
 	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
 	init_waitqueue_head(&gss_msg->waitqueue);
-	atomic_set(&gss_msg->count, 1);
+	refcount_set(&gss_msg->count, 1);
 	gss_msg->uid = uid;
 	gss_msg->auth = gss_auth;
 	switch (vers) {
@@ -542,11 +543,11 @@ gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred)
 	gss_msg = gss_add_msg(gss_new);
 	if (gss_msg == gss_new) {
 		int res;
-		atomic_inc(&gss_msg->count);
+		refcount_inc(&gss_msg->count);
 		res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg);
 		if (res) {
 			gss_unhash_msg(gss_new);
-			atomic_dec(&gss_msg->count);
+			refcount_dec(&gss_msg->count);
 			gss_release_msg(gss_new);
 			gss_msg = ERR_PTR(res);
 		}
@@ -595,7 +596,7 @@ gss_refresh_upcall(struct rpc_task *task)
 		task->tk_timeout = 0;
 		gss_cred->gc_upcall = gss_msg;
 		/* gss_upcall_callback will release the reference to gss_upcall_msg */
-		atomic_inc(&gss_msg->count);
+		refcount_inc(&gss_msg->count);
 		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
 	} else {
 		gss_handle_downcall_result(gss_cred, gss_msg);
@@ -815,7 +816,7 @@ gss_pipe_release(struct inode *inode)
 		if (!list_empty(&gss_msg->msg.list))
 			continue;
 		gss_msg->msg.errno = -EPIPE;
-		atomic_inc(&gss_msg->count);
+		refcount_inc(&gss_msg->count);
 		__gss_unhash_msg(gss_msg);
 		spin_unlock(&pipe->lock);
 		gss_release_msg(gss_msg);
@@ -834,7 +835,7 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
 	if (msg->errno < 0) {
 		dprintk("RPC:       %s releasing msg %p\n",
 			__func__, gss_msg);
-		atomic_inc(&gss_msg->count);
+		refcount_inc(&gss_msg->count);
 		gss_unhash_msg(gss_msg);
 		if (msg->errno == -ETIMEDOUT)
 			warn_gssd();
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 800caaa..2189667 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2332,7 +2332,7 @@ static void tipc_sk_remove(struct tipc_sock *tsk)
 	struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id);
 
 	if (!rhashtable_remove_fast(&tn->sk_rht, &tsk->node, tsk_rht_params)) {
-		WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
+		WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
 		__sock_put(sk);
 	}
 }
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 127656e..3a3223c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -211,7 +211,7 @@ EXPORT_SYMBOL_GPL(unix_peer_get);
 
 static inline void unix_release_addr(struct unix_address *addr)
 {
-	if (atomic_dec_and_test(&addr->refcnt))
+	if (refcount_dec_and_test(&addr->refcnt))
 		kfree(addr);
 }
 
@@ -441,7 +441,7 @@ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
 static int unix_writable(const struct sock *sk)
 {
 	return sk->sk_state != TCP_LISTEN &&
-	       (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
+	       (refcount_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
 }
 
 static void unix_write_space(struct sock *sk)
@@ -486,7 +486,7 @@ static void unix_sock_destructor(struct sock *sk)
 
 	skb_queue_purge(&sk->sk_receive_queue);
 
-	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
+	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
 	WARN_ON(!sk_unhashed(sk));
 	WARN_ON(sk->sk_socket);
 	if (!sock_flag(sk, SOCK_DEAD)) {
@@ -863,7 +863,7 @@ static int unix_autobind(struct socket *sock)
 		goto out;
 
 	addr->name->sun_family = AF_UNIX;
-	atomic_set(&addr->refcnt, 1);
+	refcount_set(&addr->refcnt, 1);
 
 retry:
 	addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
@@ -1026,7 +1026,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	memcpy(addr->name, sunaddr, addr_len);
 	addr->len = addr_len;
 	addr->hash = hash ^ sk->sk_type;
-	atomic_set(&addr->refcnt, 1);
+	refcount_set(&addr->refcnt, 1);
 
 	if (sun_path[0]) {
 		struct path path;
@@ -1324,7 +1324,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 
 	/* copy address information from listening to new sock*/
 	if (otheru->addr) {
-		atomic_inc(&otheru->addr->refcnt);
+		refcount_inc(&otheru->addr->refcnt);
 		newu->addr = otheru->addr;
 	}
 	if (otheru->path.dentry) {
@@ -2021,7 +2021,7 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page,
 	skb->len += size;
 	skb->data_len += size;
 	skb->truesize += size;
-	atomic_add(size, &sk->sk_wmem_alloc);
+	refcount_add(size, &sk->sk_wmem_alloc);
 
 	if (newskb) {
 		err = unix_scm_to_skb(&scm, skb, false);
@@ -2795,7 +2795,7 @@ static int unix_seq_show(struct seq_file *seq, void *v)
 
 		seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
 			s,
-			atomic_read(&s->sk_refcnt),
+			refcount_read(&s->sk_refcnt),
 			0,
 			s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
 			s->sk_type,
diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c
index 4596115..472dce0 100644
--- a/net/wireless/lib80211.c
+++ b/net/wireless/lib80211.c
@@ -92,7 +92,7 @@ static void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info,
 
 	spin_lock_irqsave(info->lock, flags);
 	list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) {
-		if (atomic_read(&entry->refcnt) != 0 && !force)
+		if (refcount_read(&entry->refcnt) != 0 && !force)
 			continue;
 
 		list_del(&entry->list);
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index bcaa180..e0cd04d 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -266,7 +266,7 @@ void x25_link_device_up(struct net_device *dev)
 				       X25_MASK_PACKET_SIZE |
 				       X25_MASK_WINDOW_SIZE;
 	nb->t20      = sysctl_x25_restart_request_timeout;
-	atomic_set(&nb->refcnt, 1);
+	refcount_set(&nb->refcnt, 1);
 
 	write_lock_bh(&x25_neigh_list_lock);
 	list_add(&nb->node, &x25_neigh_list);
diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c
index 277c8d2..b85b889 100644
--- a/net/x25/x25_route.c
+++ b/net/x25/x25_route.c
@@ -55,7 +55,7 @@ static int x25_add_route(struct x25_address *address, unsigned int sigdigits,
 
 	rt->sigdigits = sigdigits;
 	rt->dev       = dev;
-	atomic_set(&rt->refcnt, 1);
+	refcount_set(&rt->refcnt, 1);
 
 	list_add(&rt->node, &x25_route_list);
 	rc = 0;
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 6e3f025..25f9939 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -118,7 +118,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
 		for (i = 0; i < sp->len; i++)
 			xfrm_state_hold(sp->xvec[i]);
 	}
-	atomic_set(&sp->refcnt, 1);
+	refcount_set(&sp->refcnt, 1);
 	return sp;
 }
 EXPORT_SYMBOL(secpath_dup);
@@ -219,7 +219,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 	}
 
 	/* Allocate new secpath or COW existing one. */
-	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
+	if (!skb->sp || refcount_read(&skb->sp->refcnt) != 1) {
 		struct sec_path *sp;
 
 		sp = secpath_dup(skb->sp);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 177e208..bc39de5 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -62,7 +62,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
 
 static inline bool xfrm_pol_hold_rcu(struct xfrm_policy *policy)
 {
-	return atomic_inc_not_zero(&policy->refcnt);
+	return refcount_inc_not_zero(&policy->refcnt);
 }
 
 static inline bool
@@ -297,7 +297,7 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
 		INIT_HLIST_NODE(&policy->bydst);
 		INIT_HLIST_NODE(&policy->byidx);
 		rwlock_init(&policy->lock);
-		atomic_set(&policy->refcnt, 1);
+		refcount_set(&policy->refcnt, 1);
 		skb_queue_head_init(&policy->polq.hold_queue);
 		setup_timer(&policy->timer, xfrm_policy_timer,
 				(unsigned long)policy);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 64e3c82..e9732c8 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -48,7 +48,7 @@ static HLIST_HEAD(xfrm_state_gc_list);
 
 static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x)
 {
-	return atomic_inc_not_zero(&x->refcnt);
+	return refcount_inc_not_zero(&x->refcnt);
 }
 
 static inline unsigned int xfrm_dst_hash(struct net *net,
@@ -485,7 +485,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
 
 	if (x) {
 		write_pnet(&x->xs_net, net);
-		atomic_set(&x->refcnt, 1);
+		refcount_set(&x->refcnt, 1);
 		atomic_set(&x->tunnel_users, 0);
 		INIT_LIST_HEAD(&x->km.all);
 		INIT_HLIST_NODE(&x->bydst);
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 10/18] fs: convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (8 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 09/18] net: " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 11/18] security: " Elena Reshetova
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/powerpc/platforms/cell/spufs/file.c        |  2 +-
 drivers/staging/lustre/lustre/llite/llite_lib.c |  2 +-
 fs/afs/cell.c                                   | 20 +++---
 fs/afs/internal.h                               | 18 ++---
 fs/afs/proc.c                                   |  6 +-
 fs/afs/server.c                                 | 20 +++---
 fs/afs/vlocation.c                              | 16 ++---
 fs/afs/volume.c                                 |  6 +-
 fs/btrfs/backref.c                              |  2 +-
 fs/btrfs/compression.c                          | 18 ++---
 fs/btrfs/ctree.c                                |  2 +-
 fs/btrfs/ctree.h                                |  7 +-
 fs/btrfs/delayed-inode.c                        | 46 ++++++-------
 fs/btrfs/delayed-inode.h                        |  5 +-
 fs/btrfs/delayed-ref.c                          |  8 +--
 fs/btrfs/delayed-ref.h                          |  8 ++-
 fs/btrfs/disk-io.c                              | 14 ++--
 fs/btrfs/disk-io.h                              |  4 +-
 fs/btrfs/extent-tree.c                          | 28 ++++----
 fs/btrfs/extent_io.c                            | 91 ++++++++++++-------------
 fs/btrfs/extent_io.h                            |  9 +--
 fs/btrfs/extent_map.c                           | 10 +--
 fs/btrfs/extent_map.h                           |  3 +-
 fs/btrfs/free-space-cache.c                     |  4 +-
 fs/btrfs/ordered-data.c                         | 20 +++---
 fs/btrfs/ordered-data.h                         |  2 +-
 fs/btrfs/raid56.c                               | 19 +++---
 fs/btrfs/scrub.c                                | 42 ++++++------
 fs/btrfs/transaction.c                          | 20 +++---
 fs/btrfs/transaction.h                          |  3 +-
 fs/btrfs/tree-log.c                             |  2 +-
 fs/btrfs/volumes.c                              | 10 +--
 fs/btrfs/volumes.h                              |  2 +-
 fs/cachefiles/bind.c                            |  2 +-
 fs/cachefiles/interface.c                       | 18 ++---
 fs/cachefiles/internal.h                        |  3 +-
 fs/cachefiles/namei.c                           |  2 +-
 fs/cachefiles/rdwr.c                            |  2 +-
 fs/ceph/caps.c                                  |  4 +-
 fs/ceph/file.c                                  |  7 +-
 fs/ceph/mds_client.c                            | 20 +++---
 fs/ceph/mds_client.h                            |  5 +-
 fs/ceph/snap.c                                  |  2 +-
 fs/ceph/super.h                                 |  5 +-
 fs/cifs/cifsfs.c                                |  2 +-
 fs/cifs/cifsglob.h                              |  5 +-
 fs/cifs/connect.c                               |  4 +-
 fs/cifs/inode.c                                 |  2 +-
 fs/devpts/inode.c                               |  2 +-
 fs/f2fs/acl.c                                   |  2 +-
 fs/fscache/cache.c                              |  8 +--
 fs/fscache/operation.c                          | 38 +++++------
 fs/fscache/page.c                               |  2 +-
 fs/fuse/dev.c                                   | 10 +--
 fs/fuse/file.c                                  |  8 +--
 fs/fuse/fuse_i.h                                |  7 +-
 fs/fuse/inode.c                                 |  6 +-
 fs/gfs2/super.c                                 |  2 +-
 fs/hfs/bnode.c                                  | 14 ++--
 fs/hfs/btree.c                                  |  4 +-
 fs/hfs/btree.h                                  |  3 +-
 fs/hfs/inode.c                                  |  4 +-
 fs/hfsplus/bnode.c                              | 14 ++--
 fs/hfsplus/btree.c                              |  4 +-
 fs/hfsplus/dir.c                                |  4 +-
 fs/hfsplus/hfsplus_fs.h                         |  5 +-
 fs/hfsplus/inode.c                              | 10 +--
 fs/hfsplus/super.c                              |  2 +-
 fs/inode.c                                      |  3 +-
 fs/kernfs/dir.c                                 | 10 +--
 fs/kernfs/mount.c                               |  2 +-
 fs/lockd/clntproc.c                             | 14 ++--
 fs/lockd/host.c                                 | 16 ++---
 fs/lockd/mon.c                                  | 14 ++--
 fs/lockd/svcproc.c                              |  2 +-
 fs/mbcache.c                                    | 16 ++---
 fs/mount.h                                      |  5 +-
 fs/namespace.c                                  |  8 +--
 fs/ncpfs/sock.c                                 |  9 +--
 fs/nfs/cache_lib.c                              |  6 +-
 fs/nfs/cache_lib.h                              |  2 +-
 fs/nfs/client.c                                 | 12 ++--
 fs/nfs/dir.c                                    |  8 +--
 fs/nfs/filelayout/filelayout.c                  | 12 ++--
 fs/nfs/flexfilelayout/flexfilelayout.c          | 20 +++---
 fs/nfs/flexfilelayout/flexfilelayout.h          |  3 +-
 fs/nfs/inode.c                                  | 12 ++--
 fs/nfs/nfs4_fs.h                                |  7 +-
 fs/nfs/nfs4client.c                             | 16 ++---
 fs/nfs/nfs4proc.c                               | 26 +++----
 fs/nfs/nfs4state.c                              | 36 +++++-----
 fs/nfs/pnfs.c                                   | 32 ++++-----
 fs/nfs/pnfs.h                                   |  9 +--
 fs/nfs/pnfs_nfs.c                               | 10 +--
 fs/nfs/super.c                                  |  4 +-
 fs/nfsd/nfs4layouts.c                           |  4 +-
 fs/nfsd/nfs4state.c                             | 72 +++++++++----------
 fs/nfsd/state.h                                 | 15 ++--
 fs/nilfs2/the_nilfs.c                           |  8 +--
 fs/nilfs2/the_nilfs.h                           |  5 +-
 fs/notify/group.c                               |  6 +-
 fs/notify/inotify/inotify_user.c                |  4 +-
 fs/notify/mark.c                                |  6 +-
 fs/ntfs/aops.c                                  |  2 +-
 fs/ntfs/inode.c                                 |  6 +-
 fs/ntfs/inode.h                                 |  4 +-
 fs/ntfs/mft.c                                   | 36 +++++-----
 fs/ocfs2/filecheck.c                            | 17 +++--
 fs/posix_acl.c                                  |  6 +-
 fs/proc/generic.c                               |  4 +-
 fs/proc/internal.h                              |  5 +-
 fs/proc/root.c                                  |  2 +-
 fs/super.c                                      | 10 +--
 fs/userfaultfd.c                                |  9 +--
 fs/xfs/xfs_bmap_item.c                          |  4 +-
 fs/xfs/xfs_bmap_item.h                          |  4 +-
 fs/xfs/xfs_buf.c                                | 34 ++++-----
 fs/xfs/xfs_buf.h                                |  7 +-
 fs/xfs/xfs_buf_item.c                           | 16 ++---
 fs/xfs/xfs_buf_item.h                           |  4 +-
 fs/xfs/xfs_extfree_item.c                       |  4 +-
 fs/xfs/xfs_extfree_item.h                       |  4 +-
 fs/xfs/xfs_inode.h                              |  2 +-
 fs/xfs/xfs_log.c                                | 37 +++++-----
 fs/xfs/xfs_log_priv.h                           |  6 +-
 fs/xfs/xfs_refcount_item.c                      |  4 +-
 fs/xfs/xfs_refcount_item.h                      |  4 +-
 fs/xfs/xfs_rmap_item.c                          |  4 +-
 fs/xfs/xfs_rmap_item.h                          |  4 +-
 fs/xfs/xfs_trace.h                              | 10 +--
 fs/xfs/xfs_trans_buf.c                          | 32 ++++-----
 include/linux/fs.h                              |  3 +-
 include/linux/fscache-cache.h                   |  7 +-
 include/linux/fsnotify_backend.h                |  5 +-
 include/linux/kernfs.h                          |  3 +-
 include/linux/lockd/lockd.h                     |  9 +--
 include/linux/mbcache.h                         |  6 +-
 include/linux/nfs_fs.h                          |  3 +-
 include/linux/nfs_fs_sb.h                       |  5 +-
 include/linux/posix_acl.h                       |  7 +-
 include/trace/events/btrfs.h                    |  6 +-
 ipc/msgutil.c                                   |  2 +-
 142 files changed, 760 insertions(+), 712 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index a35e2c2..01218a7 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1492,7 +1492,7 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
 	if (ctx->owner != current->mm)
 		return -EINVAL;
 
-	if (atomic_read(&inode->i_count) != 1)
+	if (refcount_read(&inode->i_count) != 1)
 		return -EBUSY;
 
 	mutex_lock(&ctx->mapping_lock);
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index 25f5aed..3b8aff9 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -2000,7 +2000,7 @@ void ll_umount_begin(struct super_block *sb)
 	struct obd_ioctl_data *ioc_data;
 
 	CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb,
-	       sb->s_count, atomic_read(&sb->s_active));
+	       sb->s_count, refcount_read(&sb->s_active));
 
 	obd = class_exp2obd(sbi->ll_md_exp);
 	if (!obd) {
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index ca0a3cf..e0440c0 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -60,7 +60,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, unsigned namelen,
 	memcpy(cell->name, name, namelen);
 	cell->name[namelen] = 0;
 
-	atomic_set(&cell->usage, 1);
+	refcount_set(&cell->usage, 1);
 	INIT_LIST_HEAD(&cell->link);
 	rwlock_init(&cell->servers_lock);
 	INIT_LIST_HEAD(&cell->servers);
@@ -345,15 +345,15 @@ void afs_put_cell(struct afs_cell *cell)
 	if (!cell)
 		return;
 
-	_enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
+	_enter("%p{%d,%s}", cell, refcount_read(&cell->usage), cell->name);
 
-	ASSERTCMP(atomic_read(&cell->usage), >, 0);
+	ASSERTCMP(refcount_read(&cell->usage), >, 0);
 
 	/* to prevent a race, the decrement and the dequeue must be effectively
 	 * atomic */
 	write_lock(&afs_cells_lock);
 
-	if (likely(!atomic_dec_and_test(&cell->usage))) {
+	if (likely(!refcount_dec_and_test(&cell->usage))) {
 		write_unlock(&afs_cells_lock);
 		_leave("");
 		return;
@@ -376,20 +376,20 @@ void afs_put_cell(struct afs_cell *cell)
  */
 static void afs_cell_destroy(struct afs_cell *cell)
 {
-	_enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
+	_enter("%p{%d,%s}", cell, refcount_read(&cell->usage), cell->name);
 
-	ASSERTCMP(atomic_read(&cell->usage), >=, 0);
+	ASSERTCMP(refcount_read(&cell->usage), >=, 0);
 	ASSERT(list_empty(&cell->link));
 
 	/* wait for everyone to stop using the cell */
-	if (atomic_read(&cell->usage) > 0) {
+	if (refcount_read(&cell->usage) > 0) {
 		DECLARE_WAITQUEUE(myself, current);
 
 		_debug("wait for cell %s", cell->name);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		add_wait_queue(&afs_cells_freeable_wq, &myself);
 
-		while (atomic_read(&cell->usage) > 0) {
+		while (refcount_read(&cell->usage) > 0) {
 			schedule();
 			set_current_state(TASK_UNINTERRUPTIBLE);
 		}
@@ -399,7 +399,7 @@ static void afs_cell_destroy(struct afs_cell *cell)
 	}
 
 	_debug("cell dead");
-	ASSERTCMP(atomic_read(&cell->usage), ==, 0);
+	ASSERTCMP(refcount_read(&cell->usage), ==, 0);
 	ASSERT(list_empty(&cell->servers));
 	ASSERT(list_empty(&cell->vl_list));
 
@@ -448,7 +448,7 @@ void afs_cell_purge(void)
 
 		if (cell) {
 			_debug("PURGING CELL %s (%d)",
-			       cell->name, atomic_read(&cell->usage));
+			       cell->name, refcount_read(&cell->usage));
 
 			/* now the cell should be left with no references */
 			afs_cell_destroy(cell);
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 535a38d..0699072 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -187,7 +187,7 @@ struct afs_cache_cell {
  * AFS cell record
  */
 struct afs_cell {
-	atomic_t		usage;
+	refcount_t		usage;
 	struct list_head	link;		/* main cell list link */
 	struct key		*anonymous_key;	/* anonymous user key for this cell */
 	struct list_head	proc_link;	/* /proc cell list link */
@@ -241,7 +241,7 @@ struct afs_cache_vhash {
  * AFS volume location record
  */
 struct afs_vlocation {
-	atomic_t		usage;
+	refcount_t		usage;
 	time_t			time_of_death;	/* time at which put reduced usage to 0 */
 	struct list_head	link;		/* link in cell volume location list */
 	struct list_head	grave;		/* link in master graveyard list */
@@ -265,7 +265,7 @@ struct afs_vlocation {
  * AFS fileserver record
  */
 struct afs_server {
-	atomic_t		usage;
+	refcount_t		usage;
 	time_t			time_of_death;	/* time at which put reduced usage to 0 */
 	struct in_addr		addr;		/* server address */
 	struct afs_cell		*cell;		/* cell in which server resides */
@@ -297,7 +297,7 @@ struct afs_server {
  * AFS volume access record
  */
 struct afs_volume {
-	atomic_t		usage;
+	refcount_t		usage;
 	struct afs_cell		*cell;		/* cell to which belongs (unrefd ptr) */
 	struct afs_vlocation	*vlocation;	/* volume location */
 #ifdef CONFIG_AFS_FSCACHE
@@ -464,7 +464,7 @@ extern void afs_callback_update_kill(void);
 extern struct rw_semaphore afs_proc_cells_sem;
 extern struct list_head afs_proc_cells;
 
-#define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0)
+#define afs_get_cell(C) do { refcount_inc(&(C)->usage); } while(0)
 extern int afs_cell_init(char *);
 extern struct afs_cell *afs_cell_create(const char *, unsigned, char *, bool);
 extern struct afs_cell *afs_cell_lookup(const char *, unsigned, bool);
@@ -636,8 +636,8 @@ extern spinlock_t afs_server_peer_lock;
 
 #define afs_get_server(S)					\
 do {								\
-	_debug("GET SERVER %d", atomic_read(&(S)->usage));	\
-	atomic_inc(&(S)->usage);				\
+	_debug("GET SERVER %d", refcount_read(&(S)->usage));	\
+	refcount_inc(&(S)->usage);				\
 } while(0)
 
 extern struct afs_server *afs_lookup_server(struct afs_cell *,
@@ -672,7 +672,7 @@ extern int afs_vl_get_entry_by_id(struct in_addr *, struct key *,
 /*
  * vlocation.c
  */
-#define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0)
+#define afs_get_vlocation(V) do { refcount_inc(&(V)->usage); } while(0)
 
 extern int __init afs_vlocation_update_init(void);
 extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *,
@@ -725,7 +725,7 @@ extern int afs_vnode_release_lock(struct afs_vnode *, struct key *);
 /*
  * volume.c
  */
-#define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0)
+#define afs_get_volume(V) do { refcount_inc(&(V)->usage); } while(0)
 
 extern void afs_put_volume(struct afs_volume *);
 extern struct afs_volume *afs_volume_lookup(struct afs_mount_params *);
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 35efb9a..57bf6fb 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -212,7 +212,7 @@ static int afs_proc_cells_show(struct seq_file *m, void *v)
 
 	/* display one cell per line on subsequent lines */
 	seq_printf(m, "%3d %s\n",
-		   atomic_read(&cell->usage), cell->name);
+		   refcount_read(&cell->usage), cell->name);
 	return 0;
 }
 
@@ -461,7 +461,7 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
 
 	/* display one cell per line on subsequent lines */
 	seq_printf(m, "%3d %s %08x %08x %08x %s\n",
-		   atomic_read(&vlocation->usage),
+		   refcount_read(&vlocation->usage),
 		   afs_vlocation_states[vlocation->state],
 		   vlocation->vldb.vid[0],
 		   vlocation->vldb.vid[1],
@@ -647,7 +647,7 @@ static int afs_proc_cell_servers_show(struct seq_file *m, void *v)
 	/* display one cell per line on subsequent lines */
 	sprintf(ipaddr, "%pI4", &server->addr);
 	seq_printf(m, "%3d %-15.15s %5d\n",
-		   atomic_read(&server->usage), ipaddr, server->fs_state);
+		   refcount_read(&server->usage), ipaddr, server->fs_state);
 
 	return 0;
 }
diff --git a/fs/afs/server.c b/fs/afs/server.c
index d4066ab..958f63b 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -75,7 +75,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell,
 
 	server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
 	if (server) {
-		atomic_set(&server->usage, 1);
+		refcount_set(&server->usage, 1);
 		server->cell = cell;
 
 		INIT_LIST_HEAD(&server->link);
@@ -91,7 +91,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell,
 
 		memcpy(&server->addr, addr, sizeof(struct in_addr));
 		server->addr.s_addr = addr->s_addr;
-		_leave(" = %p{%d}", server, atomic_read(&server->usage));
+		_leave(" = %p{%d}", server, refcount_read(&server->usage));
 	} else {
 		_leave(" = NULL [nomem]");
 	}
@@ -140,7 +140,7 @@ struct afs_server *afs_lookup_server(struct afs_cell *cell,
 	list_add_tail(&server->link, &cell->servers);
 
 	write_unlock(&cell->servers_lock);
-	_leave(" = %p{%d}", server, atomic_read(&server->usage));
+	_leave(" = %p{%d}", server, refcount_read(&server->usage));
 	return server;
 
 	/* found a matching server quickly */
@@ -154,7 +154,7 @@ struct afs_server *afs_lookup_server(struct afs_cell *cell,
 		list_del_init(&server->grave);
 		spin_unlock(&afs_server_graveyard_lock);
 	}
-	_leave(" = %p{%d}", server, atomic_read(&server->usage));
+	_leave(" = %p{%d}", server, refcount_read(&server->usage));
 	return server;
 
 	/* found a matching server on the second pass */
@@ -226,13 +226,13 @@ void afs_put_server(struct afs_server *server)
 	if (!server)
 		return;
 
-	_enter("%p{%d}", server, atomic_read(&server->usage));
+	_enter("%p{%d}", server, refcount_read(&server->usage));
 
-	_debug("PUT SERVER %d", atomic_read(&server->usage));
+	_debug("PUT SERVER %d", refcount_read(&server->usage));
 
-	ASSERTCMP(atomic_read(&server->usage), >, 0);
+	ASSERTCMP(refcount_read(&server->usage), >, 0);
 
-	if (likely(!atomic_dec_and_test(&server->usage))) {
+	if (likely(!refcount_dec_and_test(&server->usage))) {
 		_leave("");
 		return;
 	}
@@ -240,7 +240,7 @@ void afs_put_server(struct afs_server *server)
 	afs_flush_callback_breaks(server);
 
 	spin_lock(&afs_server_graveyard_lock);
-	if (atomic_read(&server->usage) == 0) {
+	if (refcount_read(&server->usage) == 0) {
 		list_move_tail(&server->grave, &afs_server_graveyard);
 		server->time_of_death = get_seconds();
 		queue_delayed_work(afs_wq, &afs_server_reaper,
@@ -296,7 +296,7 @@ static void afs_reap_server(struct work_struct *work)
 
 		write_lock(&server->cell->servers_lock);
 		write_lock(&afs_servers_lock);
-		if (atomic_read(&server->usage) > 0) {
+		if (refcount_read(&server->usage) > 0) {
 			list_del_init(&server->grave);
 		} else {
 			list_move_tail(&server->grave, &corpses);
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 45a8639..8e10011 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -176,7 +176,7 @@ static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
 	if (vl) {
 		vl->cell = cell;
 		vl->state = AFS_VL_NEW;
-		atomic_set(&vl->usage, 1);
+		refcount_set(&vl->usage, 1);
 		INIT_LIST_HEAD(&vl->link);
 		INIT_LIST_HEAD(&vl->grave);
 		INIT_LIST_HEAD(&vl->update);
@@ -432,7 +432,7 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
 found_in_memory:
 	/* found in memory */
 	_debug("found in memory");
-	atomic_inc(&vl->usage);
+	refcount_inc(&vl->usage);
 	spin_unlock(&cell->vl_lock);
 	if (!list_empty(&vl->grave)) {
 		spin_lock(&afs_vlocation_graveyard_lock);
@@ -495,15 +495,15 @@ void afs_put_vlocation(struct afs_vlocation *vl)
 
 	_enter("%s", vl->vldb.name);
 
-	ASSERTCMP(atomic_read(&vl->usage), >, 0);
+	ASSERTCMP(refcount_read(&vl->usage), >, 0);
 
-	if (likely(!atomic_dec_and_test(&vl->usage))) {
+	if (likely(!refcount_dec_and_test(&vl->usage))) {
 		_leave("");
 		return;
 	}
 
 	spin_lock(&afs_vlocation_graveyard_lock);
-	if (atomic_read(&vl->usage) == 0) {
+	if (refcount_read(&vl->usage) == 0) {
 		_debug("buried");
 		list_move_tail(&vl->grave, &afs_vlocation_graveyard);
 		vl->time_of_death = get_seconds();
@@ -566,7 +566,7 @@ static void afs_vlocation_reaper(struct work_struct *work)
 		}
 
 		spin_lock(&vl->cell->vl_lock);
-		if (atomic_read(&vl->usage) > 0) {
+		if (refcount_read(&vl->usage) > 0) {
 			_debug("no reap");
 			list_del_init(&vl->grave);
 		} else {
@@ -641,7 +641,7 @@ static void afs_vlocation_updater(struct work_struct *work)
 
 		vl = list_entry(afs_vlocation_updates.next,
 				struct afs_vlocation, update);
-		if (atomic_read(&vl->usage) > 0)
+		if (refcount_read(&vl->usage) > 0)
 			break;
 		list_del_init(&vl->update);
 	}
@@ -656,7 +656,7 @@ static void afs_vlocation_updater(struct work_struct *work)
 	}
 
 	list_del_init(&vl->update);
-	atomic_inc(&vl->usage);
+	refcount_inc(&vl->usage);
 	spin_unlock(&afs_vlocation_updates_lock);
 
 	/* we can now perform the update */
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index d142a24..22414fd 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -100,7 +100,7 @@ struct afs_volume *afs_volume_lookup(struct afs_mount_params *params)
 	if (!volume)
 		goto error_up;
 
-	atomic_set(&volume->usage, 1);
+	refcount_set(&volume->usage, 1);
 	volume->type		= params->type;
 	volume->type_force	= params->force;
 	volume->cell		= params->cell;
@@ -179,7 +179,7 @@ void afs_put_volume(struct afs_volume *volume)
 
 	_enter("%p", volume);
 
-	ASSERTCMP(atomic_read(&volume->usage), >, 0);
+	ASSERTCMP(refcount_read(&volume->usage), >, 0);
 
 	vlocation = volume->vlocation;
 
@@ -187,7 +187,7 @@ void afs_put_volume(struct afs_volume *volume)
 	 * atomic */
 	down_write(&vlocation->cell->vl_sem);
 
-	if (likely(!atomic_dec_and_test(&volume->usage))) {
+	if (likely(!refcount_dec_and_test(&volume->usage))) {
 		up_write(&vlocation->cell->vl_sem);
 		_leave("");
 		return;
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 8299601..f285cb0 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1287,7 +1287,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 		head = btrfs_find_delayed_ref_head(trans, bytenr);
 		if (head) {
 			if (!mutex_trylock(&head->mutex)) {
-				atomic_inc(&head->node.refs);
+				refcount_inc(&head->node.refs);
 				spin_unlock(&delayed_refs->lock);
 
 				btrfs_release_path(path);
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 7f39084..133a890 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -44,7 +44,7 @@
 
 struct compressed_bio {
 	/* number of bios pending for this compressed extent */
-	atomic_t pending_bios;
+	refcount_t pending_bios;
 
 	/* the pages with the compressed data on them */
 	struct page **compressed_pages;
@@ -163,7 +163,7 @@ static void end_compressed_bio_read(struct bio *bio)
 	/* if there are more bios still pending for this compressed
 	 * extent, just exit
 	 */
-	if (!atomic_dec_and_test(&cb->pending_bios))
+	if (!refcount_dec_and_test(&cb->pending_bios))
 		goto out;
 
 	inode = cb->inode;
@@ -276,7 +276,7 @@ static void end_compressed_bio_write(struct bio *bio)
 	/* if there are more bios still pending for this compressed
 	 * extent, just exit
 	 */
-	if (!atomic_dec_and_test(&cb->pending_bios))
+	if (!refcount_dec_and_test(&cb->pending_bios))
 		goto out;
 
 	/* ok, we're the last bio for this extent, step one is to
@@ -344,7 +344,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 	cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS);
 	if (!cb)
 		return -ENOMEM;
-	atomic_set(&cb->pending_bios, 0);
+	refcount_set(&cb->pending_bios, 0);
 	cb->errors = 0;
 	cb->inode = inode;
 	cb->start = start;
@@ -365,7 +365,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 	bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
 	bio->bi_private = cb;
 	bio->bi_end_io = end_compressed_bio_write;
-	atomic_inc(&cb->pending_bios);
+	refcount_inc(&cb->pending_bios);
 
 	/* create and submit bios for the compressed pages */
 	bytes_left = compressed_len;
@@ -390,7 +390,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 			 * we inc the count.  Otherwise, the cb might get
 			 * freed before we're done setting it up
 			 */
-			atomic_inc(&cb->pending_bios);
+			refcount_inc(&cb->pending_bios);
 			ret = btrfs_bio_wq_end_io(fs_info, bio,
 						  BTRFS_WQ_ENDIO_DATA);
 			BUG_ON(ret); /* -ENOMEM */
@@ -609,7 +609,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 	if (!cb)
 		goto out;
 
-	atomic_set(&cb->pending_bios, 0);
+	refcount_set(&cb->pending_bios, 0);
 	cb->errors = 0;
 	cb->inode = inode;
 	cb->mirror_num = mirror_num;
@@ -658,7 +658,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 	bio_set_op_attrs (comp_bio, REQ_OP_READ, 0);
 	comp_bio->bi_private = cb;
 	comp_bio->bi_end_io = end_compressed_bio_read;
-	atomic_inc(&cb->pending_bios);
+	refcount_inc(&cb->pending_bios);
 
 	for (pg_index = 0; pg_index < nr_pages; pg_index++) {
 		page = cb->compressed_pages[pg_index];
@@ -687,7 +687,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 			 * we inc the count.  Otherwise, the cb might get
 			 * freed before we're done setting it up
 			 */
-			atomic_inc(&cb->pending_bios);
+			refcount_inc(&cb->pending_bios);
 
 			if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
 				ret = btrfs_lookup_bio_sums(inode, comp_bio,
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index a426dc8..ff70466 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -159,7 +159,7 @@ struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
 		 * the inc_not_zero dance and if it doesn't work then
 		 * synchronize_rcu and try again.
 		 */
-		if (atomic_inc_not_zero(&eb->refs)) {
+		if (refcount_inc_not_zero(&eb->refs)) {
 			rcu_read_unlock();
 			break;
 		}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 6a82371..c8b2b3b 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -38,6 +38,7 @@
 #include <linux/security.h>
 #include <linux/sizes.h>
 #include <linux/dynamic_debug.h>
+#include <linux/refcount.h>
 #include "extent_io.h"
 #include "extent_map.h"
 #include "async-thread.h"
@@ -509,7 +510,7 @@ struct btrfs_caching_control {
 	struct btrfs_work work;
 	struct btrfs_block_group_cache *block_group;
 	u64 progress;
-	atomic_t count;
+	refcount_t count;
 };
 
 /* Once caching_thread() finds this much free space, it will wake up waiters. */
@@ -589,7 +590,7 @@ struct btrfs_block_group_cache {
 	struct list_head list;
 
 	/* usage count */
-	atomic_t count;
+	refcount_t count;
 
 	/* List of struct btrfs_free_clusters for this block group.
 	 * Today it will only have one thing on it, but that may change
@@ -1212,7 +1213,7 @@ struct btrfs_root {
 	dev_t anon_dev;
 
 	spinlock_t root_item_lock;
-	atomic_t refs;
+	refcount_t refs;
 
 	struct mutex delalloc_mutex;
 	spinlock_t delalloc_lock;
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 80982a8..d469d5b0 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -52,7 +52,7 @@ static inline void btrfs_init_delayed_node(
 {
 	delayed_node->root = root;
 	delayed_node->inode_id = inode_id;
-	atomic_set(&delayed_node->refs, 0);
+	refcount_set(&delayed_node->refs, 0);
 	delayed_node->ins_root = RB_ROOT;
 	delayed_node->del_root = RB_ROOT;
 	mutex_init(&delayed_node->mutex);
@@ -81,7 +81,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode)
 
 	node = ACCESS_ONCE(btrfs_inode->delayed_node);
 	if (node) {
-		atomic_inc(&node->refs);
+		refcount_inc(&node->refs);
 		return node;
 	}
 
@@ -89,14 +89,14 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode)
 	node = radix_tree_lookup(&root->delayed_nodes_tree, ino);
 	if (node) {
 		if (btrfs_inode->delayed_node) {
-			atomic_inc(&node->refs);	/* can be accessed */
+			refcount_inc(&node->refs);	/* can be accessed */
 			BUG_ON(btrfs_inode->delayed_node != node);
 			spin_unlock(&root->inode_lock);
 			return node;
 		}
 		btrfs_inode->delayed_node = node;
 		/* can be accessed and cached in the inode */
-		atomic_add(2, &node->refs);
+		refcount_add(2, &node->refs);
 		spin_unlock(&root->inode_lock);
 		return node;
 	}
@@ -126,7 +126,7 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
 	btrfs_init_delayed_node(node, root, ino);
 
 	/* cached in the btrfs inode and can be accessed */
-	atomic_add(2, &node->refs);
+	refcount_add(2, &node->refs);
 
 	ret = radix_tree_preload(GFP_NOFS);
 	if (ret) {
@@ -167,7 +167,7 @@ static void btrfs_queue_delayed_node(struct btrfs_delayed_root *root,
 	} else {
 		list_add_tail(&node->n_list, &root->node_list);
 		list_add_tail(&node->p_list, &root->prepare_list);
-		atomic_inc(&node->refs);	/* inserted into list */
+		refcount_inc(&node->refs);	/* inserted into list */
 		root->nodes++;
 		set_bit(BTRFS_DELAYED_NODE_IN_LIST, &node->flags);
 	}
@@ -181,7 +181,7 @@ static void btrfs_dequeue_delayed_node(struct btrfs_delayed_root *root,
 	spin_lock(&root->lock);
 	if (test_bit(BTRFS_DELAYED_NODE_IN_LIST, &node->flags)) {
 		root->nodes--;
-		atomic_dec(&node->refs);	/* not in the list */
+		refcount_dec(&node->refs);	/* not in the list */
 		list_del_init(&node->n_list);
 		if (!list_empty(&node->p_list))
 			list_del_init(&node->p_list);
@@ -202,7 +202,7 @@ static struct btrfs_delayed_node *btrfs_first_delayed_node(
 
 	p = delayed_root->node_list.next;
 	node = list_entry(p, struct btrfs_delayed_node, n_list);
-	atomic_inc(&node->refs);
+	refcount_inc(&node->refs);
 out:
 	spin_unlock(&delayed_root->lock);
 
@@ -229,7 +229,7 @@ static struct btrfs_delayed_node *btrfs_next_delayed_node(
 		p = node->n_list.next;
 
 	next = list_entry(p, struct btrfs_delayed_node, n_list);
-	atomic_inc(&next->refs);
+	refcount_inc(&next->refs);
 out:
 	spin_unlock(&delayed_root->lock);
 
@@ -254,11 +254,11 @@ static void __btrfs_release_delayed_node(
 		btrfs_dequeue_delayed_node(delayed_root, delayed_node);
 	mutex_unlock(&delayed_node->mutex);
 
-	if (atomic_dec_and_test(&delayed_node->refs)) {
+	if (refcount_dec_and_test(&delayed_node->refs)) {
 		bool free = false;
 		struct btrfs_root *root = delayed_node->root;
 		spin_lock(&root->inode_lock);
-		if (atomic_read(&delayed_node->refs) == 0) {
+		if (refcount_read(&delayed_node->refs) == 0) {
 			radix_tree_delete(&root->delayed_nodes_tree,
 					  delayed_node->inode_id);
 			free = true;
@@ -287,7 +287,7 @@ static struct btrfs_delayed_node *btrfs_first_prepared_delayed_node(
 	p = delayed_root->prepare_list.next;
 	list_del_init(p);
 	node = list_entry(p, struct btrfs_delayed_node, p_list);
-	atomic_inc(&node->refs);
+	refcount_inc(&node->refs);
 out:
 	spin_unlock(&delayed_root->lock);
 
@@ -309,7 +309,7 @@ static struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len)
 		item->ins_or_del = 0;
 		item->bytes_reserved = 0;
 		item->delayed_node = NULL;
-		atomic_set(&item->refs, 1);
+		refcount_set(&item->refs, 1);
 	}
 	return item;
 }
@@ -484,7 +484,7 @@ static void btrfs_release_delayed_item(struct btrfs_delayed_item *item)
 {
 	if (item) {
 		__btrfs_remove_delayed_item(item);
-		if (atomic_dec_and_test(&item->refs))
+		if (refcount_dec_and_test(&item->refs))
 			kfree(item);
 	}
 }
@@ -1601,14 +1601,14 @@ bool btrfs_readdir_get_delayed_items(struct inode *inode,
 	mutex_lock(&delayed_node->mutex);
 	item = __btrfs_first_delayed_insertion_item(delayed_node);
 	while (item) {
-		atomic_inc(&item->refs);
+		refcount_inc(&item->refs);
 		list_add_tail(&item->readdir_list, ins_list);
 		item = __btrfs_next_delayed_item(item);
 	}
 
 	item = __btrfs_first_delayed_deletion_item(delayed_node);
 	while (item) {
-		atomic_inc(&item->refs);
+		refcount_inc(&item->refs);
 		list_add_tail(&item->readdir_list, del_list);
 		item = __btrfs_next_delayed_item(item);
 	}
@@ -1622,7 +1622,7 @@ bool btrfs_readdir_get_delayed_items(struct inode *inode,
 	 * insert/delete delayed items in this period. So we also needn't
 	 * requeue or dequeue this delayed node.
 	 */
-	atomic_dec(&delayed_node->refs);
+	refcount_dec(&delayed_node->refs);
 
 	return true;
 }
@@ -1635,13 +1635,13 @@ void btrfs_readdir_put_delayed_items(struct inode *inode,
 
 	list_for_each_entry_safe(curr, next, ins_list, readdir_list) {
 		list_del(&curr->readdir_list);
-		if (atomic_dec_and_test(&curr->refs))
+		if (refcount_dec_and_test(&curr->refs))
 			kfree(curr);
 	}
 
 	list_for_each_entry_safe(curr, next, del_list, readdir_list) {
 		list_del(&curr->readdir_list);
-		if (atomic_dec_and_test(&curr->refs))
+		if (refcount_dec_and_test(&curr->refs))
 			kfree(curr);
 	}
 
@@ -1668,7 +1668,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list,
 		list_del(&curr->readdir_list);
 		ret = (curr->key.offset == index);
 
-		if (atomic_dec_and_test(&curr->refs))
+		if (refcount_dec_and_test(&curr->refs))
 			kfree(curr);
 
 		if (ret)
@@ -1706,7 +1706,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
 		list_del(&curr->readdir_list);
 
 		if (curr->key.offset < ctx->pos) {
-			if (atomic_dec_and_test(&curr->refs))
+			if (refcount_dec_and_test(&curr->refs))
 				kfree(curr);
 			continue;
 		}
@@ -1723,7 +1723,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
 		over = !dir_emit(ctx, name, name_len,
 			       location.objectid, d_type);
 
-		if (atomic_dec_and_test(&curr->refs))
+		if (refcount_dec_and_test(&curr->refs))
 			kfree(curr);
 
 		if (over)
@@ -1964,7 +1964,7 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root)
 		inode_id = delayed_nodes[n - 1]->inode_id + 1;
 
 		for (i = 0; i < n; i++)
-			atomic_inc(&delayed_nodes[i]->refs);
+			refcount_inc(&delayed_nodes[i]->refs);
 		spin_unlock(&root->inode_lock);
 
 		for (i = 0; i < n; i++) {
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h
index 8a2bf5e..45545ca 100644
--- a/fs/btrfs/delayed-inode.h
+++ b/fs/btrfs/delayed-inode.h
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include "ctree.h"
 
@@ -67,7 +68,7 @@ struct btrfs_delayed_node {
 	struct rb_root del_root;
 	struct mutex mutex;
 	struct btrfs_inode_item inode_item;
-	atomic_t refs;
+	refcount_t refs;
 	u64 index_cnt;
 	unsigned long flags;
 	int count;
@@ -80,7 +81,7 @@ struct btrfs_delayed_item {
 	struct list_head readdir_list;	/* used for readdir items */
 	u64 bytes_reserved;
 	struct btrfs_delayed_node *delayed_node;
-	atomic_t refs;
+	refcount_t refs;
 	int ins_or_del;
 	u32 data_len;
 	char data[0];
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index ef724a5..f8b09e5 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -164,7 +164,7 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
 	if (mutex_trylock(&head->mutex))
 		return 0;
 
-	atomic_inc(&head->node.refs);
+	refcount_inc(&head->node.refs);
 	spin_unlock(&delayed_refs->lock);
 
 	mutex_lock(&head->mutex);
@@ -589,7 +589,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
 	delayed_refs = &trans->transaction->delayed_refs;
 
 	/* first set the basic ref node struct up */
-	atomic_set(&ref->refs, 1);
+	refcount_set(&ref->refs, 1);
 	ref->bytenr = bytenr;
 	ref->num_bytes = num_bytes;
 	ref->ref_mod = count_mod;
@@ -677,7 +677,7 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
 	delayed_refs = &trans->transaction->delayed_refs;
 
 	/* first set the basic ref node struct up */
-	atomic_set(&ref->refs, 1);
+	refcount_set(&ref->refs, 1);
 	ref->bytenr = bytenr;
 	ref->num_bytes = num_bytes;
 	ref->ref_mod = 1;
@@ -734,7 +734,7 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info,
 		seq = atomic64_read(&fs_info->tree_mod_seq);
 
 	/* first set the basic ref node struct up */
-	atomic_set(&ref->refs, 1);
+	refcount_set(&ref->refs, 1);
 	ref->bytenr = bytenr;
 	ref->num_bytes = num_bytes;
 	ref->ref_mod = 1;
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 50947b5..a96032a 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -18,6 +18,8 @@
 #ifndef __DELAYED_REF__
 #define __DELAYED_REF__
 
+#include <linux/refcount.h>
+
 /* these are the possible values of struct btrfs_delayed_ref_node->action */
 #define BTRFS_ADD_DELAYED_REF    1 /* add one backref to the tree */
 #define BTRFS_DROP_DELAYED_REF   2 /* delete one backref from the tree */
@@ -53,7 +55,7 @@ struct btrfs_delayed_ref_node {
 	u64 seq;
 
 	/* ref count on this data structure */
-	atomic_t refs;
+	refcount_t refs;
 
 	/*
 	 * how many refs is this entry adding or deleting.  For
@@ -220,8 +222,8 @@ btrfs_free_delayed_extent_op(struct btrfs_delayed_extent_op *op)
 
 static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
 {
-	WARN_ON(atomic_read(&ref->refs) == 0);
-	if (atomic_dec_and_test(&ref->refs)) {
+	WARN_ON(refcount_read(&ref->refs) == 0);
+	if (refcount_dec_and_test(&ref->refs)) {
 		WARN_ON(ref->in_tree);
 		switch (ref->type) {
 		case BTRFS_TREE_BLOCK_REF_KEY:
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1800416..b15275c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -707,7 +707,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 	 */
 	extent_buffer_get(eb);
 
-	reads_done = atomic_dec_and_test(&eb->io_pages);
+	reads_done = refcount_dec_and_test(&eb->io_pages);
 	if (!reads_done)
 		goto err;
 
@@ -771,7 +771,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 		 * again, we have to make sure it has something
 		 * to decrement
 		 */
-		atomic_inc(&eb->io_pages);
+		refcount_inc(&eb->io_pages);
 		clear_extent_buffer_uptodate(eb);
 	}
 	free_extent_buffer(eb);
@@ -786,7 +786,7 @@ static int btree_io_failed_hook(struct page *page, int failed_mirror)
 	eb = (struct extent_buffer *)page->private;
 	set_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
 	eb->read_mirror = failed_mirror;
-	atomic_dec(&eb->io_pages);
+	refcount_dec(&eb->io_pages);
 	if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
 		btree_readahead_hook(eb->fs_info, eb, -EIO);
 	return -EIO;	/* we fixed nothing */
@@ -1145,7 +1145,7 @@ static int btree_set_page_dirty(struct page *page)
 	eb = (struct extent_buffer *)page->private;
 	BUG_ON(!eb);
 	BUG_ON(!test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
-	BUG_ON(!atomic_read(&eb->refs));
+	BUG_ON(!refcount_read(&eb->refs));
 	btrfs_assert_tree_locked(eb);
 #endif
 	return __set_page_dirty_nobuffers(page);
@@ -1342,7 +1342,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
 	atomic_set(&root->log_writers, 0);
 	atomic_set(&root->log_batch, 0);
 	atomic_set(&root->orphan_inodes, 0);
-	atomic_set(&root->refs, 1);
+	refcount_set(&root->refs, 1);
 	atomic_set(&root->will_be_snapshoted, 0);
 	atomic_set(&root->qgroup_meta_rsv, 0);
 	root->log_transid = 0;
@@ -4347,7 +4347,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
 		head = rb_entry(node, struct btrfs_delayed_ref_head,
 				href_node);
 		if (!mutex_trylock(&head->mutex)) {
-			atomic_inc(&head->node.refs);
+			refcount_inc(&head->node.refs);
 			spin_unlock(&delayed_refs->lock);
 
 			mutex_lock(&head->mutex);
@@ -4619,7 +4619,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
 		t = list_first_entry(&fs_info->trans_list,
 				     struct btrfs_transaction, list);
 		if (t->state >= TRANS_STATE_COMMIT_START) {
-			atomic_inc(&t->use_count);
+			refcount_inc(&t->use_count);
 			spin_unlock(&fs_info->trans_lock);
 			btrfs_wait_for_commit(fs_info, t->transid);
 			btrfs_put_transaction(t);
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 44dcd9a..74d554c 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -103,14 +103,14 @@ struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info);
  */
 static inline struct btrfs_root *btrfs_grab_fs_root(struct btrfs_root *root)
 {
-	if (atomic_inc_not_zero(&root->refs))
+	if (refcount_inc_not_zero(&root->refs))
 		return root;
 	return NULL;
 }
 
 static inline void btrfs_put_fs_root(struct btrfs_root *root)
 {
-	if (atomic_dec_and_test(&root->refs))
+	if (refcount_dec_and_test(&root->refs))
 		kfree(root);
 }
 
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e97302f..2fe4ee3 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -122,12 +122,12 @@ static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
 
 void btrfs_get_block_group(struct btrfs_block_group_cache *cache)
 {
-	atomic_inc(&cache->count);
+	refcount_inc(&cache->count);
 }
 
 void btrfs_put_block_group(struct btrfs_block_group_cache *cache)
 {
-	if (atomic_dec_and_test(&cache->count)) {
+	if (refcount_dec_and_test(&cache->count)) {
 		WARN_ON(cache->pinned > 0);
 		WARN_ON(cache->reserved > 0);
 		kfree(cache->free_space_ctl);
@@ -315,14 +315,14 @@ get_caching_control(struct btrfs_block_group_cache *cache)
 	}
 
 	ctl = cache->caching_ctl;
-	atomic_inc(&ctl->count);
+	refcount_inc(&ctl->count);
 	spin_unlock(&cache->lock);
 	return ctl;
 }
 
 static void put_caching_control(struct btrfs_caching_control *ctl)
 {
-	if (atomic_dec_and_test(&ctl->count))
+	if (refcount_dec_and_test(&ctl->count))
 		kfree(ctl);
 }
 
@@ -598,7 +598,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 	init_waitqueue_head(&caching_ctl->wait);
 	caching_ctl->block_group = cache;
 	caching_ctl->progress = cache->key.objectid;
-	atomic_set(&caching_ctl->count, 1);
+	refcount_set(&caching_ctl->count, 1);
 	btrfs_init_work(&caching_ctl->work, btrfs_cache_helper,
 			caching_thread, NULL, NULL);
 
@@ -619,7 +619,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 		struct btrfs_caching_control *ctl;
 
 		ctl = cache->caching_ctl;
-		atomic_inc(&ctl->count);
+		refcount_inc(&ctl->count);
 		prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE);
 		spin_unlock(&cache->lock);
 
@@ -706,7 +706,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 	}
 
 	down_write(&fs_info->commit_root_sem);
-	atomic_inc(&caching_ctl->count);
+	refcount_inc(&caching_ctl->count);
 	list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups);
 	up_write(&fs_info->commit_root_sem);
 
@@ -891,7 +891,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
 	head = btrfs_find_delayed_ref_head(trans, bytenr);
 	if (head) {
 		if (!mutex_trylock(&head->mutex)) {
-			atomic_inc(&head->node.refs);
+			refcount_inc(&head->node.refs);
 			spin_unlock(&delayed_refs->lock);
 
 			btrfs_release_path(path);
@@ -2972,7 +2972,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
 				struct btrfs_delayed_ref_node *ref;
 
 				ref = &head->node;
-				atomic_inc(&ref->refs);
+				refcount_inc(&ref->refs);
 
 				spin_unlock(&delayed_refs->lock);
 				/*
@@ -3045,7 +3045,7 @@ static noinline int check_delayed_ref(struct btrfs_trans_handle *trans,
 	}
 
 	if (!mutex_trylock(&head->mutex)) {
-		atomic_inc(&head->node.refs);
+		refcount_inc(&head->node.refs);
 		spin_unlock(&delayed_refs->lock);
 
 		btrfs_release_path(path);
@@ -9792,7 +9792,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
 		ASSERT(list_empty(&block_group->dirty_list));
 		ASSERT(list_empty(&block_group->io_list));
 		ASSERT(list_empty(&block_group->bg_list));
-		ASSERT(atomic_read(&block_group->count) == 1);
+		ASSERT(refcount_read(&block_group->count) == 1);
 		btrfs_put_block_group(block_group);
 
 		spin_lock(&info->block_group_cache_lock);
@@ -9904,7 +9904,7 @@ btrfs_create_block_group_cache(struct btrfs_fs_info *fs_info,
 						       start);
 	set_free_space_tree_thresholds(cache);
 
-	atomic_set(&cache->count, 1);
+	refcount_set(&cache->count, 1);
 	spin_lock_init(&cache->lock);
 	init_rwsem(&cache->data_rwsem);
 	INIT_LIST_HEAD(&cache->list);
@@ -10415,7 +10415,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 				    &fs_info->caching_block_groups, list)
 				if (ctl->block_group == block_group) {
 					caching_ctl = ctl;
-					atomic_inc(&caching_ctl->count);
+					refcount_inc(&caching_ctl->count);
 					break;
 				}
 		}
@@ -10849,7 +10849,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
 		spin_lock(&fs_info->trans_lock);
 		trans = fs_info->running_transaction;
 		if (trans)
-			atomic_inc(&trans->use_count);
+			refcount_inc(&trans->use_count);
 		spin_unlock(&fs_info->trans_lock);
 
 		ret = find_free_dev_extent_start(trans, device, minlen, start,
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 4ac383a..b6b27c9 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -68,7 +68,7 @@ void btrfs_leak_debug_check(void)
 		pr_err("BTRFS: state leak: start %llu end %llu state %u in tree %d refs %d\n",
 		       state->start, state->end, state->state,
 		       extent_state_in_tree(state),
-		       atomic_read(&state->refs));
+		       refcount_read(&state->refs));
 		list_del(&state->leak_list);
 		kmem_cache_free(extent_state_cache, state);
 	}
@@ -76,7 +76,7 @@ void btrfs_leak_debug_check(void)
 	while (!list_empty(&buffers)) {
 		eb = list_entry(buffers.next, struct extent_buffer, leak_list);
 		pr_err("BTRFS: buffer leak start %llu len %lu refs %d\n",
-		       eb->start, eb->len, atomic_read(&eb->refs));
+		       eb->start, eb->len, refcount_read(&eb->refs));
 		list_del(&eb->leak_list);
 		kmem_cache_free(extent_buffer_cache, eb);
 	}
@@ -233,7 +233,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask)
 	state->failrec = NULL;
 	RB_CLEAR_NODE(&state->rb_node);
 	btrfs_leak_debug_add(&state->leak_list, &states);
-	atomic_set(&state->refs, 1);
+	refcount_set(&state->refs, 1);
 	init_waitqueue_head(&state->wq);
 	trace_alloc_extent_state(state, mask, _RET_IP_);
 	return state;
@@ -243,7 +243,7 @@ void free_extent_state(struct extent_state *state)
 {
 	if (!state)
 		return;
-	if (atomic_dec_and_test(&state->refs)) {
+	if (refcount_dec_and_test(&state->refs)) {
 		WARN_ON(extent_state_in_tree(state));
 		btrfs_leak_debug_del(&state->leak_list);
 		trace_free_extent_state(state, _RET_IP_);
@@ -635,7 +635,7 @@ static int __clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
 		if (cached && extent_state_in_tree(cached) &&
 		    cached->start <= start && cached->end > start) {
 			if (clear)
-				atomic_dec(&cached->refs);
+				refcount_dec(&cached->refs);
 			state = cached;
 			goto hit_next;
 		}
@@ -787,7 +787,7 @@ static void wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
 
 		if (state->state & bits) {
 			start = state->start;
-			atomic_inc(&state->refs);
+			refcount_inc(&state->refs);
 			wait_on_state(tree, state);
 			free_extent_state(state);
 			goto again;
@@ -828,7 +828,7 @@ static void cache_state_if_flags(struct extent_state *state,
 	if (cached_ptr && !(*cached_ptr)) {
 		if (!flags || (state->state & flags)) {
 			*cached_ptr = state;
-			atomic_inc(&state->refs);
+			refcount_inc(&state->refs);
 		}
 	}
 }
@@ -1532,7 +1532,7 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
 		if (!found) {
 			*start = state->start;
 			*cached_state = state;
-			atomic_inc(&state->refs);
+			refcount_inc(&state->refs);
 		}
 		found++;
 		*end = state->end;
@@ -2856,7 +2856,7 @@ __get_extent_map(struct inode *inode, struct page *page, size_t pg_offset,
 		em = *em_cached;
 		if (extent_map_in_tree(em) && start >= em->start &&
 		    start < extent_map_end(em)) {
-			atomic_inc(&em->refs);
+			refcount_inc(&em->refs);
 			return em;
 		}
 
@@ -2867,7 +2867,7 @@ __get_extent_map(struct inode *inode, struct page *page, size_t pg_offset,
 	em = get_extent(inode, page, pg_offset, start, len, 0);
 	if (em_cached && !IS_ERR_OR_NULL(em)) {
 		BUG_ON(*em_cached);
-		atomic_inc(&em->refs);
+		refcount_inc(&em->refs);
 		*em_cached = em;
 	}
 	return em;
@@ -3698,7 +3698,7 @@ static void end_bio_extent_buffer_writepage(struct bio *bio)
 
 		eb = (struct extent_buffer *)page->private;
 		BUG_ON(!eb);
-		done = atomic_dec_and_test(&eb->io_pages);
+		done = refcount_dec_and_test(&eb->io_pages);
 
 		if (bio->bi_error ||
 		    test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) {
@@ -3734,7 +3734,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
 
 	clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags);
 	num_pages = num_extent_pages(eb->start, eb->len);
-	atomic_set(&eb->io_pages, num_pages);
+	refcount_set(&eb->io_pages, num_pages);
 	if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID)
 		bio_flags = EXTENT_BIO_TREE_LOG;
 
@@ -3768,7 +3768,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
 		if (ret) {
 			set_btree_ioerr(p);
 			end_page_writeback(p);
-			if (atomic_sub_and_test(num_pages - i, &eb->io_pages))
+			if (refcount_sub_and_test(num_pages - i, &eb->io_pages))
 				end_extent_buffer_writeback(eb);
 			ret = -EIO;
 			break;
@@ -3868,7 +3868,7 @@ int btree_write_cache_pages(struct address_space *mapping,
 				continue;
 			}
 
-			ret = atomic_inc_not_zero(&eb->refs);
+			ret = refcount_inc_not_zero(&eb->refs);
 			spin_unlock(&mapping->private_lock);
 			if (!ret)
 				continue;
@@ -4594,7 +4594,7 @@ static void __free_extent_buffer(struct extent_buffer *eb)
 
 int extent_buffer_under_io(struct extent_buffer *eb)
 {
-	return (atomic_read(&eb->io_pages) ||
+	return (refcount_read(&eb->io_pages) ||
 		test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) ||
 		test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
 }
@@ -4685,8 +4685,8 @@ __alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 start,
 	btrfs_leak_debug_add(&eb->leak_list, &buffers);
 
 	spin_lock_init(&eb->refs_lock);
-	atomic_set(&eb->refs, 1);
-	atomic_set(&eb->io_pages, 0);
+	refcount_set(&eb->refs, 1);
+	refcount_set(&eb->io_pages, 0);
 
 	/*
 	 * Sanity checks, currently the maximum is 64k covered by 16x 4k pages
@@ -4787,13 +4787,13 @@ static void check_buffer_tree_ref(struct extent_buffer *eb)
 	 * So bump the ref count first, then set the bit.  If someone
 	 * beat us to it, drop the ref we added.
 	 */
-	refs = atomic_read(&eb->refs);
+	refs = refcount_read(&eb->refs);
 	if (refs >= 2 && test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
 		return;
 
 	spin_lock(&eb->refs_lock);
 	if (!test_and_set_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
-		atomic_inc(&eb->refs);
+		refcount_inc(&eb->refs);
 	spin_unlock(&eb->refs_lock);
 }
 
@@ -4821,7 +4821,7 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info,
 	rcu_read_lock();
 	eb = radix_tree_lookup(&fs_info->buffer_radix,
 			       start >> PAGE_SHIFT);
-	if (eb && atomic_inc_not_zero(&eb->refs)) {
+	if (eb && refcount_inc_not_zero(&eb->refs)) {
 		rcu_read_unlock();
 		/*
 		 * Lock our eb's refs_lock to avoid races with
@@ -4889,7 +4889,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
 	 * want the buffers to stay in memory until we're done with them, so
 	 * bump the ref count again.
 	 */
-	atomic_inc(&eb->refs);
+	refcount_inc(&eb->refs);
 	return eb;
 free_eb:
 	btrfs_release_extent_buffer(eb);
@@ -4941,7 +4941,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
 			 * overwrite page->private.
 			 */
 			exists = (struct extent_buffer *)p->private;
-			if (atomic_inc_not_zero(&exists->refs)) {
+			if (refcount_inc_not_zero(&exists->refs)) {
 				spin_unlock(&mapping->private_lock);
 				unlock_page(p);
 				put_page(p);
@@ -5014,7 +5014,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
 	return eb;
 
 free_eb:
-	WARN_ON(!atomic_dec_and_test(&eb->refs));
+	WARN_ON(!refcount_dec_and_test(&eb->refs));
 	for (i = 0; i < num_pages; i++) {
 		if (eb->pages[i])
 			unlock_page(eb->pages[i]);
@@ -5035,8 +5035,8 @@ static inline void btrfs_release_extent_buffer_rcu(struct rcu_head *head)
 /* Expects to have eb->eb_lock already held */
 static int release_extent_buffer(struct extent_buffer *eb)
 {
-	WARN_ON(atomic_read(&eb->refs) == 0);
-	if (atomic_dec_and_test(&eb->refs)) {
+	WARN_ON(refcount_read(&eb->refs) == 0);
+	if (refcount_dec_and_test(&eb->refs)) {
 		if (test_and_clear_bit(EXTENT_BUFFER_IN_TREE, &eb->bflags)) {
 			struct btrfs_fs_info *fs_info = eb->fs_info;
 
@@ -5068,30 +5068,29 @@ static int release_extent_buffer(struct extent_buffer *eb)
 
 void free_extent_buffer(struct extent_buffer *eb)
 {
-	int refs;
-	int old;
+	unsigned int refs;
 	if (!eb)
 		return;
 
-	while (1) {
-		refs = atomic_read(&eb->refs);
-		if (refs <= 3)
-			break;
-		old = atomic_cmpxchg(&eb->refs, refs, refs - 1);
-		if (old == refs)
+	/* ATTENTION: please review me */
+
+	spin_lock(&eb->refs_lock);
+	refs = refcount_read(&eb->refs);
+	if (refs > 3) {
+			refcount_set(&eb->refs, refs - 1);
+			spin_unlock(&eb->refs_lock);
 			return;
 	}
 
-	spin_lock(&eb->refs_lock);
-	if (atomic_read(&eb->refs) == 2 &&
+	if (refcount_read(&eb->refs) == 2 &&
 	    test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags))
-		atomic_dec(&eb->refs);
+		refcount_dec(&eb->refs);
 
-	if (atomic_read(&eb->refs) == 2 &&
+	if (refcount_read(&eb->refs) == 2 &&
 	    test_bit(EXTENT_BUFFER_STALE, &eb->bflags) &&
 	    !extent_buffer_under_io(eb) &&
 	    test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
-		atomic_dec(&eb->refs);
+		refcount_dec(&eb->refs);
 
 	/*
 	 * I know this is terrible, but it's temporary until we stop tracking
@@ -5108,9 +5107,9 @@ void free_extent_buffer_stale(struct extent_buffer *eb)
 	spin_lock(&eb->refs_lock);
 	set_bit(EXTENT_BUFFER_STALE, &eb->bflags);
 
-	if (atomic_read(&eb->refs) == 2 && !extent_buffer_under_io(eb) &&
+	if (refcount_read(&eb->refs) == 2 && !extent_buffer_under_io(eb) &&
 	    test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags))
-		atomic_dec(&eb->refs);
+		refcount_dec(&eb->refs);
 	release_extent_buffer(eb);
 }
 
@@ -5141,7 +5140,7 @@ void clear_extent_buffer_dirty(struct extent_buffer *eb)
 		ClearPageError(page);
 		unlock_page(page);
 	}
-	WARN_ON(atomic_read(&eb->refs) == 0);
+	WARN_ON(refcount_read(&eb->refs) == 0);
 }
 
 int set_extent_buffer_dirty(struct extent_buffer *eb)
@@ -5155,7 +5154,7 @@ int set_extent_buffer_dirty(struct extent_buffer *eb)
 	was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
 
 	num_pages = num_extent_pages(eb->start, eb->len);
-	WARN_ON(atomic_read(&eb->refs) == 0);
+	WARN_ON(refcount_read(&eb->refs) == 0);
 	WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags));
 
 	for (i = 0; i < num_pages; i++)
@@ -5246,13 +5245,13 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 
 	clear_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
 	eb->read_mirror = 0;
-	atomic_set(&eb->io_pages, num_reads);
+	refcount_set(&eb->io_pages, num_reads);
 	for (i = 0; i < num_pages; i++) {
 		page = eb->pages[i];
 
 		if (!PageUptodate(page)) {
 			if (ret) {
-				atomic_dec(&eb->io_pages);
+				refcount_dec(&eb->io_pages);
 				unlock_page(page);
 				continue;
 			}
@@ -5272,7 +5271,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 				 *
 				 * We must dec io_pages by ourselves.
 				 */
-				atomic_dec(&eb->io_pages);
+				refcount_dec(&eb->io_pages);
 			}
 		} else {
 			unlock_page(page);
@@ -5905,7 +5904,7 @@ int try_release_extent_buffer(struct page *page)
 	 * this page.
 	 */
 	spin_lock(&eb->refs_lock);
-	if (atomic_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) {
+	if (refcount_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) {
 		spin_unlock(&eb->refs_lock);
 		spin_unlock(&page->mapping->private_lock);
 		return 0;
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 17f9ce47..1b69727 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -2,6 +2,7 @@
 #define __EXTENTIO__
 
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 #include "ulist.h"
 
 /* bits for the extent state */
@@ -131,7 +132,7 @@ struct extent_state {
 
 	/* ADD NEW ELEMENTS AFTER THIS */
 	wait_queue_head_t wq;
-	atomic_t refs;
+	refcount_t refs;
 	unsigned state;
 
 	struct io_failure_record *failrec;
@@ -149,8 +150,8 @@ struct extent_buffer {
 	unsigned long bflags;
 	struct btrfs_fs_info *fs_info;
 	spinlock_t refs_lock;
-	atomic_t refs;
-	atomic_t io_pages;
+	refcount_t refs;
+	refcount_t io_pages;
 	int read_mirror;
 	struct rcu_head rcu_head;
 	pid_t lock_owner;
@@ -393,7 +394,7 @@ static inline unsigned long num_extent_pages(u64 start, u64 len)
 
 static inline void extent_buffer_get(struct extent_buffer *eb)
 {
-	atomic_inc(&eb->refs);
+	refcount_inc(&eb->refs);
 }
 
 int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 26f9ac7..6985015 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -55,7 +55,7 @@ struct extent_map *alloc_extent_map(void)
 	em->flags = 0;
 	em->compress_type = BTRFS_COMPRESS_NONE;
 	em->generation = 0;
-	atomic_set(&em->refs, 1);
+	refcount_set(&em->refs, 1);
 	INIT_LIST_HEAD(&em->list);
 	return em;
 }
@@ -71,8 +71,8 @@ void free_extent_map(struct extent_map *em)
 {
 	if (!em)
 		return;
-	WARN_ON(atomic_read(&em->refs) == 0);
-	if (atomic_dec_and_test(&em->refs)) {
+	WARN_ON(refcount_read(&em->refs) == 0);
+	if (refcount_dec_and_test(&em->refs)) {
 		WARN_ON(extent_map_in_tree(em));
 		WARN_ON(!list_empty(&em->list));
 		if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags))
@@ -322,7 +322,7 @@ static inline void setup_extent_mapping(struct extent_map_tree *tree,
 					struct extent_map *em,
 					int modified)
 {
-	atomic_inc(&em->refs);
+	refcount_inc(&em->refs);
 	em->mod_start = em->start;
 	em->mod_len = em->len;
 
@@ -381,7 +381,7 @@ __lookup_extent_mapping(struct extent_map_tree *tree,
 	if (strict && !(end > em->start && start < extent_map_end(em)))
 		return NULL;
 
-	atomic_inc(&em->refs);
+	refcount_inc(&em->refs);
 	return em;
 }
 
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index eb8b8fa..a67b2de 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -2,6 +2,7 @@
 #define __EXTENTMAP__
 
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 
 #define EXTENT_MAP_LAST_BYTE ((u64)-4)
 #define EXTENT_MAP_HOLE ((u64)-3)
@@ -41,7 +42,7 @@ struct extent_map {
 		 */
 		struct map_lookup *map_lookup;
 	};
-	atomic_t refs;
+	refcount_t refs;
 	unsigned int compress_type;
 	struct list_head list;
 };
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 7015892..e8f8de4 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2677,7 +2677,7 @@ int btrfs_return_cluster_to_free_space(
 		spin_unlock(&cluster->lock);
 		return 0;
 	}
-	atomic_inc(&block_group->count);
+	refcount_inc(&block_group->count);
 	spin_unlock(&cluster->lock);
 
 	ctl = block_group->free_space_ctl;
@@ -3095,7 +3095,7 @@ int btrfs_find_space_cluster(struct btrfs_fs_info *fs_info,
 		list_del_init(&entry->list);
 
 	if (!ret) {
-		atomic_inc(&block_group->count);
+		refcount_inc(&block_group->count);
 		list_add_tail(&cluster->block_group_list,
 			      &block_group->cluster_list);
 		cluster->block_group = block_group;
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 041c332..963f6fe 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -212,7 +212,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
 		set_bit(BTRFS_ORDERED_DIRECT, &entry->flags);
 
 	/* one ref for the tree */
-	atomic_set(&entry->refs, 1);
+	refcount_set(&entry->refs, 1);
 	init_waitqueue_head(&entry->wait);
 	INIT_LIST_HEAD(&entry->list);
 	INIT_LIST_HEAD(&entry->root_extent_list);
@@ -358,7 +358,7 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode,
 out:
 	if (!ret && cached && entry) {
 		*cached = entry;
-		atomic_inc(&entry->refs);
+		refcount_inc(&entry->refs);
 	}
 	spin_unlock_irqrestore(&tree->lock, flags);
 	return ret == 0;
@@ -425,7 +425,7 @@ int btrfs_dec_test_ordered_pending(struct inode *inode,
 out:
 	if (!ret && cached && entry) {
 		*cached = entry;
-		atomic_inc(&entry->refs);
+		refcount_inc(&entry->refs);
 	}
 	spin_unlock_irqrestore(&tree->lock, flags);
 	return ret == 0;
@@ -456,7 +456,7 @@ void btrfs_get_logged_extents(struct inode *inode,
 		if (test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags))
 			continue;
 		list_add(&ordered->log_list, logged_list);
-		atomic_inc(&ordered->refs);
+		refcount_inc(&ordered->refs);
 	}
 	spin_unlock_irq(&tree->lock);
 }
@@ -565,7 +565,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
 
 	trace_btrfs_ordered_extent_put(entry->inode, entry);
 
-	if (atomic_dec_and_test(&entry->refs)) {
+	if (refcount_dec_and_test(&entry->refs)) {
 		ASSERT(list_empty(&entry->log_list));
 		ASSERT(list_empty(&entry->trans_list));
 		ASSERT(list_empty(&entry->root_extent_list));
@@ -623,7 +623,7 @@ void btrfs_remove_ordered_extent(struct inode *inode,
 		spin_lock(&fs_info->trans_lock);
 		trans = fs_info->running_transaction;
 		if (trans)
-			atomic_inc(&trans->use_count);
+			refcount_inc(&trans->use_count);
 		spin_unlock(&fs_info->trans_lock);
 
 		ASSERT(trans);
@@ -690,7 +690,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
 
 		list_move_tail(&ordered->root_extent_list,
 			       &root->ordered_extents);
-		atomic_inc(&ordered->refs);
+		refcount_inc(&ordered->refs);
 		spin_unlock(&root->ordered_extent_lock);
 
 		btrfs_init_work(&ordered->flush_work,
@@ -870,7 +870,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct inode *inode,
 	if (!offset_in_entry(entry, file_offset))
 		entry = NULL;
 	if (entry)
-		atomic_inc(&entry->refs);
+		refcount_inc(&entry->refs);
 out:
 	spin_unlock_irq(&tree->lock);
 	return entry;
@@ -912,7 +912,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(struct inode *inode,
 	}
 out:
 	if (entry)
-		atomic_inc(&entry->refs);
+		refcount_inc(&entry->refs);
 	spin_unlock_irq(&tree->lock);
 	return entry;
 }
@@ -949,7 +949,7 @@ btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset)
 		goto out;
 
 	entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-	atomic_inc(&entry->refs);
+	refcount_inc(&entry->refs);
 out:
 	spin_unlock_irq(&tree->lock);
 	return entry;
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index 5f2b0ca..926bc22 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -111,7 +111,7 @@ struct btrfs_ordered_extent {
 	int compress_type;
 
 	/* reference count */
-	atomic_t refs;
+	refcount_t refs;
 
 	/* the inode we belong to */
 	struct inode *inode;
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index d2a9a1e..31125ab 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -149,7 +149,7 @@ struct btrfs_raid_bio {
 
 	int generic_bio_cnt;
 
-	atomic_t refs;
+	refcount_t refs;
 
 	atomic_t stripes_pending;
 
@@ -389,7 +389,7 @@ static void __remove_rbio_from_cache(struct btrfs_raid_bio *rbio)
 		if (bio_list_empty(&rbio->bio_list)) {
 			if (!list_empty(&rbio->hash_list)) {
 				list_del_init(&rbio->hash_list);
-				atomic_dec(&rbio->refs);
+				refcount_dec(&rbio->refs);
 				BUG_ON(!list_empty(&rbio->plug_list));
 			}
 		}
@@ -480,7 +480,7 @@ static void cache_rbio(struct btrfs_raid_bio *rbio)
 
 	/* bump our ref if we were not in the list before */
 	if (!test_and_set_bit(RBIO_CACHE_BIT, &rbio->flags))
-		atomic_inc(&rbio->refs);
+		refcount_inc(&rbio->refs);
 
 	if (!list_empty(&rbio->stripe_cache)){
 		list_move(&rbio->stripe_cache, &table->stripe_cache);
@@ -691,7 +691,7 @@ static noinline int lock_stripe_add(struct btrfs_raid_bio *rbio)
 			    test_bit(RBIO_CACHE_BIT, &cur->flags) &&
 			    !test_bit(RBIO_RMW_LOCKED_BIT, &cur->flags)) {
 				list_del_init(&cur->hash_list);
-				atomic_dec(&cur->refs);
+				refcount_dec(&cur->refs);
 
 				steal_rbio(cur, rbio);
 				cache_drop = cur;
@@ -740,7 +740,7 @@ static noinline int lock_stripe_add(struct btrfs_raid_bio *rbio)
 		}
 	}
 lockit:
-	atomic_inc(&rbio->refs);
+	refcount_inc(&rbio->refs);
 	list_add(&rbio->hash_list, &h->hash_list);
 out:
 	spin_unlock_irqrestore(&h->lock, flags);
@@ -786,7 +786,7 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio)
 		}
 
 		list_del_init(&rbio->hash_list);
-		atomic_dec(&rbio->refs);
+		refcount_dec(&rbio->refs);
 
 		/*
 		 * we use the plug list to hold all the rbios
@@ -803,7 +803,7 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio)
 			list_del_init(&rbio->plug_list);
 
 			list_add(&next->hash_list, &h->hash_list);
-			atomic_inc(&next->refs);
+			refcount_inc(&next->refs);
 			spin_unlock(&rbio->bio_list_lock);
 			spin_unlock_irqrestore(&h->lock, flags);
 
@@ -845,8 +845,7 @@ static void __free_raid_bio(struct btrfs_raid_bio *rbio)
 {
 	int i;
 
-	WARN_ON(atomic_read(&rbio->refs) < 0);
-	if (!atomic_dec_and_test(&rbio->refs))
+	if (!refcount_dec_and_test(&rbio->refs))
 		return;
 
 	WARN_ON(!list_empty(&rbio->stripe_cache));
@@ -999,7 +998,7 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
 	rbio->stripe_npages = stripe_npages;
 	rbio->faila = -1;
 	rbio->failb = -1;
-	atomic_set(&rbio->refs, 1);
+	refcount_set(&rbio->refs, 1);
 	atomic_set(&rbio->error, 0);
 	atomic_set(&rbio->stripes_pending, 0);
 
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 9a94670..454518c 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -64,7 +64,7 @@ struct scrub_ctx;
 #define SCRUB_MAX_PAGES_PER_BLOCK	16	/* 64k per node/leaf/sector */
 
 struct scrub_recover {
-	atomic_t		refs;
+	refcount_t		refs;
 	struct btrfs_bio	*bbio;
 	u64			map_length;
 };
@@ -79,7 +79,7 @@ struct scrub_page {
 	u64			logical;
 	u64			physical;
 	u64			physical_for_dev_replace;
-	atomic_t		refs;
+	refcount_t		refs;
 	struct {
 		unsigned int	mirror_num:8;
 		unsigned int	have_csum:1;
@@ -112,7 +112,7 @@ struct scrub_block {
 	struct scrub_page	*pagev[SCRUB_MAX_PAGES_PER_BLOCK];
 	int			page_count;
 	atomic_t		outstanding_pages;
-	atomic_t		refs; /* free mem on transition to zero */
+	refcount_t		refs; /* free mem on transition to zero */
 	struct scrub_ctx	*sctx;
 	struct scrub_parity	*sparity;
 	struct {
@@ -142,7 +142,7 @@ struct scrub_parity {
 
 	int			stripe_len;
 
-	atomic_t		refs;
+	refcount_t		refs;
 
 	struct list_head	spages;
 
@@ -202,7 +202,7 @@ struct scrub_ctx {
 	 * doesn't free the scrub context before or while the workers are
 	 * doing the wakeup() call.
 	 */
-	atomic_t                refs;
+	refcount_t                refs;
 };
 
 struct scrub_fixup_nodatasum {
@@ -307,7 +307,7 @@ static void scrub_put_ctx(struct scrub_ctx *sctx);
 
 static void scrub_pending_bio_inc(struct scrub_ctx *sctx)
 {
-	atomic_inc(&sctx->refs);
+	refcount_inc(&sctx->refs);
 	atomic_inc(&sctx->bios_in_flight);
 }
 
@@ -358,7 +358,7 @@ static void scrub_pending_trans_workers_inc(struct scrub_ctx *sctx)
 {
 	struct btrfs_fs_info *fs_info = sctx->fs_info;
 
-	atomic_inc(&sctx->refs);
+	refcount_inc(&sctx->refs);
 	/*
 	 * increment scrubs_running to prevent cancel requests from
 	 * completing as long as a worker is running. we must also
@@ -449,7 +449,7 @@ static noinline_for_stack void scrub_free_ctx(struct scrub_ctx *sctx)
 
 static void scrub_put_ctx(struct scrub_ctx *sctx)
 {
-	if (atomic_dec_and_test(&sctx->refs))
+	if (refcount_dec_and_test(&sctx->refs))
 		scrub_free_ctx(sctx);
 }
 
@@ -464,7 +464,7 @@ struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev, int is_dev_replace)
 	sctx = kzalloc(sizeof(*sctx), GFP_KERNEL);
 	if (!sctx)
 		goto nomem;
-	atomic_set(&sctx->refs, 1);
+	refcount_set(&sctx->refs, 1);
 	sctx->is_dev_replace = is_dev_replace;
 	sctx->pages_per_rd_bio = SCRUB_PAGES_PER_RD_BIO;
 	sctx->curr = -1;
@@ -859,12 +859,12 @@ static void scrub_fixup_nodatasum(struct btrfs_work *work)
 
 static inline void scrub_get_recover(struct scrub_recover *recover)
 {
-	atomic_inc(&recover->refs);
+	refcount_inc(&recover->refs);
 }
 
 static inline void scrub_put_recover(struct scrub_recover *recover)
 {
-	if (atomic_dec_and_test(&recover->refs)) {
+	if (refcount_dec_and_test(&recover->refs)) {
 		btrfs_put_bbio(recover->bbio);
 		kfree(recover);
 	}
@@ -1345,7 +1345,7 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
 			return -ENOMEM;
 		}
 
-		atomic_set(&recover->refs, 1);
+		refcount_set(&recover->refs, 1);
 		recover->bbio = bbio;
 		recover->map_length = mapped_length;
 
@@ -2000,12 +2000,12 @@ static int scrub_checksum_super(struct scrub_block *sblock)
 
 static void scrub_block_get(struct scrub_block *sblock)
 {
-	atomic_inc(&sblock->refs);
+	refcount_inc(&sblock->refs);
 }
 
 static void scrub_block_put(struct scrub_block *sblock)
 {
-	if (atomic_dec_and_test(&sblock->refs)) {
+	if (refcount_dec_and_test(&sblock->refs)) {
 		int i;
 
 		if (sblock->sparity)
@@ -2019,12 +2019,12 @@ static void scrub_block_put(struct scrub_block *sblock)
 
 static void scrub_page_get(struct scrub_page *spage)
 {
-	atomic_inc(&spage->refs);
+	refcount_inc(&spage->refs);
 }
 
 static void scrub_page_put(struct scrub_page *spage)
 {
-	if (atomic_dec_and_test(&spage->refs)) {
+	if (refcount_dec_and_test(&spage->refs)) {
 		if (spage->page)
 			__free_page(spage->page);
 		kfree(spage);
@@ -2257,7 +2257,7 @@ static int scrub_pages(struct scrub_ctx *sctx, u64 logical, u64 len,
 
 	/* one ref inside this function, plus one for each page added to
 	 * a bio later on */
-	atomic_set(&sblock->refs, 1);
+	refcount_set(&sblock->refs, 1);
 	sblock->sctx = sctx;
 	sblock->no_io_error_seen = 1;
 
@@ -2557,7 +2557,7 @@ static int scrub_pages_for_parity(struct scrub_parity *sparity,
 
 	/* one ref inside this function, plus one for each page added to
 	 * a bio later on */
-	atomic_set(&sblock->refs, 1);
+	refcount_set(&sblock->refs, 1);
 	sblock->sctx = sctx;
 	sblock->no_io_error_seen = 1;
 	sblock->sparity = sparity;
@@ -2824,12 +2824,12 @@ static inline int scrub_calc_parity_bitmap_len(int nsectors)
 
 static void scrub_parity_get(struct scrub_parity *sparity)
 {
-	atomic_inc(&sparity->refs);
+	refcount_inc(&sparity->refs);
 }
 
 static void scrub_parity_put(struct scrub_parity *sparity)
 {
-	if (!atomic_dec_and_test(&sparity->refs))
+	if (!refcount_dec_and_test(&sparity->refs))
 		return;
 
 	scrub_parity_check_and_repair(sparity);
@@ -2881,7 +2881,7 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
 	sparity->scrub_dev = sdev;
 	sparity->logic_start = logic_start;
 	sparity->logic_end = logic_end;
-	atomic_set(&sparity->refs, 1);
+	refcount_set(&sparity->refs, 1);
 	INIT_LIST_HEAD(&sparity->spages);
 	sparity->dbitmap = sparity->bitmap;
 	sparity->ebitmap = (void *)sparity->bitmap + bitmap_len;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 0e0508f..d586fd6 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -60,8 +60,8 @@ static const unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
 
 void btrfs_put_transaction(struct btrfs_transaction *transaction)
 {
-	WARN_ON(atomic_read(&transaction->use_count) == 0);
-	if (atomic_dec_and_test(&transaction->use_count)) {
+	WARN_ON(refcount_read(&transaction->use_count) == 0);
+	if (refcount_dec_and_test(&transaction->use_count)) {
 		BUG_ON(!list_empty(&transaction->list));
 		WARN_ON(!RB_EMPTY_ROOT(&transaction->delayed_refs.href_root));
 		if (transaction->delayed_refs.pending_csums)
@@ -207,7 +207,7 @@ static noinline int join_transaction(struct btrfs_fs_info *fs_info,
 			spin_unlock(&fs_info->trans_lock);
 			return -EBUSY;
 		}
-		atomic_inc(&cur_trans->use_count);
+		refcount_inc(&cur_trans->use_count);
 		atomic_inc(&cur_trans->num_writers);
 		extwriter_counter_inc(cur_trans, type);
 		spin_unlock(&fs_info->trans_lock);
@@ -257,7 +257,7 @@ static noinline int join_transaction(struct btrfs_fs_info *fs_info,
 	 * One for this trans handle, one so it will live on until we
 	 * commit the transaction.
 	 */
-	atomic_set(&cur_trans->use_count, 2);
+	refcount_set(&cur_trans->use_count, 2);
 	atomic_set(&cur_trans->pending_ordered, 0);
 	cur_trans->flags = 0;
 	cur_trans->start_time = get_seconds();
@@ -432,7 +432,7 @@ static void wait_current_trans(struct btrfs_fs_info *fs_info)
 	spin_lock(&fs_info->trans_lock);
 	cur_trans = fs_info->running_transaction;
 	if (cur_trans && is_transaction_blocked(cur_trans)) {
-		atomic_inc(&cur_trans->use_count);
+		refcount_inc(&cur_trans->use_count);
 		spin_unlock(&fs_info->trans_lock);
 
 		wait_event(fs_info->transaction_wait,
@@ -734,7 +734,7 @@ int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid)
 		list_for_each_entry(t, &fs_info->trans_list, list) {
 			if (t->transid == transid) {
 				cur_trans = t;
-				atomic_inc(&cur_trans->use_count);
+				refcount_inc(&cur_trans->use_count);
 				ret = 0;
 				break;
 			}
@@ -763,7 +763,7 @@ int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid)
 				if (t->state == TRANS_STATE_COMPLETED)
 					break;
 				cur_trans = t;
-				atomic_inc(&cur_trans->use_count);
+				refcount_inc(&cur_trans->use_count);
 				break;
 			}
 		}
@@ -1833,7 +1833,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
 
 	/* take transaction reference */
 	cur_trans = trans->transaction;
-	atomic_inc(&cur_trans->use_count);
+	refcount_inc(&cur_trans->use_count);
 
 	btrfs_end_transaction(trans);
 
@@ -2009,7 +2009,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 	spin_lock(&fs_info->trans_lock);
 	if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
 		spin_unlock(&fs_info->trans_lock);
-		atomic_inc(&cur_trans->use_count);
+		refcount_inc(&cur_trans->use_count);
 		ret = btrfs_end_transaction(trans);
 
 		wait_for_commit(cur_trans);
@@ -2029,7 +2029,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 		prev_trans = list_entry(cur_trans->list.prev,
 					struct btrfs_transaction, list);
 		if (prev_trans->state != TRANS_STATE_COMPLETED) {
-			atomic_inc(&prev_trans->use_count);
+			refcount_inc(&prev_trans->use_count);
 			spin_unlock(&fs_info->trans_lock);
 
 			wait_for_commit(prev_trans);
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 5dfb559..2d9ad36 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -18,6 +18,7 @@
 
 #ifndef __BTRFS_TRANSACTION__
 #define __BTRFS_TRANSACTION__
+#include <linux/refcount.h>
 #include "btrfs_inode.h"
 #include "delayed-ref.h"
 #include "ctree.h"
@@ -49,7 +50,7 @@ struct btrfs_transaction {
 	 * transaction can end
 	 */
 	atomic_t num_writers;
-	atomic_t use_count;
+	refcount_t use_count;
 	atomic_t pending_ordered;
 
 	unsigned long flags;
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index f10bf52..fdcc03e 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4187,7 +4187,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
 		if (em->generation <= test_gen)
 			continue;
 		/* Need a ref to keep it from getting evicted from cache */
-		atomic_inc(&em->refs);
+		refcount_inc(&em->refs);
 		set_bit(EXTENT_FLAG_LOGGING, &em->flags);
 		list_add_tail(&em->list, &extents);
 		num++;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 3c3c69c..c6b0424 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4833,7 +4833,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 	ret = add_extent_mapping(em_tree, em, 0);
 	if (!ret) {
 		list_add_tail(&em->list, &trans->transaction->pending_chunks);
-		atomic_inc(&em->refs);
+		refcount_inc(&em->refs);
 	}
 	write_unlock(&em_tree->lock);
 	if (ret) {
@@ -5297,22 +5297,22 @@ static struct btrfs_bio *alloc_btrfs_bio(int total_stripes, int real_stripes)
 		GFP_NOFS|__GFP_NOFAIL);
 
 	atomic_set(&bbio->error, 0);
-	atomic_set(&bbio->refs, 1);
+	refcount_set(&bbio->refs, 1);
 
 	return bbio;
 }
 
 void btrfs_get_bbio(struct btrfs_bio *bbio)
 {
-	WARN_ON(!atomic_read(&bbio->refs));
-	atomic_inc(&bbio->refs);
+	WARN_ON(!refcount_read(&bbio->refs));
+	refcount_inc(&bbio->refs);
 }
 
 void btrfs_put_bbio(struct btrfs_bio *bbio)
 {
 	if (!bbio)
 		return;
-	if (atomic_dec_and_test(&bbio->refs))
+	if (refcount_dec_and_test(&bbio->refs))
 		kfree(bbio);
 }
 
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 24ba6bc..0ef3f5c 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -298,7 +298,7 @@ struct btrfs_bio;
 typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err);
 
 struct btrfs_bio {
-	atomic_t refs;
+	refcount_t refs;
 	atomic_t stripes_pending;
 	struct btrfs_fs_info *fs_info;
 	u64 map_type; /* get from map_lookup->type */
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 3ff867f..341864e 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -109,7 +109,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 
 	ASSERTCMP(fsdef->backer, ==, NULL);
 
-	atomic_set(&fsdef->usage, 1);
+	refcount_set(&fsdef->usage, 1);
 	fsdef->type = FSCACHE_COOKIE_TYPE_INDEX;
 
 	_debug("- fsdef %p", fsdef);
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index e7f16a7..d3f87c3 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -51,7 +51,7 @@ static struct fscache_object *cachefiles_alloc_object(
 	ASSERTCMP(object->backer, ==, NULL);
 
 	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
-	atomic_set(&object->usage, 1);
+	refcount_set(&object->usage, 1);
 
 	fscache_object_init(&object->fscache, cookie, &cache->cache);
 
@@ -182,13 +182,13 @@ struct fscache_object *cachefiles_grab_object(struct fscache_object *_object)
 	struct cachefiles_object *object =
 		container_of(_object, struct cachefiles_object, fscache);
 
-	_enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage));
+	_enter("{OBJ%x,%d}", _object->debug_id, refcount_read(&object->usage));
 
 #ifdef CACHEFILES_DEBUG_SLAB
-	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
+	ASSERT((refcount_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
 #endif
 
-	atomic_inc(&object->usage);
+	refcount_inc(&object->usage);
 	return &object->fscache;
 }
 
@@ -261,13 +261,13 @@ static void cachefiles_drop_object(struct fscache_object *_object)
 	object = container_of(_object, struct cachefiles_object, fscache);
 
 	_enter("{OBJ%x,%d}",
-	       object->fscache.debug_id, atomic_read(&object->usage));
+	       object->fscache.debug_id, refcount_read(&object->usage));
 
 	cache = container_of(object->fscache.cache,
 			     struct cachefiles_cache, cache);
 
 #ifdef CACHEFILES_DEBUG_SLAB
-	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
+	ASSERT((refcount_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
 #endif
 
 	/* We need to tidy the object up if we did in fact manage to open it.
@@ -319,16 +319,16 @@ static void cachefiles_put_object(struct fscache_object *_object)
 	object = container_of(_object, struct cachefiles_object, fscache);
 
 	_enter("{OBJ%x,%d}",
-	       object->fscache.debug_id, atomic_read(&object->usage));
+	       object->fscache.debug_id, refcount_read(&object->usage));
 
 #ifdef CACHEFILES_DEBUG_SLAB
-	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
+	ASSERT((refcount_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
 #endif
 
 	ASSERTIFCMP(object->fscache.parent,
 		    object->fscache.parent->n_children, >, 0);
 
-	if (atomic_dec_and_test(&object->usage)) {
+	if (refcount_dec_and_test(&object->usage)) {
 		_debug("- kill object OBJ%x", object->fscache.debug_id);
 
 		ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index cd1effe..61771e6 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -21,6 +21,7 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
+#include <linux/refcount.h>
 
 struct cachefiles_cache;
 struct cachefiles_object;
@@ -43,7 +44,7 @@ struct cachefiles_object {
 	loff_t				i_size;		/* object size */
 	unsigned long			flags;
 #define CACHEFILES_OBJECT_ACTIVE	0		/* T if marked active */
-	atomic_t			usage;		/* object usage count */
+	refcount_t			usage;		/* object usage count */
 	uint8_t				type;		/* object type */
 	uint8_t				new;		/* T if object new */
 	spinlock_t			work_lock;
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 41df8a2..e3bc512 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -197,7 +197,7 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
 		cachefiles_printk_object(object, xobject);
 		BUG();
 	}
-	atomic_inc(&xobject->usage);
+	refcount_inc(&xobject->usage);
 	write_unlock(&cache->active_lock);
 
 	if (test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index afbdc41..c987de6 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -692,7 +692,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
 			     struct cachefiles_cache, cache);
 
 	_enter("{OBJ%x,%d},,%d,,",
-	       object->fscache.debug_id, atomic_read(&op->op.usage),
+	       object->fscache.debug_id, refcount_read(&op->op.usage),
 	       *nr_pages);
 
 	if (!object->backer)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index baea866..e3a84a0 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1382,7 +1382,7 @@ static void __ceph_flush_snaps(struct ceph_inode_info *ci,
 		first_tid = cf->tid + 1;
 
 		capsnap = container_of(cf, struct ceph_cap_snap, cap_flush);
-		atomic_inc(&capsnap->nref);
+		refcount_inc(&capsnap->nref);
 		spin_unlock(&ci->i_ceph_lock);
 
 		dout("__flush_snaps %p capsnap %p tid %llu %s\n",
@@ -2197,7 +2197,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
 			     inode, capsnap, cf->tid,
 			     ceph_cap_string(capsnap->dirty));
 
-			atomic_inc(&capsnap->nref);
+			refcount_inc(&capsnap->nref);
 			spin_unlock(&ci->i_ceph_lock);
 
 			ret = __send_flush_snap(inode, session, capsnap, cap->mseq,
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 045d30d..3e2055b 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -8,6 +8,7 @@
 #include <linux/namei.h>
 #include <linux/writeback.h>
 #include <linux/falloc.h>
+#include <linux/refcount.h>
 
 #include "super.h"
 #include "mds_client.h"
@@ -609,7 +610,7 @@ struct ceph_aio_request {
 	int error;
 	struct list_head osd_reqs;
 	unsigned num_reqs;
-	atomic_t pending_reqs;
+	refcount_t pending_reqs;
 	struct timespec mtime;
 	struct ceph_cap_flush *prealloc_cf;
 };
@@ -627,7 +628,7 @@ static void ceph_aio_complete(struct inode *inode,
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	int ret;
 
-	if (!atomic_dec_and_test(&aio_req->pending_reqs))
+	if (!refcount_dec_and_test(&aio_req->pending_reqs))
 		return;
 
 	ret = aio_req->error;
@@ -988,7 +989,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
 		if (aio_req) {
 			aio_req->total_len += len;
 			aio_req->num_reqs++;
-			atomic_inc(&aio_req->pending_reqs);
+			refcount_inc(&aio_req->pending_reqs);
 
 			req->r_callback = ceph_aio_complete_req;
 			req->r_inode = inode;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 4f49253..939359f 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -377,9 +377,9 @@ const char *ceph_session_state_name(int s)
 
 static struct ceph_mds_session *get_session(struct ceph_mds_session *s)
 {
-	if (atomic_inc_not_zero(&s->s_ref)) {
+	if (refcount_inc_not_zero(&s->s_ref)) {
 		dout("mdsc get_session %p %d -> %d\n", s,
-		     atomic_read(&s->s_ref)-1, atomic_read(&s->s_ref));
+		     refcount_read(&s->s_ref)-1, refcount_read(&s->s_ref));
 		return s;
 	} else {
 		dout("mdsc get_session %p 0 -- FAIL", s);
@@ -390,8 +390,8 @@ static struct ceph_mds_session *get_session(struct ceph_mds_session *s)
 void ceph_put_mds_session(struct ceph_mds_session *s)
 {
 	dout("mdsc put_session %p %d -> %d\n", s,
-	     atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1);
-	if (atomic_dec_and_test(&s->s_ref)) {
+	     refcount_read(&s->s_ref), refcount_read(&s->s_ref)-1);
+	if (refcount_dec_and_test(&s->s_ref)) {
 		if (s->s_auth.authorizer)
 			ceph_auth_destroy_authorizer(s->s_auth.authorizer);
 		kfree(s);
@@ -410,7 +410,7 @@ struct ceph_mds_session *__ceph_lookup_mds_session(struct ceph_mds_client *mdsc,
 		return NULL;
 	session = mdsc->sessions[mds];
 	dout("lookup_mds_session %p %d\n", session,
-	     atomic_read(&session->s_ref));
+	     refcount_read(&session->s_ref));
 	get_session(session);
 	return session;
 }
@@ -465,7 +465,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
 	INIT_LIST_HEAD(&s->s_caps);
 	s->s_nr_caps = 0;
 	s->s_trim_caps = 0;
-	atomic_set(&s->s_ref, 1);
+	refcount_set(&s->s_ref, 1);
 	INIT_LIST_HEAD(&s->s_waiting);
 	INIT_LIST_HEAD(&s->s_unsafe);
 	s->s_num_cap_releases = 0;
@@ -493,7 +493,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
 	}
 	mdsc->sessions[mds] = s;
 	atomic_inc(&mdsc->num_sessions);
-	atomic_inc(&s->s_ref);  /* one ref to sessions[], one to caller */
+	refcount_inc(&s->s_ref);  /* one ref to sessions[], one to caller */
 
 	ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds,
 		      ceph_mdsmap_get_addr(mdsc->mdsmap, mds));
@@ -1955,7 +1955,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
 
 	if (req->r_pagelist) {
 		struct ceph_pagelist *pagelist = req->r_pagelist;
-		atomic_inc(&pagelist->refcnt);
+		refcount_inc(&pagelist->refcnt);
 		ceph_msg_data_add_pagelist(msg, pagelist);
 		msg->hdr.data_len = cpu_to_le32(pagelist->length);
 	} else {
@@ -3840,7 +3840,7 @@ static struct ceph_connection *con_get(struct ceph_connection *con)
 	struct ceph_mds_session *s = con->private;
 
 	if (get_session(s)) {
-		dout("mdsc con_get %p ok (%d)\n", s, atomic_read(&s->s_ref));
+		dout("mdsc con_get %p ok (%d)\n", s, refcount_read(&s->s_ref));
 		return con;
 	}
 	dout("mdsc con_get %p FAIL\n", s);
@@ -3851,7 +3851,7 @@ static void con_put(struct ceph_connection *con)
 {
 	struct ceph_mds_session *s = con->private;
 
-	dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref) - 1);
+	dout("mdsc con_put %p (%d)\n", s, refcount_read(&s->s_ref) - 1);
 	ceph_put_mds_session(s);
 }
 
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 3c6f77b..d55da01 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -7,6 +7,7 @@
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/types.h>
 #include <linux/ceph/messenger.h>
@@ -156,7 +157,7 @@ struct ceph_mds_session {
 	unsigned long     s_renew_requested; /* last time we sent a renew req */
 	u64               s_renew_seq;
 
-	atomic_t          s_ref;
+	refcount_t          s_ref;
 	struct list_head  s_waiting;  /* waiting requests */
 	struct list_head  s_unsafe;   /* unsafe requests */
 };
@@ -368,7 +369,7 @@ __ceph_lookup_mds_session(struct ceph_mds_client *, int mds);
 static inline struct ceph_mds_session *
 ceph_get_mds_session(struct ceph_mds_session *s)
 {
-	atomic_inc(&s->s_ref);
+	refcount_inc(&s->s_ref);
 	return s;
 }
 
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 8f8b41c..dab5d67 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -519,7 +519,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
 	     capsnap->need_flush ? "" : "no_flush");
 	ihold(inode);
 
-	atomic_set(&capsnap->nref, 1);
+	refcount_set(&capsnap->nref, 1);
 	INIT_LIST_HEAD(&capsnap->ci_item);
 
 	capsnap->follows = old_snapc->seq;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 3373b61..bda6326 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -14,6 +14,7 @@
 #include <linux/writeback.h>
 #include <linux/slab.h>
 #include <linux/posix_acl.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/libceph.h>
 
@@ -162,7 +163,7 @@ struct ceph_cap_flush {
  * data before flushing the snapped state (tracked here) back to the MDS.
  */
 struct ceph_cap_snap {
-	atomic_t nref;
+	refcount_t nref;
 	struct list_head ci_item;
 
 	struct ceph_cap_flush cap_flush;
@@ -191,7 +192,7 @@ struct ceph_cap_snap {
 
 static inline void ceph_put_cap_snap(struct ceph_cap_snap *capsnap)
 {
-	if (atomic_dec_and_test(&capsnap->nref)) {
+	if (refcount_dec_and_test(&capsnap->nref)) {
 		if (capsnap->xattr_blob)
 			ceph_buffer_put(capsnap->xattr_blob);
 		kfree(capsnap);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 70f4e65..8e20e00 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -101,7 +101,7 @@ cifs_sb_active(struct super_block *sb)
 	struct cifs_sb_info *server = CIFS_SB(sb);
 
 	if (atomic_inc_return(&server->active) == 1)
-		atomic_inc(&sb->s_active);
+		refcount_inc(&sb->s_active);
 }
 
 void
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7ea8a33..14c534d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -28,6 +28,7 @@
 #include "cifsacl.h"
 #include <crypto/internal/hash.h>
 #include <linux/scatterlist.h>
+#include <linux/refcount.h>
 #include <uapi/linux/cifs/cifs_mount.h>
 #ifdef CONFIG_CIFS_SMB2
 #include "smb2pdu.h"
@@ -968,7 +969,7 @@ struct tcon_link {
 #define TCON_LINK_PENDING	1
 #define TCON_LINK_IN_TREE	2
 	unsigned long		tl_time;
-	atomic_t		tl_count;
+	refcount_t		tl_count;
 	struct cifs_tcon	*tl_tcon;
 };
 
@@ -986,7 +987,7 @@ static inline struct tcon_link *
 cifs_get_tlink(struct tcon_link *tlink)
 {
 	if (tlink && !IS_ERR(tlink))
-		atomic_inc(&tlink->tl_count);
+		refcount_inc(&tlink->tl_count);
 	return tlink;
 }
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 35ae49e..b18920f 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2808,7 +2808,7 @@ cifs_put_tlink(struct tcon_link *tlink)
 	if (!tlink || IS_ERR(tlink))
 		return;
 
-	if (!atomic_dec_and_test(&tlink->tl_count) ||
+	if (!refcount_dec_and_test(&tlink->tl_count) ||
 	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
 		tlink->tl_time = jiffies;
 		return;
@@ -4349,7 +4349,7 @@ cifs_prune_tlinks(struct work_struct *work)
 		tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
 
 		if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
-		    atomic_read(&tlink->tl_count) != 0 ||
+		    refcount_read(&tlink->tl_count) != 0 ||
 		    time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
 			continue;
 
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 7ab5be7..c6ab340 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1950,7 +1950,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
 	}
 
 	cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
-		 full_path, inode, inode->i_count.counter,
+		 full_path, inode, atomic_read(&inode->i_count),
 		 dentry, cifs_get_time(dentry), jiffies);
 
 	if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 108df2e..fba89ab 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -164,7 +164,7 @@ struct pts_fs_info *devpts_acquire(struct file *filp)
 	/*
 	 * pty code needs to hold extra references in case of last /dev/tty close
 	 */
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	result = DEVPTS_SB(sb);
 
 out:
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 8f48769..b9fc36d 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -266,7 +266,7 @@ static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl,
 				sizeof(struct posix_acl_entry);
 		clone = kmemdup(acl, size, flags);
 		if (clone)
-			atomic_set(&clone->a_refcount, 1);
+			refcount_set(&clone->a_refcount, 1);
 	}
 	return clone;
 }
diff --git a/fs/fscache/cache.c b/fs/fscache/cache.c
index 56cce7f..ca6e282 100644
--- a/fs/fscache/cache.c
+++ b/fs/fscache/cache.c
@@ -33,7 +33,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
 
 	list_for_each_entry(tag, &fscache_cache_tag_list, link) {
 		if (strcmp(tag->name, name) == 0) {
-			atomic_inc(&tag->usage);
+			refcount_inc(&tag->usage);
 			up_read(&fscache_addremove_sem);
 			return tag;
 		}
@@ -47,7 +47,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
 		/* return a dummy tag if out of memory */
 		return ERR_PTR(-ENOMEM);
 
-	atomic_set(&xtag->usage, 1);
+	refcount_set(&xtag->usage, 1);
 	strcpy(xtag->name, name);
 
 	/* write lock, search again and add if still not present */
@@ -55,7 +55,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
 
 	list_for_each_entry(tag, &fscache_cache_tag_list, link) {
 		if (strcmp(tag->name, name) == 0) {
-			atomic_inc(&tag->usage);
+			refcount_inc(&tag->usage);
 			up_write(&fscache_addremove_sem);
 			kfree(xtag);
 			return tag;
@@ -75,7 +75,7 @@ void __fscache_release_cache_tag(struct fscache_cache_tag *tag)
 	if (tag != ERR_PTR(-ENOMEM)) {
 		down_write(&fscache_addremove_sem);
 
-		if (atomic_dec_and_test(&tag->usage))
+		if (refcount_dec_and_test(&tag->usage))
 			list_del_init(&tag->link);
 		else
 			tag = NULL;
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index de67745..eb84c95 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -38,7 +38,7 @@ void fscache_operation_init(struct fscache_operation *op,
 			    fscache_operation_release_t release)
 {
 	INIT_WORK(&op->work, fscache_op_work_func);
-	atomic_set(&op->usage, 1);
+	refcount_set(&op->usage, 1);
 	op->state = FSCACHE_OP_ST_INITIALISED;
 	op->debug_id = atomic_inc_return(&fscache_op_debug_id);
 	op->processor = processor;
@@ -60,19 +60,19 @@ EXPORT_SYMBOL(fscache_operation_init);
 void fscache_enqueue_operation(struct fscache_operation *op)
 {
 	_enter("{OBJ%x OP%x,%u}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERT(list_empty(&op->pend_link));
 	ASSERT(op->processor != NULL);
 	ASSERT(fscache_object_is_available(op->object));
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
 
 	fscache_stat(&fscache_n_op_enqueue);
 	switch (op->flags & FSCACHE_OP_TYPE) {
 	case FSCACHE_OP_ASYNC:
 		_debug("queue async");
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		if (!queue_work(fscache_op_wq, &op->work))
 			fscache_put_operation(op);
 		break;
@@ -156,7 +156,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 	_enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
 
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 	ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -183,11 +183,11 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 		object->n_exclusive++;	/* reads and writes must wait */
 
 		if (object->n_in_progress > 0) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 		} else if (!list_empty(&object->pending_ops)) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 			fscache_start_operations(object);
@@ -203,7 +203,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 		op->object = object;
 		object->n_ops++;
 		object->n_exclusive++;	/* reads and writes must wait */
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		list_add_tail(&op->pend_link, &object->pending_ops);
 		fscache_stat(&fscache_n_op_pend);
 		ret = 0;
@@ -238,10 +238,10 @@ int fscache_submit_op(struct fscache_object *object,
 	int ret;
 
 	_enter("{OBJ%x OP%x},{%u}",
-	       object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 	ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -267,11 +267,11 @@ int fscache_submit_op(struct fscache_object *object,
 		object->n_ops++;
 
 		if (object->n_exclusive > 0) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 		} else if (!list_empty(&object->pending_ops)) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 			fscache_start_operations(object);
@@ -283,7 +283,7 @@ int fscache_submit_op(struct fscache_object *object,
 	} else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
 		op->object = object;
 		object->n_ops++;
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		list_add_tail(&op->pend_link, &object->pending_ops);
 		fscache_stat(&fscache_n_op_pend);
 		ret = 0;
@@ -359,7 +359,7 @@ int fscache_cancel_op(struct fscache_operation *op,
 
 	ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING);
 	ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 
@@ -481,11 +481,11 @@ void fscache_put_operation(struct fscache_operation *op)
 	struct fscache_cache *cache;
 
 	_enter("{OBJ%x OP%x,%d}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
-	if (!atomic_dec_and_test(&op->usage))
+	if (!refcount_dec_and_test(&op->usage))
 		return;
 
 	_debug("PUT OP");
@@ -569,7 +569,7 @@ void fscache_operation_gc(struct work_struct *work)
 		       object->debug_id, op->debug_id);
 		fscache_stat(&fscache_n_op_gc);
 
-		ASSERTCMP(atomic_read(&op->usage), ==, 0);
+		ASSERTCMP(refcount_read(&op->usage), ==, 0);
 		ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD);
 
 		ASSERTCMP(object->n_ops, >, 0);
@@ -599,7 +599,7 @@ void fscache_op_work_func(struct work_struct *work)
 	unsigned long start;
 
 	_enter("{OBJ%x OP%x,%d}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERT(op->processor != NULL);
 	start = jiffies;
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index c8c4f79..352393c 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -774,7 +774,7 @@ static void fscache_write_op(struct fscache_operation *_op)
 	void *results[1];
 	int ret;
 
-	_enter("{OP%x,%d}", op->op.debug_id, atomic_read(&op->op.usage));
+	_enter("{OP%x,%d}", op->op.debug_id, refcount_read(&op->op.usage));
 
 	spin_lock(&object->lock);
 	cookie = object->cookie;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 70ea57c..a01e042 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -44,7 +44,7 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages,
 	INIT_LIST_HEAD(&req->list);
 	INIT_LIST_HEAD(&req->intr_entry);
 	init_waitqueue_head(&req->waitq);
-	atomic_set(&req->count, 1);
+	refcount_set(&req->count, 1);
 	req->pages = pages;
 	req->page_descs = page_descs;
 	req->max_pages = npages;
@@ -101,14 +101,14 @@ void fuse_request_free(struct fuse_req *req)
 
 void __fuse_get_request(struct fuse_req *req)
 {
-	atomic_inc(&req->count);
+	refcount_inc(&req->count);
 }
 
 /* Must be called with > 1 refcount */
 static void __fuse_put_request(struct fuse_req *req)
 {
-	BUG_ON(atomic_read(&req->count) < 2);
-	atomic_dec(&req->count);
+	BUG_ON(refcount_read(&req->count) < 2);
+	refcount_dec(&req->count);
 }
 
 static void fuse_req_init_context(struct fuse_req *req)
@@ -263,7 +263,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
 
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
-	if (atomic_dec_and_test(&req->count)) {
+	if (refcount_dec_and_test(&req->count)) {
 		if (test_bit(FR_BACKGROUND, &req->flags)) {
 			/*
 			 * We get here in the unlikely case that a background
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2401c5d..af9c53f 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -58,7 +58,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
 	}
 
 	INIT_LIST_HEAD(&ff->write_entry);
-	atomic_set(&ff->count, 0);
+	refcount_set(&ff->count, 0);
 	RB_CLEAR_NODE(&ff->polled_node);
 	init_waitqueue_head(&ff->poll_wait);
 
@@ -77,7 +77,7 @@ void fuse_file_free(struct fuse_file *ff)
 
 struct fuse_file *fuse_file_get(struct fuse_file *ff)
 {
-	atomic_inc(&ff->count);
+	refcount_inc(&ff->count);
 	return ff;
 }
 
@@ -88,7 +88,7 @@ static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
 
 static void fuse_file_put(struct fuse_file *ff, bool sync)
 {
-	if (atomic_dec_and_test(&ff->count)) {
+	if (refcount_dec_and_test(&ff->count)) {
 		struct fuse_req *req = ff->reserved_req;
 
 		if (ff->fc->no_open) {
@@ -297,7 +297,7 @@ static int fuse_release(struct inode *inode, struct file *file)
 
 void fuse_sync_release(struct fuse_file *ff, int flags)
 {
-	WARN_ON(atomic_read(&ff->count) > 1);
+	WARN_ON(refcount_read(&ff->count) > 1);
 	fuse_prepare_release(ff, flags, FUSE_RELEASE);
 	__set_bit(FR_FORCE, &ff->reserved_req->flags);
 	__clear_bit(FR_BACKGROUND, &ff->reserved_req->flags);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 052f8d3..e2769a1 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -24,6 +24,7 @@
 #include <linux/workqueue.h>
 #include <linux/kref.h>
 #include <linux/xattr.h>
+#include <linux/refcount.h>
 
 /** Max number of pages that can be used in a single read request */
 #define FUSE_MAX_PAGES_PER_REQ 32
@@ -137,7 +138,7 @@ struct fuse_file {
 	u64 nodeid;
 
 	/** Refcount */
-	atomic_t count;
+	refcount_t count;
 
 	/** FOPEN_* flags returned by open */
 	u32 open_flags;
@@ -306,7 +307,7 @@ struct fuse_req {
 	struct list_head intr_entry;
 
 	/** refcount */
-	atomic_t count;
+	refcount_t count;
 
 	/** Unique ID for the interrupt request */
 	u64 intr_unique;
@@ -448,7 +449,7 @@ struct fuse_conn {
 	spinlock_t lock;
 
 	/** Refcount */
-	atomic_t count;
+	refcount_t count;
 
 	/** Number of fuse_dev's */
 	atomic_t dev_count;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 6fe6a88..3961c5f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -608,7 +608,7 @@ void fuse_conn_init(struct fuse_conn *fc)
 	memset(fc, 0, sizeof(*fc));
 	spin_lock_init(&fc->lock);
 	init_rwsem(&fc->killsb);
-	atomic_set(&fc->count, 1);
+	refcount_set(&fc->count, 1);
 	atomic_set(&fc->dev_count, 1);
 	init_waitqueue_head(&fc->blocked_waitq);
 	init_waitqueue_head(&fc->reserved_req_waitq);
@@ -631,7 +631,7 @@ EXPORT_SYMBOL_GPL(fuse_conn_init);
 
 void fuse_conn_put(struct fuse_conn *fc)
 {
-	if (atomic_dec_and_test(&fc->count)) {
+	if (refcount_dec_and_test(&fc->count)) {
 		if (fc->destroy_req)
 			fuse_request_free(fc->destroy_req);
 		fc->release(fc);
@@ -641,7 +641,7 @@ EXPORT_SYMBOL_GPL(fuse_conn_put);
 
 struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
 {
-	atomic_inc(&fc->count);
+	refcount_inc(&fc->count);
 	return fc;
 }
 EXPORT_SYMBOL_GPL(fuse_conn_get);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index e3ee387..49af2ef 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -954,7 +954,7 @@ void gfs2_freeze_func(struct work_struct *work)
 	struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_freeze_work);
 	struct super_block *sb = sdp->sd_vfs;
 
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0,
 				   &freeze_gh);
 	if (error) {
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index d77d844..7b822e4 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -257,7 +257,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 	node->tree = tree;
 	node->this = cnid;
 	set_bit(HFS_BNODE_NEW, &node->flags);
-	atomic_set(&node->refcnt, 1);
+	refcount_set(&node->refcnt, 1);
 	hfs_dbg(BNODE_REFS, "new_node(%d:%d): 1\n",
 		node->tree->cnid, node->this);
 	init_waitqueue_head(&node->lock_wq);
@@ -302,7 +302,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
 	struct hfs_bnode **p;
 
 	hfs_dbg(BNODE_REFS, "remove_node(%d:%d): %d\n",
-		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		node->tree->cnid, node->this, refcount_read(&node->refcnt));
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
@@ -446,10 +446,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
 void hfs_bnode_get(struct hfs_bnode *node)
 {
 	if (node) {
-		atomic_inc(&node->refcnt);
+		refcount_inc(&node->refcnt);
 		hfs_dbg(BNODE_REFS, "get_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
+			refcount_read(&node->refcnt));
 	}
 }
 
@@ -462,9 +462,9 @@ void hfs_bnode_put(struct hfs_bnode *node)
 
 		hfs_dbg(BNODE_REFS, "put_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
-		BUG_ON(!atomic_read(&node->refcnt));
-		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
+			refcount_read(&node->refcnt));
+		BUG_ON(!refcount_read(&node->refcnt));
+		if (!refcount_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
 			if (!node->page[i])
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 37cdd95..5758e5e 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -144,10 +144,10 @@ void hfs_btree_close(struct hfs_btree *tree)
 	for (i = 0; i < NODE_HASH_SIZE; i++) {
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
-			if (atomic_read(&node->refcnt))
+			if (refcount_read(&node->refcnt))
 				pr_err("node %d:%d still has %d user(s)!\n",
 				       node->tree->cnid, node->this,
-				       atomic_read(&node->refcnt));
+				       refcount_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
 		}
diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h
index f6bd266..99b5fd3 100644
--- a/fs/hfs/btree.h
+++ b/fs/hfs/btree.h
@@ -6,6 +6,7 @@
  * (C) 2003 Ardis Technologies <roman@ardistech.com>
  */
 
+#include <linux/refcount.h>
 #include "hfs_fs.h"
 
 typedef int (*btree_keycmp)(const btree_key *, const btree_key *);
@@ -57,7 +58,7 @@ struct hfs_bnode {
 	struct hfs_bnode *next_hash;
 	unsigned long flags;
 	wait_queue_head_t lock_wq;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	unsigned int page_offset;
 	struct page *page[0];
 };
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index f776acf..8ac61e4 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -98,7 +98,7 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
 		node = hfs_bnode_findhash(tree, nidx);
 		if (!node)
 			;
-		else if (atomic_read(&node->refcnt))
+		else if (refcount_read(&node->refcnt))
 			res = 0;
 		if (res && node) {
 			hfs_bnode_unhash(node);
@@ -113,7 +113,7 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
 			node = hfs_bnode_findhash(tree, nidx++);
 			if (!node)
 				continue;
-			if (atomic_read(&node->refcnt)) {
+			if (refcount_read(&node->refcnt)) {
 				res = 0;
 				break;
 			}
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index ce014ce..9abaf14 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -422,7 +422,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 	node->tree = tree;
 	node->this = cnid;
 	set_bit(HFS_BNODE_NEW, &node->flags);
-	atomic_set(&node->refcnt, 1);
+	refcount_set(&node->refcnt, 1);
 	hfs_dbg(BNODE_REFS, "new_node(%d:%d): 1\n",
 		node->tree->cnid, node->this);
 	init_waitqueue_head(&node->lock_wq);
@@ -468,7 +468,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
 	struct hfs_bnode **p;
 
 	hfs_dbg(BNODE_REFS, "remove_node(%d:%d): %d\n",
-		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		node->tree->cnid, node->this, refcount_read(&node->refcnt));
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
@@ -614,10 +614,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
 void hfs_bnode_get(struct hfs_bnode *node)
 {
 	if (node) {
-		atomic_inc(&node->refcnt);
+		refcount_inc(&node->refcnt);
 		hfs_dbg(BNODE_REFS, "get_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
+			refcount_read(&node->refcnt));
 	}
 }
 
@@ -630,9 +630,9 @@ void hfs_bnode_put(struct hfs_bnode *node)
 
 		hfs_dbg(BNODE_REFS, "put_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
-		BUG_ON(!atomic_read(&node->refcnt));
-		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
+			refcount_read(&node->refcnt));
+		BUG_ON(!refcount_read(&node->refcnt));
+		if (!refcount_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
 			if (!node->page[i])
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index d9d1a36..0823dca 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -265,11 +265,11 @@ void hfs_btree_close(struct hfs_btree *tree)
 	for (i = 0; i < NODE_HASH_SIZE; i++) {
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
-			if (atomic_read(&node->refcnt))
+			if (refcount_read(&node->refcnt))
 				pr_crit("node %d:%d "
 						"still has %d user(s)!\n",
 					node->tree->cnid, node->this,
-					atomic_read(&node->refcnt));
+					refcount_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
 		}
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 31d5e3f..44825c9 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -371,7 +371,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
 	mutex_lock(&sbi->vh_mutex);
 	cnid = (u32)(unsigned long)dentry->d_fsdata;
 	if (inode->i_ino == cnid &&
-	    atomic_read(&HFSPLUS_I(inode)->opencnt)) {
+	    refcount_read(&HFSPLUS_I(inode)->opencnt)) {
 		str.name = name;
 		str.len = sprintf(name, "temp%lu", inode->i_ino);
 		res = hfsplus_rename_cat(inode->i_ino,
@@ -394,7 +394,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
 	if (!inode->i_nlink) {
 		if (inode->i_ino != cnid) {
 			sbi->file_count--;
-			if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) {
+			if (!refcount_read(&HFSPLUS_I(inode)->opencnt)) {
 				res = hfsplus_delete_cat(inode->i_ino,
 							 sbi->hidden_dir,
 							 NULL);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index a3f03b2..8adb343 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -20,6 +20,7 @@
 #include <linux/mutex.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
+#include <linux/refcount.h>
 #include "hfsplus_raw.h"
 
 #define DBG_BNODE_REFS	0x00000001
@@ -115,7 +116,7 @@ struct hfs_bnode {
 	struct hfs_bnode *next_hash;
 	unsigned long flags;
 	wait_queue_head_t lock_wq;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	unsigned int page_offset;
 	struct page *page[0];
 };
@@ -206,7 +207,7 @@ static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
 
 
 struct hfsplus_inode_info {
-	atomic_t opencnt;
+	refcount_t opencnt;
 
 	/*
 	 * Extent allocation information, protected by extents_lock.
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 2e796f8..b7d74bb 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -94,7 +94,7 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
 		node = hfs_bnode_findhash(tree, nidx);
 		if (!node)
 			;
-		else if (atomic_read(&node->refcnt))
+		else if (refcount_read(&node->refcnt))
 			res = 0;
 		if (res && node) {
 			hfs_bnode_unhash(node);
@@ -110,7 +110,7 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
 			node = hfs_bnode_findhash(tree, nidx++);
 			if (!node)
 				continue;
-			if (atomic_read(&node->refcnt)) {
+			if (refcount_read(&node->refcnt)) {
 				res = 0;
 				break;
 			}
@@ -217,7 +217,7 @@ static int hfsplus_file_open(struct inode *inode, struct file *file)
 		inode = HFSPLUS_I(inode)->rsrc_inode;
 	if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
 		return -EOVERFLOW;
-	atomic_inc(&HFSPLUS_I(inode)->opencnt);
+	refcount_inc(&HFSPLUS_I(inode)->opencnt);
 	return 0;
 }
 
@@ -227,7 +227,7 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
 
 	if (HFSPLUS_IS_RSRC(inode))
 		inode = HFSPLUS_I(inode)->rsrc_inode;
-	if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) {
+	if (refcount_dec_and_test(&HFSPLUS_I(inode)->opencnt)) {
 		inode_lock(inode);
 		hfsplus_file_truncate(inode);
 		if (inode->i_flags & S_DEAD) {
@@ -372,7 +372,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
 	INIT_LIST_HEAD(&hip->open_dir_list);
 	spin_lock_init(&hip->open_dir_lock);
 	mutex_init(&hip->extents_lock);
-	atomic_set(&hip->opencnt, 0);
+	refcount_set(&hip->opencnt, 0);
 	hip->extent_state = 0;
 	hip->flags = 0;
 	hip->userflags = 0;
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 67aedf4..004e246 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -72,7 +72,7 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
 	HFSPLUS_I(inode)->flags = 0;
 	HFSPLUS_I(inode)->extent_state = 0;
 	HFSPLUS_I(inode)->rsrc_inode = NULL;
-	atomic_set(&HFSPLUS_I(inode)->opencnt, 0);
+	refcount_set(&HFSPLUS_I(inode)->opencnt, 0);
 
 	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
 	    inode->i_ino == HFSPLUS_ROOT_CNID) {
diff --git a/fs/inode.c b/fs/inode.c
index 88110fd..2aa022c 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -397,7 +397,8 @@ void __iget(struct inode *inode)
  */
 void ihold(struct inode *inode)
 {
-	WARN_ON(atomic_inc_return(&inode->i_count) < 2);
+	atomic_inc(&inode->i_count);
+	WARN_ON(atomic_read(&inode->i_count) < 2);
 }
 EXPORT_SYMBOL(ihold);
 
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index cf4c636..2227fea 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -480,8 +480,8 @@ static void kernfs_drain(struct kernfs_node *kn)
 void kernfs_get(struct kernfs_node *kn)
 {
 	if (kn) {
-		WARN_ON(!atomic_read(&kn->count));
-		atomic_inc(&kn->count);
+		WARN_ON(!refcount_read(&kn->count));
+		refcount_inc(&kn->count);
 	}
 }
 EXPORT_SYMBOL_GPL(kernfs_get);
@@ -497,7 +497,7 @@ void kernfs_put(struct kernfs_node *kn)
 	struct kernfs_node *parent;
 	struct kernfs_root *root;
 
-	if (!kn || !atomic_dec_and_test(&kn->count))
+	if (!kn || !refcount_dec_and_test(&kn->count))
 		return;
 	root = kernfs_root(kn);
  repeat:
@@ -528,7 +528,7 @@ void kernfs_put(struct kernfs_node *kn)
 
 	kn = parent;
 	if (kn) {
-		if (atomic_dec_and_test(&kn->count))
+		if (refcount_dec_and_test(&kn->count))
 			goto repeat;
 	} else {
 		/* just released the root kn, free @root too */
@@ -625,7 +625,7 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 		goto err_out2;
 	kn->ino = ret;
 
-	atomic_set(&kn->count, 1);
+	refcount_set(&kn->count, 1);
 	atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
 	RB_CLEAR_NODE(&kn->rb);
 
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index d5b149a..8d61bcf 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -319,7 +319,7 @@ struct super_block *kernfs_pin_sb(struct kernfs_root *root, const void *ns)
 	list_for_each_entry(info, &root->supers, node) {
 		if (info->ns == ns) {
 			sb = info->sb;
-			if (!atomic_inc_not_zero(&info->sb->s_active))
+			if (!refcount_inc_not_zero(&info->sb->s_active))
 				sb = ERR_PTR(-EINVAL);
 			break;
 		}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 1129520..d9991da 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -48,13 +48,13 @@ void nlmclnt_next_cookie(struct nlm_cookie *c)
 
 static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner)
 {
-	atomic_inc(&lockowner->count);
+	refcount_inc(&lockowner->count);
 	return lockowner;
 }
 
 static void nlm_put_lockowner(struct nlm_lockowner *lockowner)
 {
-	if (!atomic_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
+	if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
 		return;
 	list_del(&lockowner->list);
 	spin_unlock(&lockowner->host->h_lock);
@@ -105,7 +105,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_
 		res = __nlm_find_lockowner(host, owner);
 		if (res == NULL && new != NULL) {
 			res = new;
-			atomic_set(&new->count, 1);
+			refcount_set(&new->count, 1);
 			new->owner = owner;
 			new->pid = __nlm_alloc_pid(host);
 			new->host = nlm_get_host(host);
@@ -198,7 +198,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
 	for(;;) {
 		call = kzalloc(sizeof(*call), GFP_KERNEL);
 		if (call != NULL) {
-			atomic_set(&call->a_count, 1);
+			refcount_set(&call->a_count, 1);
 			locks_init_lock(&call->a_args.lock.fl);
 			locks_init_lock(&call->a_res.lock.fl);
 			call->a_host = nlm_get_host(host);
@@ -214,7 +214,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
 
 void nlmclnt_release_call(struct nlm_rqst *call)
 {
-	if (!atomic_dec_and_test(&call->a_count))
+	if (!refcount_dec_and_test(&call->a_count))
 		return;
 	nlmclnt_release_host(call->a_host);
 	nlmclnt_release_lockargs(call);
@@ -668,7 +668,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
 		goto out;
 	}
 
-	atomic_inc(&req->a_count);
+	refcount_inc(&req->a_count);
 	status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
 			NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
 	if (status < 0)
@@ -745,7 +745,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
 	nlmclnt_setlockargs(req, fl);
 	req->a_args.block = block;
 
-	atomic_inc(&req->a_count);
+	refcount_inc(&req->a_count);
 	status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
 			NLMPROC_CANCEL, &nlmclnt_cancel_ops);
 	if (status == 0 && req->a_res.status == nlm_lck_denied)
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index d716c99..c38f43e 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -113,7 +113,7 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
 	unsigned long now = jiffies;
 
 	if (nsm != NULL)
-		atomic_inc(&nsm->sm_count);
+		refcount_inc(&nsm->sm_count);
 	else {
 		host = NULL;
 		nsm = nsm_get_handle(ni->net, ni->sap, ni->salen,
@@ -150,7 +150,7 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
 	host->h_state      = 0;
 	host->h_nsmstate   = 0;
 	host->h_pidcount   = 0;
-	atomic_set(&host->h_count, 1);
+	refcount_set(&host->h_count, 1);
 	mutex_init(&host->h_mutex);
 	host->h_nextrebind = now + NLM_HOST_REBIND;
 	host->h_expires    = now + NLM_HOST_EXPIRE;
@@ -289,7 +289,7 @@ void nlmclnt_release_host(struct nlm_host *host)
 
 	WARN_ON_ONCE(host->h_server);
 
-	if (atomic_dec_and_test(&host->h_count)) {
+	if (refcount_dec_and_test(&host->h_count)) {
 		WARN_ON_ONCE(!list_empty(&host->h_lockowners));
 		WARN_ON_ONCE(!list_empty(&host->h_granted));
 		WARN_ON_ONCE(!list_empty(&host->h_reclaim));
@@ -409,7 +409,7 @@ void nlmsvc_release_host(struct nlm_host *host)
 	dprintk("lockd: release server host %s\n", host->h_name);
 
 	WARN_ON_ONCE(!host->h_server);
-	atomic_dec(&host->h_count);
+	refcount_dec(&host->h_count);
 }
 
 /*
@@ -503,7 +503,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
 {
 	if (host) {
 		dprintk("lockd: get host %s\n", host->h_name);
-		atomic_inc(&host->h_count);
+		refcount_inc(&host->h_count);
 		host->h_expires = jiffies + NLM_HOST_EXPIRE;
 	}
 	return host;
@@ -590,7 +590,7 @@ static void nlm_complain_hosts(struct net *net)
 		if (net && host->net != net)
 			continue;
 		dprintk("       %s (cnt %d use %d exp %ld net %p)\n",
-			host->h_name, atomic_read(&host->h_count),
+			host->h_name, refcount_read(&host->h_count),
 			host->h_inuse, host->h_expires, host->net);
 	}
 }
@@ -658,11 +658,11 @@ nlm_gc_hosts(struct net *net)
 	for_each_host_safe(host, next, chain, nlm_server_hosts) {
 		if (net && host->net != net)
 			continue;
-		if (atomic_read(&host->h_count) || host->h_inuse
+		if (refcount_read(&host->h_count) || host->h_inuse
 		 || time_before(jiffies, host->h_expires)) {
 			dprintk("nlm_gc_hosts skipping %s "
 				"(cnt %d use %d exp %ld net %p)\n",
-				host->h_name, atomic_read(&host->h_count),
+				host->h_name, refcount_read(&host->h_count),
 				host->h_inuse, host->h_expires, host->net);
 			continue;
 		}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 19166d4..0fcbcd6 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -189,7 +189,7 @@ void nsm_unmonitor(const struct nlm_host *host)
 	struct nsm_res	res;
 	int status;
 
-	if (atomic_read(&nsm->sm_count) == 1
+	if (refcount_read(&nsm->sm_count) == 1
 	 && nsm->sm_monitored && !nsm->sm_sticky) {
 		dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
 
@@ -277,7 +277,7 @@ static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
 	if (unlikely(new == NULL))
 		return NULL;
 
-	atomic_set(&new->sm_count, 1);
+	refcount_set(&new->sm_count, 1);
 	new->sm_name = (char *)(new + 1);
 	memcpy(nsm_addr(new), sap, salen);
 	new->sm_addrlen = salen;
@@ -335,13 +335,13 @@ struct nsm_handle *nsm_get_handle(const struct net *net,
 		cached = nsm_lookup_addr(&ln->nsm_handles, sap);
 
 	if (cached != NULL) {
-		atomic_inc(&cached->sm_count);
+		refcount_inc(&cached->sm_count);
 		spin_unlock(&nsm_lock);
 		kfree(new);
 		dprintk("lockd: found nsm_handle for %s (%s), "
 				"cnt %d\n", cached->sm_name,
 				cached->sm_addrbuf,
-				atomic_read(&cached->sm_count));
+				refcount_read(&cached->sm_count));
 		return cached;
 	}
 
@@ -386,12 +386,12 @@ struct nsm_handle *nsm_reboot_lookup(const struct net *net,
 		return cached;
 	}
 
-	atomic_inc(&cached->sm_count);
+	refcount_inc(&cached->sm_count);
 	spin_unlock(&nsm_lock);
 
 	dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
 			cached->sm_name, cached->sm_addrbuf,
-			atomic_read(&cached->sm_count));
+			refcount_read(&cached->sm_count));
 	return cached;
 }
 
@@ -402,7 +402,7 @@ struct nsm_handle *nsm_reboot_lookup(const struct net *net,
  */
 void nsm_release(struct nsm_handle *nsm)
 {
-	if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
+	if (refcount_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
 		list_del(&nsm->sm_link);
 		spin_unlock(&nsm_lock);
 		dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index fb26b9f..c1ffd6a 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -263,7 +263,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
 
 void nlmsvc_release_call(struct nlm_rqst *call)
 {
-	if (!atomic_dec_and_test(&call->a_count))
+	if (!refcount_dec_and_test(&call->a_count))
 		return;
 	nlmsvc_release_host(call->a_host);
 	kfree(call);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index b19be42..57a82de 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -89,7 +89,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key,
 
 	INIT_LIST_HEAD(&entry->e_list);
 	/* One ref for hash, one ref returned */
-	atomic_set(&entry->e_refcnt, 1);
+	refcount_set(&entry->e_refcnt, 1);
 	entry->e_key = key;
 	entry->e_block = block;
 	entry->e_reusable = reusable;
@@ -108,7 +108,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key,
 	spin_lock(&cache->c_list_lock);
 	list_add_tail(&entry->e_list, &cache->c_list);
 	/* Grab ref for LRU list */
-	atomic_inc(&entry->e_refcnt);
+	refcount_inc(&entry->e_refcnt);
 	cache->c_entry_count++;
 	spin_unlock(&cache->c_list_lock);
 
@@ -140,7 +140,7 @@ static struct mb_cache_entry *__entry_find(struct mb_cache *cache,
 		entry = hlist_bl_entry(node, struct mb_cache_entry,
 				       e_hash_list);
 		if (entry->e_key == key && entry->e_reusable) {
-			atomic_inc(&entry->e_refcnt);
+			refcount_inc(&entry->e_refcnt);
 			goto out;
 		}
 		node = node->next;
@@ -203,7 +203,7 @@ struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *cache, u32 key,
 	hlist_bl_lock(head);
 	hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
 		if (entry->e_key == key && entry->e_block == block) {
-			atomic_inc(&entry->e_refcnt);
+			refcount_inc(&entry->e_refcnt);
 			goto out;
 		}
 	}
@@ -239,7 +239,7 @@ void mb_cache_entry_delete_block(struct mb_cache *cache, u32 key,
 			if (!list_empty(&entry->e_list)) {
 				list_del_init(&entry->e_list);
 				cache->c_entry_count--;
-				atomic_dec(&entry->e_refcnt);
+				refcount_dec(&entry->e_refcnt);
 			}
 			spin_unlock(&cache->c_list_lock);
 			mb_cache_entry_put(cache, entry);
@@ -300,7 +300,7 @@ static unsigned long mb_cache_shrink(struct mb_cache *cache,
 		hlist_bl_lock(head);
 		if (!hlist_bl_unhashed(&entry->e_hash_list)) {
 			hlist_bl_del_init(&entry->e_hash_list);
-			atomic_dec(&entry->e_refcnt);
+			refcount_dec(&entry->e_refcnt);
 		}
 		hlist_bl_unlock(head);
 		if (mb_cache_entry_put(cache, entry))
@@ -397,11 +397,11 @@ void mb_cache_destroy(struct mb_cache *cache)
 	list_for_each_entry_safe(entry, next, &cache->c_list, e_list) {
 		if (!hlist_bl_unhashed(&entry->e_hash_list)) {
 			hlist_bl_del_init(&entry->e_hash_list);
-			atomic_dec(&entry->e_refcnt);
+			refcount_dec(&entry->e_refcnt);
 		} else
 			WARN_ON(1);
 		list_del(&entry->e_list);
-		WARN_ON(atomic_read(&entry->e_refcnt) != 1);
+		WARN_ON(refcount_read(&entry->e_refcnt) != 1);
 		mb_cache_entry_put(cache, entry);
 	}
 	kfree(cache->c_hash);
diff --git a/fs/mount.h b/fs/mount.h
index 2c856fc..4e77900 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -3,9 +3,10 @@
 #include <linux/poll.h>
 #include <linux/ns_common.h>
 #include <linux/fs_pin.h>
+#include <linux/refcount.h>
 
 struct mnt_namespace {
-	atomic_t		count;
+	refcount_t		count;
 	struct ns_common	ns;
 	struct mount *	root;
 	struct list_head	list;
@@ -111,7 +112,7 @@ static inline void detach_mounts(struct dentry *dentry)
 
 static inline void get_mnt_ns(struct mnt_namespace *ns)
 {
-	atomic_inc(&ns->count);
+	refcount_inc(&ns->count);
 }
 
 extern seqlock_t mount_lock;
diff --git a/fs/namespace.c b/fs/namespace.c
index b5b1259..550cff9 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1010,7 +1010,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 	    (!(flag & CL_EXPIRE) || list_empty(&old->mnt_expire)))
 		mnt->mnt.mnt_flags |= MNT_LOCKED;
 
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	mnt->mnt.mnt_sb = sb;
 	mnt->mnt.mnt_root = dget(root);
 	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
@@ -2837,7 +2837,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 	}
 	new_ns->ns.ops = &mntns_operations;
 	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
-	atomic_set(&new_ns->count, 1);
+	refcount_set(&new_ns->count, 1);
 	new_ns->root = NULL;
 	INIT_LIST_HEAD(&new_ns->list);
 	init_waitqueue_head(&new_ns->poll);
@@ -2964,7 +2964,7 @@ struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
 
 	/* trade a vfsmount reference for active sb one */
 	s = path.mnt->mnt_sb;
-	atomic_inc(&s->s_active);
+	refcount_inc(&s->s_active);
 	mntput(path.mnt);
 	/* lock the sucker */
 	down_write(&s->s_umount);
@@ -3227,7 +3227,7 @@ void __init mnt_init(void)
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-	if (!atomic_dec_and_test(&ns->count))
+	if (!refcount_dec_and_test(&ns->count))
 		return;
 	drop_collected_mounts(&ns->root->mnt);
 	free_mnt_ns(ns);
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
index f32f272..1bfb544 100644
--- a/fs/ncpfs/sock.c
+++ b/fs/ncpfs/sock.c
@@ -28,6 +28,7 @@
 #include <linux/ipx.h>
 #include <linux/poll.h>
 #include <linux/file.h>
+#include <linux/refcount.h>
 
 #include "ncp_fs.h"
 
@@ -58,7 +59,7 @@ static int _send(struct socket *sock, const void *buff, int len)
 struct ncp_request_reply {
 	struct list_head req;
 	wait_queue_head_t wq;
-	atomic_t refs;
+	refcount_t refs;
 	unsigned char* reply_buf;
 	size_t datalen;
 	int result;
@@ -80,7 +81,7 @@ static inline struct ncp_request_reply* ncp_alloc_req(void)
 		return NULL;
 
 	init_waitqueue_head(&req->wq);
-	atomic_set(&req->refs, (1));
+	refcount_set(&req->refs, (1));
 	req->status = RQ_IDLE;
 
 	return req;
@@ -88,12 +89,12 @@ static inline struct ncp_request_reply* ncp_alloc_req(void)
 
 static void ncp_req_get(struct ncp_request_reply *req)
 {
-	atomic_inc(&req->refs);
+	refcount_inc(&req->refs);
 }
 
 static void ncp_req_put(struct ncp_request_reply *req)
 {
-	if (atomic_dec_and_test(&req->refs))
+	if (refcount_dec_and_test(&req->refs))
 		kfree(req);
 }
 
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
index 6de1570..cf8ccb6 100644
--- a/fs/nfs/cache_lib.c
+++ b/fs/nfs/cache_lib.c
@@ -66,7 +66,7 @@ int nfs_cache_upcall(struct cache_detail *cd, char *entry_name)
  */
 void nfs_cache_defer_req_put(struct nfs_cache_defer_req *dreq)
 {
-	if (atomic_dec_and_test(&dreq->count))
+	if (refcount_dec_and_test(&dreq->count))
 		kfree(dreq);
 }
 
@@ -86,7 +86,7 @@ static struct cache_deferred_req *nfs_dns_cache_defer(struct cache_req *req)
 
 	dreq = container_of(req, struct nfs_cache_defer_req, req);
 	dreq->deferred_req.revisit = nfs_dns_cache_revisit;
-	atomic_inc(&dreq->count);
+	refcount_inc(&dreq->count);
 
 	return &dreq->deferred_req;
 }
@@ -98,7 +98,7 @@ struct nfs_cache_defer_req *nfs_cache_defer_req_alloc(void)
 	dreq = kzalloc(sizeof(*dreq), GFP_KERNEL);
 	if (dreq) {
 		init_completion(&dreq->completion);
-		atomic_set(&dreq->count, 1);
+		refcount_set(&dreq->count, 1);
 		dreq->req.defer = nfs_dns_cache_defer;
 	}
 	return dreq;
diff --git a/fs/nfs/cache_lib.h b/fs/nfs/cache_lib.h
index 4116d2c..02b378c 100644
--- a/fs/nfs/cache_lib.h
+++ b/fs/nfs/cache_lib.h
@@ -15,7 +15,7 @@ struct nfs_cache_defer_req {
 	struct cache_req req;
 	struct cache_deferred_req deferred_req;
 	struct completion completion;
-	atomic_t count;
+	refcount_t count;
 };
 
 extern int nfs_cache_upcall(struct cache_detail *cd, char *entry_name);
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 91a8d61..6c67d2e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -163,7 +163,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
 
 	clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
 
-	atomic_set(&clp->cl_count, 1);
+	refcount_set(&clp->cl_count, 1);
 	clp->cl_cons_state = NFS_CS_INITING;
 
 	memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen);
@@ -271,10 +271,10 @@ void nfs_put_client(struct nfs_client *clp)
 	if (!clp)
 		return;
 
-	dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count));
+	dprintk("--> nfs_put_client({%d})\n", refcount_read(&clp->cl_count));
 	nn = net_generic(clp->cl_net, nfs_net_id);
 
-	if (atomic_dec_and_lock(&clp->cl_count, &nn->nfs_client_lock)) {
+	if (refcount_dec_and_lock(&clp->cl_count, &nn->nfs_client_lock)) {
 		list_del(&clp->cl_share_link);
 		nfs_cb_idr_remove_locked(clp);
 		spin_unlock(&nn->nfs_client_lock);
@@ -319,7 +319,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
 							   sap))
 				continue;
 
-		atomic_inc(&clp->cl_count);
+		refcount_inc(&clp->cl_count);
 		return clp;
 	}
 	return NULL;
@@ -1029,7 +1029,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
 	/* Copy data from the source */
 	server->nfs_client = source->nfs_client;
 	server->destroy = source->destroy;
-	atomic_inc(&server->nfs_client->cl_count);
+	refcount_inc(&server->nfs_client->cl_count);
 	nfs_server_copy_userdata(server, source);
 
 	server->fsid = fattr->fsid;
@@ -1195,7 +1195,7 @@ static int nfs_server_list_show(struct seq_file *m, void *v)
 		   clp->rpc_ops->version,
 		   rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
 		   rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
-		   atomic_read(&clp->cl_count),
+		   refcount_read(&clp->cl_count),
 		   clp->cl_hostname);
 	rcu_read_unlock();
 
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index fad8104..0c95d2b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -145,7 +145,7 @@ struct nfs_cache_array_entry {
 };
 
 struct nfs_cache_array {
-	atomic_t refcount;
+	refcount_t refcount;
 	int size;
 	int eof_index;
 	u64 last_cookie;
@@ -201,7 +201,7 @@ void nfs_readdir_clear_array(struct page *page)
 	int i;
 
 	array = kmap_atomic(page);
-	if (atomic_dec_and_test(&array->refcount))
+	if (refcount_dec_and_test(&array->refcount))
 		for (i = 0; i < array->size; i++)
 			kfree(array->array[i].string.name);
 	kunmap_atomic(array);
@@ -210,7 +210,7 @@ void nfs_readdir_clear_array(struct page *page)
 static bool grab_page(struct page *page)
 {
 	struct nfs_cache_array *array = kmap_atomic(page);
-	bool res = atomic_inc_not_zero(&array->refcount);
+	bool res = refcount_inc_not_zero(&array->refcount);
 	kunmap_atomic(array);
 	return res;
 }
@@ -680,7 +680,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
 		goto out_label_free;
 	}
 	memset(array, 0, sizeof(struct nfs_cache_array));
-	atomic_set(&array->refcount, 1);
+	refcount_set(&array->refcount, 1);
 	array->eof_index = -1;
 
 	status = nfs_readdir_alloc_pages(pages, array_size);
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index a3fc48b..cf82247 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -498,10 +498,10 @@ filelayout_read_pagelist(struct nfs_pgio_header *hdr)
 		return PNFS_NOT_ATTEMPTED;
 
 	dprintk("%s USE DS: %s cl_count %d\n", __func__,
-		ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count));
+		ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count));
 
 	/* No multipath support. Use first DS */
-	atomic_inc(&ds->ds_clp->cl_count);
+	refcount_inc(&ds->ds_clp->cl_count);
 	hdr->ds_clp = ds->ds_clp;
 	hdr->ds_commit_idx = idx;
 	fh = nfs4_fl_select_ds_fh(lseg, j);
@@ -542,10 +542,10 @@ filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
 
 	dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n",
 		__func__, hdr->inode->i_ino, sync, (size_t) hdr->args.count,
-		offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count));
+		offset, ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count));
 
 	hdr->pgio_done_cb = filelayout_write_done_cb;
-	atomic_inc(&ds->ds_clp->cl_count);
+	refcount_inc(&ds->ds_clp->cl_count);
 	hdr->ds_clp = ds->ds_clp;
 	hdr->ds_commit_idx = idx;
 	fh = nfs4_fl_select_ds_fh(lseg, j);
@@ -1038,9 +1038,9 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
 		goto out_err;
 
 	dprintk("%s ino %lu, how %d cl_count %d\n", __func__,
-		data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count));
+		data->inode->i_ino, how, refcount_read(&ds->ds_clp->cl_count));
 	data->commit_done_cb = filelayout_commit_done_cb;
-	atomic_inc(&ds->ds_clp->cl_count);
+	refcount_inc(&ds->ds_clp->cl_count);
 	data->ds_clp = ds->ds_clp;
 	fh = select_ds_fh_from_commit(lseg, data->ds_commit_index);
 	if (fh)
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 0ca4af8..9be6afc 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -187,7 +187,7 @@ ff_layout_add_mirror(struct pnfs_layout_hdr *lo,
 			continue;
 		if (!ff_mirror_match_fh(mirror, pos))
 			continue;
-		if (atomic_inc_not_zero(&pos->ref)) {
+		if (refcount_inc_not_zero(&pos->ref)) {
 			spin_unlock(&inode->i_lock);
 			return pos;
 		}
@@ -218,7 +218,7 @@ static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags)
 	mirror = kzalloc(sizeof(*mirror), gfp_flags);
 	if (mirror != NULL) {
 		spin_lock_init(&mirror->lock);
-		atomic_set(&mirror->ref, 1);
+		refcount_set(&mirror->ref, 1);
 		INIT_LIST_HEAD(&mirror->mirrors);
 	}
 	return mirror;
@@ -242,7 +242,7 @@ static void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror)
 
 static void ff_layout_put_mirror(struct nfs4_ff_layout_mirror *mirror)
 {
-	if (mirror != NULL && atomic_dec_and_test(&mirror->ref))
+	if (mirror != NULL && refcount_dec_and_test(&mirror->ref))
 		ff_layout_free_mirror(mirror);
 }
 
@@ -1771,10 +1771,10 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
 	vers = nfs4_ff_layout_ds_version(lseg, idx);
 
 	dprintk("%s USE DS: %s cl_count %d vers %d\n", __func__,
-		ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count), vers);
+		ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count), vers);
 
 	hdr->pgio_done_cb = ff_layout_read_done_cb;
-	atomic_inc(&ds->ds_clp->cl_count);
+	refcount_inc(&ds->ds_clp->cl_count);
 	hdr->ds_clp = ds->ds_clp;
 	fh = nfs4_ff_layout_select_ds_fh(lseg, idx);
 	if (fh)
@@ -1830,11 +1830,11 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
 
 	dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d vers %d\n",
 		__func__, hdr->inode->i_ino, sync, (size_t) hdr->args.count,
-		offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count),
+		offset, ds->ds_remotestr, refcount_read(&ds->ds_clp->cl_count),
 		vers);
 
 	hdr->pgio_done_cb = ff_layout_write_done_cb;
-	atomic_inc(&ds->ds_clp->cl_count);
+	refcount_inc(&ds->ds_clp->cl_count);
 	hdr->ds_clp = ds->ds_clp;
 	hdr->ds_commit_idx = idx;
 	fh = nfs4_ff_layout_select_ds_fh(lseg, idx);
@@ -1899,11 +1899,11 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how)
 	vers = nfs4_ff_layout_ds_version(lseg, idx);
 
 	dprintk("%s ino %lu, how %d cl_count %d vers %d\n", __func__,
-		data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count),
+		data->inode->i_ino, how, refcount_read(&ds->ds_clp->cl_count),
 		vers);
 	data->commit_done_cb = ff_layout_commit_done_cb;
 	data->cred = ds_cred;
-	atomic_inc(&ds->ds_clp->cl_count);
+	refcount_inc(&ds->ds_clp->cl_count);
 	data->ds_clp = ds->ds_clp;
 	fh = select_ds_fh_from_commit(lseg, data->ds_commit_index);
 	if (fh)
@@ -2325,7 +2325,7 @@ ff_layout_mirror_prepare_stats(struct pnfs_layout_hdr *lo,
 		if (!test_and_clear_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags))
 			continue;
 		/* mirror refcount put in cleanup_layoutstats */
-		if (!atomic_inc_not_zero(&mirror->ref))
+		if (!refcount_inc_not_zero(&mirror->ref))
 			continue;
 		dev = &mirror->mirror_ds->id_node; 
 		memcpy(&devinfo->dev_id, &dev->deviceid, NFS4_DEVICEID4_SIZE);
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h
index f4f39b0..1b5d60b 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.h
+++ b/fs/nfs/flexfilelayout/flexfilelayout.h
@@ -13,6 +13,7 @@
 #define FF_FLAGS_NO_IO_THRU_MDS  2
 #define FF_FLAGS_NO_READ_IO      4
 
+#include <linux/refcount.h>
 #include "../pnfs.h"
 
 /* XXX: Let's filter out insanely large mirror count for now to avoid oom
@@ -81,7 +82,7 @@ struct nfs4_ff_layout_mirror {
 	nfs4_stateid			stateid;
 	struct rpc_cred	__rcu		*ro_cred;
 	struct rpc_cred	__rcu		*rw_cred;
-	atomic_t			ref;
+	refcount_t			ref;
 	spinlock_t			lock;
 	unsigned long			flags;
 	struct nfs4_ff_layoutstat	read_stat;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5ca4d96..2c29da9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -751,7 +751,7 @@ EXPORT_SYMBOL_GPL(nfs_getattr);
 
 static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
 {
-	atomic_set(&l_ctx->count, 1);
+	refcount_set(&l_ctx->count, 1);
 	l_ctx->lockowner = current->files;
 	INIT_LIST_HEAD(&l_ctx->list);
 	atomic_set(&l_ctx->io_count, 0);
@@ -765,7 +765,7 @@ static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context
 	do {
 		if (pos->lockowner != current->files)
 			continue;
-		atomic_inc(&pos->count);
+		refcount_inc(&pos->count);
 		return pos;
 	} while ((pos = list_entry(pos->list.next, typeof(*pos), list)) != head);
 	return NULL;
@@ -804,7 +804,7 @@ void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
 	struct nfs_open_context *ctx = l_ctx->open_context;
 	struct inode *inode = d_inode(ctx->dentry);
 
-	if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock))
+	if (!refcount_dec_and_lock(&l_ctx->count, &inode->i_lock))
 		return;
 	list_del(&l_ctx->list);
 	spin_unlock(&inode->i_lock);
@@ -881,7 +881,7 @@ EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
 struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
 {
 	if (ctx != NULL)
-		atomic_inc(&ctx->lock_context.count);
+		refcount_inc(&ctx->lock_context.count);
 	return ctx;
 }
 EXPORT_SYMBOL_GPL(get_nfs_open_context);
@@ -892,11 +892,11 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 	struct super_block *sb = ctx->dentry->d_sb;
 
 	if (!list_empty(&ctx->list)) {
-		if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+		if (!refcount_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
 			return;
 		list_del(&ctx->list);
 		spin_unlock(&inode->i_lock);
-	} else if (!atomic_dec_and_test(&ctx->lock_context.count))
+	} else if (!refcount_dec_and_test(&ctx->lock_context.count))
 		return;
 	if (inode != NULL)
 		NFS_PROTO(inode)->close_context(ctx, is_sync);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 6651658..8b1db33 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -22,6 +22,7 @@
 #define NFS4_MAX_LOOP_ON_RECOVER (10)
 
 #include <linux/seqlock.h>
+#include <linux/refcount.h>
 
 struct idmap;
 
@@ -107,7 +108,7 @@ struct nfs4_state_owner {
 	struct rpc_cred	     *so_cred;	 /* Associated cred */
 
 	spinlock_t	     so_lock;
-	atomic_t	     so_count;
+	refcount_t	     so_count;
 	unsigned long	     so_flags;
 	struct list_head     so_states;
 	struct nfs_seqid_counter so_seqid;
@@ -144,7 +145,7 @@ struct nfs4_lock_state {
 	unsigned long		ls_flags;
 	struct nfs_seqid_counter	ls_seqid;
 	nfs4_stateid		ls_stateid;
-	atomic_t		ls_count;
+	refcount_t		ls_count;
 	fl_owner_t		ls_owner;
 };
 
@@ -183,7 +184,7 @@ struct nfs4_state {
 	unsigned int n_wronly;		/* Number of write-only references */
 	unsigned int n_rdwr;		/* Number of read/write references */
 	fmode_t state;			/* State on the server (R,W, or RW) */
-	atomic_t count;
+	refcount_t count;
 };
 
 
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 5ae9d64..6984760 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -506,7 +506,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
 		/* If "pos" isn't marked ready, we can't trust the
 		 * remaining fields in "pos" */
 		if (pos->cl_cons_state > NFS_CS_READY) {
-			atomic_inc(&pos->cl_count);
+			refcount_inc(&pos->cl_count);
 			spin_unlock(&nn->nfs_client_lock);
 
 			nfs_put_client(prev);
@@ -541,7 +541,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
 		 * way that a SETCLIENTID_CONFIRM to pos can succeed is
 		 * if new and pos point to the same server:
 		 */
-		atomic_inc(&pos->cl_count);
+		refcount_inc(&pos->cl_count);
 		spin_unlock(&nn->nfs_client_lock);
 
 		nfs_put_client(prev);
@@ -558,7 +558,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
 			prev = NULL;
 			*result = pos;
 			dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
-				__func__, pos, atomic_read(&pos->cl_count));
+				__func__, pos, refcount_read(&pos->cl_count));
 			goto out;
 		case -ERESTARTSYS:
 		case -ETIMEDOUT:
@@ -750,7 +750,7 @@ int nfs41_walk_client_list(struct nfs_client *new,
 		 * ID and serverowner fields.  Wait for CREATE_SESSION
 		 * to finish. */
 		if (pos->cl_cons_state > NFS_CS_READY) {
-			atomic_inc(&pos->cl_count);
+			refcount_inc(&pos->cl_count);
 			spin_unlock(&nn->nfs_client_lock);
 
 			nfs_put_client(prev);
@@ -784,11 +784,11 @@ int nfs41_walk_client_list(struct nfs_client *new,
 		if (!nfs4_match_client_owner_id(pos, new))
 			continue;
 found:
-		atomic_inc(&pos->cl_count);
+		refcount_inc(&pos->cl_count);
 		*result = pos;
 		status = 0;
 		dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
-			__func__, pos, atomic_read(&pos->cl_count));
+			__func__, pos, refcount_read(&pos->cl_count));
 		break;
 	}
 
@@ -820,7 +820,7 @@ nfs4_find_client_ident(struct net *net, int cb_ident)
 	spin_lock(&nn->nfs_client_lock);
 	clp = idr_find(&nn->cb_ident_idr, cb_ident);
 	if (clp)
-		atomic_inc(&clp->cl_count);
+		refcount_inc(&clp->cl_count);
 	spin_unlock(&nn->nfs_client_lock);
 	return clp;
 }
@@ -875,7 +875,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
 		    sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
 			continue;
 
-		atomic_inc(&clp->cl_count);
+		refcount_inc(&clp->cl_count);
 		spin_unlock(&nn->nfs_client_lock);
 		return clp;
 	}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6dcbc5d..d285ec9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1228,7 +1228,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
 	p->dentry = dget(dentry);
 	p->dir = parent;
 	p->owner = sp;
-	atomic_inc(&sp->so_count);
+	refcount_inc(&sp->so_count);
 	p->o_arg.open_flags = flags;
 	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
 	p->o_arg.umask = current_umask();
@@ -1682,7 +1682,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
 out:
 	return ERR_PTR(ret);
 out_return_state:
-	atomic_inc(&state->count);
+	refcount_inc(&state->count);
 	return state;
 }
 
@@ -1748,7 +1748,7 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
 update:
 	update_open_stateid(state, &data->o_res.stateid, NULL,
 			    data->o_arg.fmode);
-	atomic_inc(&state->count);
+	refcount_inc(&state->count);
 
 	return state;
 err:
@@ -1834,7 +1834,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
 	if (opendata == NULL)
 		return ERR_PTR(-ENOMEM);
 	opendata->state = state;
-	atomic_inc(&state->count);
+	refcount_inc(&state->count);
 	return opendata;
 }
 
@@ -2594,7 +2594,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
 		if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
 			struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
 
-			atomic_inc(&lsp->ls_count);
+			refcount_inc(&lsp->ls_count);
 			spin_unlock(&state->state_lock);
 
 			nfs4_put_lock_state(prev);
@@ -4863,7 +4863,7 @@ static void nfs4_renew_release(void *calldata)
 	struct nfs4_renewdata *data = calldata;
 	struct nfs_client *clp = data->client;
 
-	if (atomic_read(&clp->cl_count) > 1)
+	if (refcount_read(&clp->cl_count) > 1)
 		nfs4_schedule_state_renewal(clp);
 	nfs_put_client(clp);
 	kfree(data);
@@ -4911,7 +4911,7 @@ static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred,
 
 	if (renew_flags == 0)
 		return 0;
-	if (!atomic_inc_not_zero(&clp->cl_count))
+	if (!refcount_inc_not_zero(&clp->cl_count))
 		return -EIO;
 	data = kmalloc(sizeof(*data), GFP_NOFS);
 	if (data == NULL)
@@ -5917,7 +5917,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
 	p->arg.seqid = seqid;
 	p->res.seqid = seqid;
 	p->lsp = lsp;
-	atomic_inc(&lsp->ls_count);
+	refcount_inc(&lsp->ls_count);
 	/* Ensure we don't close file until we're done freeing locks! */
 	p->ctx = get_nfs_open_context(ctx);
 	memcpy(&p->fl, fl, sizeof(p->fl));
@@ -6125,7 +6125,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
 	p->res.lock_seqid = p->arg.lock_seqid;
 	p->lsp = lsp;
 	p->server = server;
-	atomic_inc(&lsp->ls_count);
+	refcount_inc(&lsp->ls_count);
 	p->ctx = get_nfs_open_context(ctx);
 	get_file(fl->fl_file);
 	memcpy(&p->fl, fl, sizeof(p->fl));
@@ -7580,7 +7580,7 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
 	struct rpc_task *task;
 	int status = -EIO;
 
-	if (!atomic_inc_not_zero(&clp->cl_count))
+	if (!refcount_inc_not_zero(&clp->cl_count))
 		goto out;
 
 	status = -ENOMEM;
@@ -8142,7 +8142,7 @@ static void nfs41_sequence_release(void *data)
 	struct nfs4_sequence_data *calldata = data;
 	struct nfs_client *clp = calldata->clp;
 
-	if (atomic_read(&clp->cl_count) > 1)
+	if (refcount_read(&clp->cl_count) > 1)
 		nfs4_schedule_state_renewal(clp);
 	nfs_put_client(clp);
 	kfree(calldata);
@@ -8171,7 +8171,7 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 	trace_nfs4_sequence(clp, task->tk_status);
 	if (task->tk_status < 0) {
 		dprintk("%s ERROR %d\n", __func__, task->tk_status);
-		if (atomic_read(&clp->cl_count) == 1)
+		if (refcount_read(&clp->cl_count) == 1)
 			goto out;
 
 		if (nfs41_sequence_handle_errors(task, clp) == -EAGAIN) {
@@ -8219,7 +8219,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
 		.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
 	};
 
-	if (!atomic_inc_not_zero(&clp->cl_count))
+	if (!refcount_inc_not_zero(&clp->cl_count))
 		return ERR_PTR(-EIO);
 	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
 	if (calldata == NULL) {
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 1d152f4..80cf185 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -400,7 +400,7 @@ nfs4_find_state_owner_locked(struct nfs_server *server, struct rpc_cred *cred)
 		else {
 			if (!list_empty(&sp->so_lru))
 				list_del_init(&sp->so_lru);
-			atomic_inc(&sp->so_count);
+			refcount_inc(&sp->so_count);
 			return sp;
 		}
 	}
@@ -427,7 +427,7 @@ nfs4_insert_state_owner_locked(struct nfs4_state_owner *new)
 		else {
 			if (!list_empty(&sp->so_lru))
 				list_del_init(&sp->so_lru);
-			atomic_inc(&sp->so_count);
+			refcount_inc(&sp->so_count);
 			return sp;
 		}
 	}
@@ -486,7 +486,7 @@ nfs4_alloc_state_owner(struct nfs_server *server,
 	spin_lock_init(&sp->so_lock);
 	INIT_LIST_HEAD(&sp->so_states);
 	nfs4_init_seqid_counter(&sp->so_seqid);
-	atomic_set(&sp->so_count, 1);
+	refcount_set(&sp->so_count, 1);
 	INIT_LIST_HEAD(&sp->so_lru);
 	seqcount_init(&sp->so_reclaim_seqcount);
 	mutex_init(&sp->so_delegreturn_mutex);
@@ -593,7 +593,7 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 	struct nfs_server *server = sp->so_server;
 	struct nfs_client *clp = server->nfs_client;
 
-	if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock))
+	if (!refcount_dec_and_lock(&sp->so_count, &clp->cl_lock))
 		return;
 
 	sp->so_expires = jiffies;
@@ -635,7 +635,7 @@ nfs4_alloc_open_state(void)
 	state = kzalloc(sizeof(*state), GFP_NOFS);
 	if (!state)
 		return NULL;
-	atomic_set(&state->count, 1);
+	refcount_set(&state->count, 1);
 	INIT_LIST_HEAD(&state->lock_states);
 	spin_lock_init(&state->state_lock);
 	seqlock_init(&state->seqlock);
@@ -668,7 +668,7 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
 			continue;
 		if (!nfs4_valid_open_stateid(state))
 			continue;
-		if (atomic_inc_not_zero(&state->count))
+		if (refcount_inc_not_zero(&state->count))
 			return state;
 	}
 	return NULL;
@@ -698,7 +698,7 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
 	if (state == NULL && new != NULL) {
 		state = new;
 		state->owner = owner;
-		atomic_inc(&owner->so_count);
+		refcount_inc(&owner->so_count);
 		list_add(&state->inode_states, &nfsi->open_states);
 		ihold(inode);
 		state->inode = inode;
@@ -722,7 +722,7 @@ void nfs4_put_open_state(struct nfs4_state *state)
 	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
 
-	if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
+	if (!refcount_dec_and_lock(&state->count, &owner->so_lock))
 		return;
 	spin_lock(&inode->i_lock);
 	list_del(&state->inode_states);
@@ -744,7 +744,7 @@ static void __nfs4_close(struct nfs4_state *state,
 	int call_close = 0;
 	fmode_t newstate;
 
-	atomic_inc(&owner->so_count);
+	refcount_inc(&owner->so_count);
 	/* Protect against nfs4_find_state() */
 	spin_lock(&owner->so_lock);
 	switch (fmode & (FMODE_READ | FMODE_WRITE)) {
@@ -819,7 +819,7 @@ __nfs4_find_lock_state(struct nfs4_state *state,
 			ret = pos;
 	}
 	if (ret)
-		atomic_inc(&ret->ls_count);
+		refcount_inc(&ret->ls_count);
 	return ret;
 }
 
@@ -837,7 +837,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
 	if (lsp == NULL)
 		return NULL;
 	nfs4_init_seqid_counter(&lsp->ls_seqid);
-	atomic_set(&lsp->ls_count, 1);
+	refcount_set(&lsp->ls_count, 1);
 	lsp->ls_state = state;
 	lsp->ls_owner = fl_owner;
 	lsp->ls_seqid.owner_id = ida_simple_get(&server->lockowner_id, 0, 0, GFP_NOFS);
@@ -901,7 +901,7 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
 	if (lsp == NULL)
 		return;
 	state = lsp->ls_state;
-	if (!atomic_dec_and_lock(&lsp->ls_count, &state->state_lock))
+	if (!refcount_dec_and_lock(&lsp->ls_count, &state->state_lock))
 		return;
 	list_del(&lsp->ls_locks);
 	if (list_empty(&state->lock_states))
@@ -921,7 +921,7 @@ static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
 	struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner;
 
 	dst->fl_u.nfs4_fl.owner = lsp;
-	atomic_inc(&lsp->ls_count);
+	refcount_inc(&lsp->ls_count);
 }
 
 static void nfs4_fl_release_lock(struct file_lock *fl)
@@ -1170,7 +1170,7 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
 	if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
 		return;
 	__module_get(THIS_MODULE);
-	atomic_inc(&clp->cl_count);
+	refcount_inc(&clp->cl_count);
 
 	/* The rcu_read_lock() is not strictly necessary, as the state
 	 * manager is the only thread that ever changes the rpc_xprt
@@ -1262,7 +1262,7 @@ int nfs4_wait_clnt_recover(struct nfs_client *clp)
 
 	might_sleep();
 
-	atomic_inc(&clp->cl_count);
+	refcount_inc(&clp->cl_count);
 	res = wait_on_bit_action(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING,
 				 nfs_wait_bit_killable, TASK_KILLABLE);
 	if (res)
@@ -1519,7 +1519,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
 			continue;
 		if (state->state == 0)
 			continue;
-		atomic_inc(&state->count);
+		refcount_inc(&state->count);
 		spin_unlock(&sp->so_lock);
 		status = ops->recover_open(sp, state);
 		if (status >= 0) {
@@ -1778,7 +1778,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
 			if (!test_and_clear_bit(ops->owner_flag_bit,
 							&sp->so_flags))
 				continue;
-			if (!atomic_inc_not_zero(&sp->so_count))
+			if (!refcount_inc_not_zero(&sp->so_count))
 				continue;
 			spin_unlock(&clp->cl_lock);
 			rcu_read_unlock();
@@ -2498,7 +2498,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
 			break;
 		if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
 			break;
-	} while (atomic_read(&clp->cl_count) > 1);
+	} while (refcount_read(&clp->cl_count) > 1);
 	return;
 out_error:
 	if (strlen(section))
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 59554f3..3064bda 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -98,7 +98,7 @@ unset_pnfs_layoutdriver(struct nfs_server *nfss)
 		if (nfss->pnfs_curr_ld->clear_layoutdriver)
 			nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
 		/* Decrement the MDS count. Purge the deviceid cache if zero */
-		if (atomic_dec_and_test(&nfss->nfs_client->cl_mds_count))
+		if (refcount_dec_and_test(&nfss->nfs_client->cl_mds_count))
 			nfs4_deviceid_purge_client(nfss->nfs_client);
 		module_put(nfss->pnfs_curr_ld->owner);
 	}
@@ -190,7 +190,7 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,
 		goto out_no_driver;
 	}
 	/* Bump the MDS count */
-	atomic_inc(&server->nfs_client->cl_mds_count);
+	refcount_inc(&server->nfs_client->cl_mds_count);
 
 	dprintk("%s: pNFS module for %u set\n", __func__, id);
 	return;
@@ -251,7 +251,7 @@ EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver);
 void
 pnfs_get_layout_hdr(struct pnfs_layout_hdr *lo)
 {
-	atomic_inc(&lo->plh_refcount);
+	refcount_inc(&lo->plh_refcount);
 }
 
 static struct pnfs_layout_hdr *
@@ -296,7 +296,7 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
 
 	pnfs_layoutreturn_before_put_layout_hdr(lo);
 
-	if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
+	if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
 		if (!list_empty(&lo->plh_segs))
 			WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n");
 		pnfs_detach_layout_hdr(lo);
@@ -389,14 +389,14 @@ pnfs_layout_set_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit)
 {
 	lo->plh_retry_timestamp = jiffies;
 	if (!test_and_set_bit(fail_bit, &lo->plh_flags))
-		atomic_inc(&lo->plh_refcount);
+		refcount_inc(&lo->plh_refcount);
 }
 
 static void
 pnfs_layout_clear_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit)
 {
 	if (test_and_clear_bit(fail_bit, &lo->plh_flags))
-		atomic_dec(&lo->plh_refcount);
+		refcount_dec(&lo->plh_refcount);
 }
 
 static void
@@ -444,7 +444,7 @@ pnfs_init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg,
 {
 	INIT_LIST_HEAD(&lseg->pls_list);
 	INIT_LIST_HEAD(&lseg->pls_lc_list);
-	atomic_set(&lseg->pls_refcount, 1);
+	refcount_set(&lseg->pls_refcount, 1);
 	set_bit(NFS_LSEG_VALID, &lseg->pls_flags);
 	lseg->pls_layout = lo;
 	lseg->pls_range = *range;
@@ -466,7 +466,7 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
 	WARN_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
 	list_del_init(&lseg->pls_list);
 	/* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */
-	atomic_dec(&lo->plh_refcount);
+	refcount_dec(&lo->plh_refcount);
 	if (test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
 		return;
 	if (list_empty(&lo->plh_segs) &&
@@ -501,13 +501,13 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
 		return;
 
 	dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg,
-		atomic_read(&lseg->pls_refcount),
+		refcount_read(&lseg->pls_refcount),
 		test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
 
 	lo = lseg->pls_layout;
 	inode = lo->plh_inode;
 
-	if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
+	if (refcount_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
 		if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) {
 			spin_unlock(&inode->i_lock);
 			return;
@@ -550,9 +550,9 @@ pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg)
 	assert_spin_locked(&lseg->pls_layout->plh_inode->i_lock);
 
 	dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg,
-		atomic_read(&lseg->pls_refcount),
+		refcount_read(&lseg->pls_refcount),
 		test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
-	if (atomic_dec_and_test(&lseg->pls_refcount)) {
+	if (refcount_dec_and_test(&lseg->pls_refcount)) {
 		struct pnfs_layout_hdr *lo = lseg->pls_layout;
 		if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags))
 			return;
@@ -587,7 +587,7 @@ pnfs_lseg_range_contained(const struct pnfs_layout_range *l1,
 static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg,
 		struct list_head *tmp_list)
 {
-	if (!atomic_dec_and_test(&lseg->pls_refcount))
+	if (!refcount_dec_and_test(&lseg->pls_refcount))
 		return false;
 	pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
 	list_add(&lseg->pls_list, tmp_list);
@@ -606,7 +606,7 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
 		 * outstanding io is finished.
 		 */
 		dprintk("%s: lseg %p ref %d\n", __func__, lseg,
-			atomic_read(&lseg->pls_refcount));
+			refcount_read(&lseg->pls_refcount));
 		if (pnfs_lseg_dec_and_remove_zero(lseg, tmp_list))
 			rv = 1;
 	}
@@ -1487,7 +1487,7 @@ alloc_init_layout_hdr(struct inode *ino,
 	lo = pnfs_alloc_layout_hdr(ino, gfp_flags);
 	if (!lo)
 		return NULL;
-	atomic_set(&lo->plh_refcount, 1);
+	refcount_set(&lo->plh_refcount, 1);
 	INIT_LIST_HEAD(&lo->plh_layouts);
 	INIT_LIST_HEAD(&lo->plh_segs);
 	INIT_LIST_HEAD(&lo->plh_return_segs);
@@ -1582,7 +1582,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
 	}
 
 	dprintk("%s:Return lseg %p ref %d\n",
-		__func__, ret, ret ? atomic_read(&ret->pls_refcount) : 0);
+		__func__, ret, ret ? refcount_read(&ret->pls_refcount) : 0);
 	return ret;
 }
 
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 63f77b4..61cafea 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -30,6 +30,7 @@
 #ifndef FS_NFS_PNFS_H
 #define FS_NFS_PNFS_H
 
+#include <linux/refcount.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
 #include <linux/workqueue.h>
@@ -54,7 +55,7 @@ struct nfs4_pnfs_ds {
 	char			*ds_remotestr;	/* comma sep list of addrs */
 	struct list_head	ds_addrs;
 	struct nfs_client	*ds_clp;
-	atomic_t		ds_count;
+	refcount_t		ds_count;
 	unsigned long		ds_state;
 #define NFS4DS_CONNECTING	0	/* ds is establishing connection */
 };
@@ -63,7 +64,7 @@ struct pnfs_layout_segment {
 	struct list_head pls_list;
 	struct list_head pls_lc_list;
 	struct pnfs_layout_range pls_range;
-	atomic_t pls_refcount;
+	refcount_t pls_refcount;
 	u32 pls_seq;
 	unsigned long pls_flags;
 	struct pnfs_layout_hdr *pls_layout;
@@ -185,7 +186,7 @@ struct pnfs_layoutdriver_type {
 };
 
 struct pnfs_layout_hdr {
-	atomic_t		plh_refcount;
+	refcount_t		plh_refcount;
 	atomic_t		plh_outstanding; /* number of RPCs out */
 	struct list_head	plh_layouts;   /* other client layouts */
 	struct list_head	plh_bulk_destroy;
@@ -399,7 +400,7 @@ static inline struct pnfs_layout_segment *
 pnfs_get_lseg(struct pnfs_layout_segment *lseg)
 {
 	if (lseg) {
-		atomic_inc(&lseg->pls_refcount);
+		refcount_inc(&lseg->pls_refcount);
 		smp_mb__after_atomic();
 	}
 	return lseg;
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index 9414b49..13bd1fe 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -359,7 +359,7 @@ print_ds(struct nfs4_pnfs_ds *ds)
 		"        client %p\n"
 		"        cl_exchange_flags %x\n",
 		ds->ds_remotestr,
-		atomic_read(&ds->ds_count), ds->ds_clp,
+		refcount_read(&ds->ds_count), ds->ds_clp,
 		ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0);
 }
 
@@ -472,7 +472,7 @@ static void destroy_ds(struct nfs4_pnfs_ds *ds)
 
 void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds)
 {
-	if (atomic_dec_and_lock(&ds->ds_count,
+	if (refcount_dec_and_lock(&ds->ds_count,
 				&nfs4_ds_cache_lock)) {
 		list_del_init(&ds->ds_node);
 		spin_unlock(&nfs4_ds_cache_lock);
@@ -558,7 +558,7 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
 		INIT_LIST_HEAD(&ds->ds_addrs);
 		list_splice_init(dsaddrs, &ds->ds_addrs);
 		ds->ds_remotestr = remotestr;
-		atomic_set(&ds->ds_count, 1);
+		refcount_set(&ds->ds_count, 1);
 		INIT_LIST_HEAD(&ds->ds_node);
 		ds->ds_clp = NULL;
 		list_add(&ds->ds_node, &nfs4_data_server_cache);
@@ -567,10 +567,10 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
 	} else {
 		kfree(remotestr);
 		kfree(ds);
-		atomic_inc(&tmp_ds->ds_count);
+		refcount_inc(&tmp_ds->ds_count);
 		dprintk("%s data server %s found, inc'ed ds_count to %d\n",
 			__func__, tmp_ds->ds_remotestr,
-			atomic_read(&tmp_ds->ds_count));
+			refcount_read(&tmp_ds->ds_count));
 		ds = tmp_ds;
 	}
 	spin_unlock(&nfs4_ds_cache_lock);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 6bca178..58e4b51 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -412,10 +412,10 @@ bool nfs_sb_active(struct super_block *sb)
 {
 	struct nfs_server *server = NFS_SB(sb);
 
-	if (!atomic_inc_not_zero(&sb->s_active))
+	if (!refcount_inc_not_zero(&sb->s_active))
 		return false;
 	if (atomic_inc_return(&server->active) != 1)
-		atomic_dec(&sb->s_active);
+		refcount_dec(&sb->s_active);
 	return true;
 }
 EXPORT_SYMBOL_GPL(nfs_sb_active);
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index 596205d..5a83aea 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -334,7 +334,7 @@ nfsd4_recall_file_layout(struct nfs4_layout_stateid *ls)
 
 	trace_layout_recall(&ls->ls_stid.sc_stateid);
 
-	atomic_inc(&ls->ls_stid.sc_count);
+	refcount_inc(&ls->ls_stid.sc_count);
 	nfsd4_run_cb(&ls->ls_recall);
 
 out_unlock:
@@ -439,7 +439,7 @@ nfsd4_insert_layout(struct nfsd4_layoutget *lgp, struct nfs4_layout_stateid *ls)
 			goto done;
 	}
 
-	atomic_inc(&ls->ls_stid.sc_count);
+	refcount_inc(&ls->ls_stid.sc_count);
 	list_add_tail(&new->lo_perstate, &ls->ls_layouts);
 	new = NULL;
 done:
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 4b4beaa..c3f17be 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -108,7 +108,7 @@ static bool is_session_dead(struct nfsd4_session *ses)
 
 static __be32 mark_session_dead_locked(struct nfsd4_session *ses, int ref_held_by_me)
 {
-	if (atomic_read(&ses->se_ref) > ref_held_by_me)
+	if (refcount_read(&ses->se_ref) > ref_held_by_me)
 		return nfserr_jukebox;
 	ses->se_flags |= NFS4_SESSION_DEAD;
 	return nfs_ok;
@@ -127,7 +127,7 @@ static __be32 get_client_locked(struct nfs4_client *clp)
 
 	if (is_client_expired(clp))
 		return nfserr_expired;
-	atomic_inc(&clp->cl_refcount);
+	refcount_inc(&clp->cl_refcount);
 	return nfs_ok;
 }
 
@@ -159,7 +159,7 @@ static void put_client_renew_locked(struct nfs4_client *clp)
 
 	lockdep_assert_held(&nn->client_lock);
 
-	if (!atomic_dec_and_test(&clp->cl_refcount))
+	if (!refcount_dec_and_test(&clp->cl_refcount))
 		return;
 	if (!is_client_expired(clp))
 		renew_client_locked(clp);
@@ -169,7 +169,7 @@ static void put_client_renew(struct nfs4_client *clp)
 {
 	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-	if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
+	if (!refcount_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
 		return;
 	if (!is_client_expired(clp))
 		renew_client_locked(clp);
@@ -185,7 +185,7 @@ static __be32 nfsd4_get_session_locked(struct nfsd4_session *ses)
 	status = get_client_locked(ses->se_client);
 	if (status)
 		return status;
-	atomic_inc(&ses->se_ref);
+	refcount_inc(&ses->se_ref);
 	return nfs_ok;
 }
 
@@ -196,7 +196,7 @@ static void nfsd4_put_session_locked(struct nfsd4_session *ses)
 
 	lockdep_assert_held(&nn->client_lock);
 
-	if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses))
+	if (refcount_dec_and_test(&ses->se_ref) && is_session_dead(ses))
 		free_session(ses);
 	put_client_renew_locked(clp);
 }
@@ -293,7 +293,7 @@ static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = {
 static inline struct nfs4_stateowner *
 nfs4_get_stateowner(struct nfs4_stateowner *sop)
 {
-	atomic_inc(&sop->so_count);
+	refcount_inc(&sop->so_count);
 	return sop;
 }
 
@@ -359,7 +359,7 @@ put_nfs4_file(struct nfs4_file *fi)
 {
 	might_lock(&state_lock);
 
-	if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) {
+	if (refcount_dec_and_lock(&fi->fi_ref, &state_lock)) {
 		hlist_del_rcu(&fi->fi_hash);
 		spin_unlock(&state_lock);
 		WARN_ON_ONCE(!list_empty(&fi->fi_clnt_odstate));
@@ -568,7 +568,7 @@ alloc_clnt_odstate(struct nfs4_client *clp)
 	co = kmem_cache_zalloc(odstate_slab, GFP_KERNEL);
 	if (co) {
 		co->co_client = clp;
-		atomic_set(&co->co_odcount, 1);
+		refcount_set(&co->co_odcount, 1);
 	}
 	return co;
 }
@@ -586,7 +586,7 @@ static inline void
 get_clnt_odstate(struct nfs4_clnt_odstate *co)
 {
 	if (co)
-		atomic_inc(&co->co_odcount);
+		refcount_inc(&co->co_odcount);
 }
 
 static void
@@ -598,7 +598,7 @@ put_clnt_odstate(struct nfs4_clnt_odstate *co)
 		return;
 
 	fp = co->co_file;
-	if (atomic_dec_and_lock(&co->co_odcount, &fp->fi_lock)) {
+	if (refcount_dec_and_lock(&co->co_odcount, &fp->fi_lock)) {
 		list_del(&co->co_perfile);
 		spin_unlock(&fp->fi_lock);
 
@@ -654,7 +654,7 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
 	stid->sc_stateid.si_opaque.so_id = new_id;
 	stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
 	/* Will be incremented before return to client: */
-	atomic_set(&stid->sc_count, 1);
+	refcount_set(&stid->sc_count, 1);
 	spin_lock_init(&stid->sc_lock);
 
 	/*
@@ -815,7 +815,7 @@ nfs4_put_stid(struct nfs4_stid *s)
 
 	might_lock(&clp->cl_lock);
 
-	if (!atomic_dec_and_lock(&s->sc_count, &clp->cl_lock)) {
+	if (!refcount_dec_and_lock(&s->sc_count, &clp->cl_lock)) {
 		wake_up_all(&close_wq);
 		return;
 	}
@@ -915,7 +915,7 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp)
 	if (status)
 		return status;
 	++fp->fi_delegees;
-	atomic_inc(&dp->dl_stid.sc_count);
+	refcount_inc(&dp->dl_stid.sc_count);
 	dp->dl_stid.sc_type = NFS4_DELEG_STID;
 	list_add(&dp->dl_perfile, &fp->fi_delegations);
 	list_add(&dp->dl_perclnt, &clp->cl_delegations);
@@ -1155,7 +1155,7 @@ static void nfs4_put_stateowner(struct nfs4_stateowner *sop)
 
 	might_lock(&clp->cl_lock);
 
-	if (!atomic_dec_and_lock(&sop->so_count, &clp->cl_lock))
+	if (!refcount_dec_and_lock(&sop->so_count, &clp->cl_lock))
 		return;
 	sop->so_ops->so_unhash(sop);
 	spin_unlock(&clp->cl_lock);
@@ -1216,7 +1216,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp,
 
 	WARN_ON_ONCE(!list_empty(&stp->st_locks));
 
-	if (!atomic_dec_and_test(&s->sc_count)) {
+	if (!refcount_dec_and_test(&s->sc_count)) {
 		wake_up_all(&close_wq);
 		return;
 	}
@@ -1647,7 +1647,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
 	new->se_flags = cses->flags;
 	new->se_cb_prog = cses->callback_prog;
 	new->se_cb_sec = cses->cb_sec;
-	atomic_set(&new->se_ref, 0);
+	refcount_set(&new->se_ref, 0);
 	idx = hash_sessionid(&new->se_sessionid);
 	list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
 	spin_lock(&clp->cl_lock);
@@ -1766,7 +1766,7 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
 	clp->cl_name.len = name.len;
 	INIT_LIST_HEAD(&clp->cl_sessions);
 	idr_init(&clp->cl_stateids);
-	atomic_set(&clp->cl_refcount, 0);
+	refcount_set(&clp->cl_refcount, 0);
 	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
 	INIT_LIST_HEAD(&clp->cl_idhash);
 	INIT_LIST_HEAD(&clp->cl_openowners);
@@ -1794,7 +1794,7 @@ free_client(struct nfs4_client *clp)
 		ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
 				se_perclnt);
 		list_del(&ses->se_perclnt);
-		WARN_ON_ONCE(atomic_read(&ses->se_ref));
+		WARN_ON_ONCE(refcount_read(&ses->se_ref));
 		free_session(ses);
 	}
 	rpc_destroy_wait_queue(&clp->cl_cb_waitq);
@@ -1843,7 +1843,7 @@ unhash_client(struct nfs4_client *clp)
 
 static __be32 mark_client_expired_locked(struct nfs4_client *clp)
 {
-	if (atomic_read(&clp->cl_refcount))
+	if (refcount_read(&clp->cl_refcount))
 		return nfserr_jukebox;
 	unhash_client_locked(clp);
 	return nfs_ok;
@@ -2087,7 +2087,7 @@ find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask)
 	s = find_stateid_locked(cl, t);
 	if (s != NULL) {
 		if (typemask & s->sc_type)
-			atomic_inc(&s->sc_count);
+			refcount_inc(&s->sc_count);
 		else
 			s = NULL;
 	}
@@ -3354,7 +3354,7 @@ static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval,
 {
 	lockdep_assert_held(&state_lock);
 
-	atomic_set(&fp->fi_ref, 1);
+	refcount_set(&fp->fi_ref, 1);
 	spin_lock_init(&fp->fi_lock);
 	INIT_LIST_HEAD(&fp->fi_stateids);
 	INIT_LIST_HEAD(&fp->fi_delegations);
@@ -3473,7 +3473,7 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj
 	INIT_LIST_HEAD(&sop->so_stateids);
 	sop->so_client = clp;
 	init_nfs4_replay(&sop->so_replay);
-	atomic_set(&sop->so_count, 1);
+	refcount_set(&sop->so_count, 1);
 	return sop;
 }
 
@@ -3517,7 +3517,7 @@ nfsd4_find_existing_open(struct nfs4_file *fp, struct nfsd4_open *open)
 			continue;
 		if (local->st_stateowner == &oo->oo_owner) {
 			ret = local;
-			atomic_inc(&ret->st_stid.sc_count);
+			refcount_inc(&ret->st_stid.sc_count);
 			break;
 		}
 	}
@@ -3576,7 +3576,7 @@ init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
 		goto out_unlock;
 
 	open->op_stp = NULL;
-	atomic_inc(&stp->st_stid.sc_count);
+	refcount_inc(&stp->st_stid.sc_count);
 	stp->st_stid.sc_type = NFS4_OPEN_STID;
 	INIT_LIST_HEAD(&stp->st_locks);
 	stp->st_stateowner = nfs4_get_stateowner(&oo->oo_owner);
@@ -3624,7 +3624,7 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net)
 	 * there should be no danger of the refcount going back up again at
 	 * this point.
 	 */
-	wait_event(close_wq, atomic_read(&s->st_stid.sc_count) == 2);
+	wait_event(close_wq, refcount_read(&s->st_stid.sc_count) == 2);
 
 	release_all_access(s);
 	if (s->st_stid.sc_file) {
@@ -3650,7 +3650,7 @@ find_file_locked(struct knfsd_fh *fh, unsigned int hashval)
 
 	hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) {
 		if (fh_match(&fp->fi_fhandle, fh)) {
-			if (atomic_inc_not_zero(&fp->fi_ref))
+			if (refcount_inc_not_zero(&fp->fi_ref))
 				return fp;
 		}
 	}
@@ -3786,7 +3786,7 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
 	 * lock) we know the server hasn't removed the lease yet, we know
 	 * it's safe to take a reference.
 	 */
-	atomic_inc(&dp->dl_stid.sc_count);
+	refcount_inc(&dp->dl_stid.sc_count);
 	nfsd4_run_cb(&dp->dl_recall);
 }
 
@@ -3882,7 +3882,7 @@ static __be32 lookup_clientid(clientid_t *clid,
 		spin_unlock(&nn->client_lock);
 		return nfserr_expired;
 	}
-	atomic_inc(&found->cl_refcount);
+	refcount_inc(&found->cl_refcount);
 	spin_unlock(&nn->client_lock);
 
 	/* Cache the nfs4_client in cstate! */
@@ -5071,7 +5071,7 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		ret = nfserr_locks_held;
 		break;
 	case NFS4_LOCK_STID:
-		atomic_inc(&s->sc_count);
+		refcount_inc(&s->sc_count);
 		spin_unlock(&cl->cl_lock);
 		ret = nfsd4_free_lock_stateid(stateid, s);
 		goto out;
@@ -5575,7 +5575,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
 
 	lockdep_assert_held(&clp->cl_lock);
 
-	atomic_inc(&stp->st_stid.sc_count);
+	refcount_inc(&stp->st_stid.sc_count);
 	stp->st_stid.sc_type = NFS4_LOCK_STID;
 	stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
 	get_nfs4_file(fp);
@@ -5602,7 +5602,7 @@ find_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp)
 
 	list_for_each_entry(lst, &lo->lo_owner.so_stateids, st_perstateowner) {
 		if (lst->st_stid.sc_file == fp) {
-			atomic_inc(&lst->st_stid.sc_count);
+			refcount_inc(&lst->st_stid.sc_count);
 			return lst;
 		}
 	}
@@ -6305,7 +6305,7 @@ nfs4_check_open_reclaim(clientid_t *clid,
 static inline void
 put_client(struct nfs4_client *clp)
 {
-	atomic_dec(&clp->cl_refcount);
+	refcount_dec(&clp->cl_refcount);
 }
 
 static struct nfs4_client *
@@ -6423,7 +6423,7 @@ nfsd_inject_add_lock_to_list(struct nfs4_ol_stateid *lst,
 		return;
 
 	lockdep_assert_held(&nn->client_lock);
-	atomic_inc(&clp->cl_refcount);
+	refcount_inc(&clp->cl_refcount);
 	list_add(&lst->st_locks, collect);
 }
 
@@ -6576,7 +6576,7 @@ nfsd_foreach_client_openowner(struct nfs4_client *clp, u64 max,
 		if (func) {
 			func(oop);
 			if (collect) {
-				atomic_inc(&clp->cl_refcount);
+				refcount_inc(&clp->cl_refcount);
 				list_add(&oop->oo_perclient, collect);
 			}
 		}
@@ -6714,7 +6714,7 @@ static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max,
 			if (dp->dl_time != 0)
 				continue;
 
-			atomic_inc(&clp->cl_refcount);
+			refcount_inc(&clp->cl_refcount);
 			WARN_ON(!unhash_delegation_locked(dp));
 			list_add(&dp->dl_recall_lru, victims);
 		}
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index c939936..74b7ff8 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -36,6 +36,7 @@
 #define _NFSD4_STATE_H
 
 #include <linux/idr.h>
+#include <linux/refcount.h>
 #include <linux/sunrpc/svc_xprt.h>
 #include "nfsfh.h"
 
@@ -83,7 +84,7 @@ struct nfsd4_callback_ops {
  * fields that are of general use to any stateid.
  */
 struct nfs4_stid {
-	atomic_t		sc_count;
+	refcount_t		sc_count;
 #define NFS4_OPEN_STID 1
 #define NFS4_LOCK_STID 2
 #define NFS4_DELEG_STID 4
@@ -238,7 +239,7 @@ struct nfsd4_conn {
  * working on the object (primarily during the processing of compounds).
  */
 struct nfsd4_session {
-	atomic_t		se_ref;
+	refcount_t		se_ref;
 	struct list_head	se_hash;	/* hash by sessionid */
 	struct list_head	se_perclnt;
 /* See SESSION4_PERSIST, etc. for standard flags; this is internal-only: */
@@ -343,7 +344,7 @@ struct nfs4_client {
 	struct nfsd4_clid_slot	cl_cs_slot;	/* create_session slot */
 	u32			cl_exchange_flags;
 	/* number of rpc's in progress over an associated session: */
-	atomic_t		cl_refcount;
+	refcount_t		cl_refcount;
 	struct nfs4_op_map      cl_spo_must_allow;
 
 	/* for nfs41 callbacks */
@@ -407,7 +408,7 @@ struct nfs4_stateowner {
 	const struct nfs4_stateowner_operations	*so_ops;
 	/* after increment in nfsd4_bump_seqid, represents the next
 	 * sequence id expected from the client: */
-	atomic_t				so_count;
+	refcount_t				so_count;
 	u32					so_seqid;
 	struct xdr_netobj			so_owner; /* open owner name */
 	struct nfs4_replay			so_replay;
@@ -465,7 +466,7 @@ struct nfs4_clnt_odstate {
 	struct nfs4_client	*co_client;
 	struct nfs4_file	*co_file;
 	struct list_head	co_perfile;
-	atomic_t		co_odcount;
+	refcount_t		co_odcount;
 };
 
 /*
@@ -481,7 +482,7 @@ struct nfs4_clnt_odstate {
  * the global state_lock spinlock.
  */
 struct nfs4_file {
-	atomic_t		fi_ref;
+	refcount_t		fi_ref;
 	spinlock_t		fi_lock;
 	struct hlist_node       fi_hash;	/* hash on fi_fhandle */
 	struct list_head        fi_stateids;
@@ -633,7 +634,7 @@ struct nfs4_file *find_file(struct knfsd_fh *fh);
 void put_nfs4_file(struct nfs4_file *fi);
 static inline void get_nfs4_file(struct nfs4_file *fi)
 {
-	atomic_inc(&fi->fi_ref);
+	refcount_inc(&fi->fi_ref);
 }
 struct file *find_any_file(struct nfs4_file *f);
 
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 2dd75bf..afebb50 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -737,7 +737,7 @@ struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno)
 		} else if (cno > root->cno) {
 			n = n->rb_right;
 		} else {
-			atomic_inc(&root->count);
+			refcount_inc(&root->count);
 			spin_unlock(&nilfs->ns_cptree_lock);
 			return root;
 		}
@@ -776,7 +776,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
 		} else if (cno > root->cno) {
 			p = &(*p)->rb_right;
 		} else {
-			atomic_inc(&root->count);
+			refcount_inc(&root->count);
 			spin_unlock(&nilfs->ns_cptree_lock);
 			kfree(new);
 			return root;
@@ -786,7 +786,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
 	new->cno = cno;
 	new->ifile = NULL;
 	new->nilfs = nilfs;
-	atomic_set(&new->count, 1);
+	refcount_set(&new->count, 1);
 	atomic64_set(&new->inodes_count, 0);
 	atomic64_set(&new->blocks_count, 0);
 
@@ -806,7 +806,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
 
 void nilfs_put_root(struct nilfs_root *root)
 {
-	if (atomic_dec_and_test(&root->count)) {
+	if (refcount_dec_and_test(&root->count)) {
 		struct the_nilfs *nilfs = root->nilfs;
 
 		nilfs_sysfs_delete_snapshot_group(root);
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index b305c6f..883d732 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -27,6 +27,7 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 struct nilfs_sc_info;
 struct nilfs_sysfs_dev_subgroups;
@@ -246,7 +247,7 @@ struct nilfs_root {
 	__u64 cno;
 	struct rb_node rb_node;
 
-	atomic_t count;
+	refcount_t count;
 	struct the_nilfs *nilfs;
 	struct inode *ifile;
 
@@ -299,7 +300,7 @@ void nilfs_swap_super_block(struct the_nilfs *);
 
 static inline void nilfs_get_root(struct nilfs_root *root)
 {
-	atomic_inc(&root->count);
+	refcount_inc(&root->count);
 }
 
 static inline int nilfs_valid_fs(struct the_nilfs *nilfs)
diff --git a/fs/notify/group.c b/fs/notify/group.c
index fbe3cbe..81356c1 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -98,7 +98,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
  */
 void fsnotify_get_group(struct fsnotify_group *group)
 {
-	atomic_inc(&group->refcnt);
+	refcount_inc(&group->refcnt);
 }
 
 /*
@@ -106,7 +106,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
  */
 void fsnotify_put_group(struct fsnotify_group *group)
 {
-	if (atomic_dec_and_test(&group->refcnt))
+	if (refcount_dec_and_test(&group->refcnt))
 		fsnotify_final_destroy_group(group);
 }
 
@@ -122,7 +122,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 		return ERR_PTR(-ENOMEM);
 
 	/* set to 0 when there a no external references to this group */
-	atomic_set(&group->refcnt, 1);
+	refcount_set(&group->refcnt, 1);
 	atomic_set(&group->num_marks, 0);
 
 	spin_lock_init(&group->notification_lock);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 69d1ea3..115bea0 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -378,7 +378,7 @@ static struct inotify_inode_mark *inotify_idr_find_locked(struct fsnotify_group
 
 		fsnotify_get_mark(fsn_mark);
 		/* One ref for being in the idr, one ref we just took */
-		BUG_ON(atomic_read(&fsn_mark->refcnt) < 2);
+		BUG_ON(refcount_read(&fsn_mark->refcnt) < 2);
 	}
 
 	return i_mark;
@@ -467,7 +467,7 @@ static void inotify_remove_from_idr(struct fsnotify_group *group,
 	 * one ref held by the caller trying to kill us
 	 * one ref grabbed by inotify_idr_find
 	 */
-	if (unlikely(atomic_read(&i_mark->fsn_mark.refcnt) < 3)) {
+	if (unlikely(refcount_read(&i_mark->fsn_mark.refcnt) < 3)) {
 		printk(KERN_ERR "%s: i_mark=%p i_mark->wd=%d i_mark->group=%p"
 			" i_mark->inode=%p\n", __func__, i_mark, i_mark->wd,
 			i_mark->fsn_mark.group, i_mark->fsn_mark.inode);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index d3fea0b..48e9944 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -102,12 +102,12 @@ static DECLARE_DELAYED_WORK(reaper_work, fsnotify_mark_destroy_workfn);
 
 void fsnotify_get_mark(struct fsnotify_mark *mark)
 {
-	atomic_inc(&mark->refcnt);
+	refcount_inc(&mark->refcnt);
 }
 
 void fsnotify_put_mark(struct fsnotify_mark *mark)
 {
-	if (atomic_dec_and_test(&mark->refcnt)) {
+	if (refcount_dec_and_test(&mark->refcnt)) {
 		if (mark->group)
 			fsnotify_put_group(mark->group);
 		mark->free_mark(mark);
@@ -530,7 +530,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
 {
 	memset(mark, 0, sizeof(*mark));
 	spin_lock_init(&mark->lock);
-	atomic_set(&mark->refcnt, 1);
+	refcount_set(&mark->refcnt, 1);
 	mark->free_mark = free_mark;
 }
 
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index cc91856..d5c52d1 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -1290,7 +1290,7 @@ static int ntfs_write_mst_block(struct page *page,
 				tni == base_tni ? "base" : "extent",
 				tni->mft_no);
 		mutex_unlock(&tni->mrec_lock);
-		atomic_dec(&tni->count);
+		refcount_dec(&tni->count);
 		iput(VFS_I(base_tni));
 	}
 	SetPageUptodate(page);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 7c410f8..7facd1a 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -344,7 +344,7 @@ void ntfs_destroy_big_inode(struct inode *inode)
 
 	ntfs_debug("Entering.");
 	BUG_ON(ni->page);
-	if (!atomic_dec_and_test(&ni->count))
+	if (!refcount_dec_and_test(&ni->count))
 		BUG();
 	call_rcu(&inode->i_rcu, ntfs_i_callback);
 }
@@ -367,7 +367,7 @@ static void ntfs_destroy_extent_inode(ntfs_inode *ni)
 {
 	ntfs_debug("Entering.");
 	BUG_ON(ni->page);
-	if (!atomic_dec_and_test(&ni->count))
+	if (!refcount_dec_and_test(&ni->count))
 		BUG();
 	kmem_cache_free(ntfs_inode_cache, ni);
 }
@@ -396,7 +396,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
 	rwlock_init(&ni->size_lock);
 	ni->initialized_size = ni->allocated_size = 0;
 	ni->seq_no = 0;
-	atomic_set(&ni->count, 1);
+	refcount_set(&ni->count, 1);
 	ni->vol = NTFS_SB(sb);
 	ntfs_init_runlist(&ni->runlist);
 	mutex_init(&ni->mrec_lock);
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h
index b3c3469..9058f14 100644
--- a/fs/ntfs/inode.h
+++ b/fs/ntfs/inode.h
@@ -24,7 +24,7 @@
 #ifndef _LINUX_NTFS_INODE_H
 #define _LINUX_NTFS_INODE_H
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include <linux/fs.h>
 #include <linux/list.h>
@@ -52,7 +52,7 @@ struct _ntfs_inode {
 				   See ntfs_inode_state_bits below. */
 	unsigned long mft_no;	/* Number of the mft record / inode. */
 	u16 seq_no;		/* Sequence number of the mft record. */
-	atomic_t count;		/* Inode reference count for book keeping. */
+	refcount_t count;	/* Inode reference count for book keeping. */
 	ntfs_volume *vol;	/* Pointer to the ntfs volume of this inode. */
 	/*
 	 * If NInoAttr() is true, the below fields describe the attribute which
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index b6f4021..aad8654 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -160,7 +160,7 @@ MFT_RECORD *map_mft_record(ntfs_inode *ni)
 	ntfs_debug("Entering for mft_no 0x%lx.", ni->mft_no);
 
 	/* Make sure the ntfs inode doesn't go away. */
-	atomic_inc(&ni->count);
+	refcount_inc(&ni->count);
 
 	/* Serialize access to this mft record. */
 	mutex_lock(&ni->mrec_lock);
@@ -170,7 +170,7 @@ MFT_RECORD *map_mft_record(ntfs_inode *ni)
 		return m;
 
 	mutex_unlock(&ni->mrec_lock);
-	atomic_dec(&ni->count);
+	refcount_dec(&ni->count);
 	ntfs_error(ni->vol->sb, "Failed with error code %lu.", -PTR_ERR(m));
 	return m;
 }
@@ -221,7 +221,7 @@ void unmap_mft_record(ntfs_inode *ni)
 
 	unmap_mft_record_page(ni);
 	mutex_unlock(&ni->mrec_lock);
-	atomic_dec(&ni->count);
+	refcount_dec(&ni->count);
 	/*
 	 * If pure ntfs_inode, i.e. no vfs inode attached, we leave it to
 	 * ntfs_clear_extent_inode() in the extent inode case, and to the
@@ -258,7 +258,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
 	ntfs_debug("Mapping extent mft record 0x%lx (base mft record 0x%lx).",
 			mft_no, base_ni->mft_no);
 	/* Make sure the base ntfs inode doesn't go away. */
-	atomic_inc(&base_ni->count);
+	refcount_inc(&base_ni->count);
 	/*
 	 * Check if this extent inode has already been added to the base inode,
 	 * in which case just return it. If not found, add it to the base
@@ -272,17 +272,17 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
 				continue;
 			ni = extent_nis[i];
 			/* Make sure the ntfs inode doesn't go away. */
-			atomic_inc(&ni->count);
+			refcount_inc(&ni->count);
 			break;
 		}
 	}
 	if (likely(ni != NULL)) {
 		mutex_unlock(&base_ni->extent_lock);
-		atomic_dec(&base_ni->count);
+		refcount_dec(&base_ni->count);
 		/* We found the record; just have to map and return it. */
 		m = map_mft_record(ni);
 		/* map_mft_record() has incremented this on success. */
-		atomic_dec(&ni->count);
+		refcount_dec(&ni->count);
 		if (likely(!IS_ERR(m))) {
 			/* Verify the sequence number. */
 			if (likely(le16_to_cpu(m->sequence_number) == seq_no)) {
@@ -305,7 +305,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
 	ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no);
 	if (unlikely(!ni)) {
 		mutex_unlock(&base_ni->extent_lock);
-		atomic_dec(&base_ni->count);
+		refcount_dec(&base_ni->count);
 		return ERR_PTR(-ENOMEM);
 	}
 	ni->vol = base_ni->vol;
@@ -316,7 +316,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
 	m = map_mft_record(ni);
 	if (IS_ERR(m)) {
 		mutex_unlock(&base_ni->extent_lock);
-		atomic_dec(&base_ni->count);
+		refcount_dec(&base_ni->count);
 		ntfs_clear_extent_inode(ni);
 		goto map_err_out;
 	}
@@ -351,14 +351,14 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
 	}
 	base_ni->ext.extent_ntfs_inos[base_ni->nr_extents++] = ni;
 	mutex_unlock(&base_ni->extent_lock);
-	atomic_dec(&base_ni->count);
+	refcount_dec(&base_ni->count);
 	ntfs_debug("Done 2.");
 	*ntfs_ino = ni;
 	return m;
 unm_err_out:
 	unmap_mft_record(ni);
 	mutex_unlock(&base_ni->extent_lock);
-	atomic_dec(&base_ni->count);
+	refcount_dec(&base_ni->count);
 	/*
 	 * If the extent inode was not attached to the base inode we need to
 	 * release it or we will leak memory.
@@ -971,12 +971,12 @@ bool ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
 		/* The inode is in icache. */
 		ni = NTFS_I(vi);
 		/* Take a reference to the ntfs inode. */
-		atomic_inc(&ni->count);
+		refcount_inc(&ni->count);
 		/* If the inode is dirty, do not write this record. */
 		if (NInoDirty(ni)) {
 			ntfs_debug("Inode 0x%lx is dirty, do not write it.",
 					mft_no);
-			atomic_dec(&ni->count);
+			refcount_dec(&ni->count);
 			iput(vi);
 			return false;
 		}
@@ -985,7 +985,7 @@ bool ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
 		if (unlikely(!mutex_trylock(&ni->mrec_lock))) {
 			ntfs_debug("Mft record 0x%lx is already locked, do "
 					"not write it.", mft_no);
-			atomic_dec(&ni->count);
+			refcount_dec(&ni->count);
 			iput(vi);
 			return false;
 		}
@@ -1081,14 +1081,14 @@ bool ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
 	ntfs_debug("Extent inode 0x%lx is attached to its base inode 0x%lx.",
 			mft_no, na.mft_no);
 	/* Take a reference to the extent ntfs inode. */
-	atomic_inc(&eni->count);
+	refcount_inc(&eni->count);
 	mutex_unlock(&ni->extent_lock);
 	/*
 	 * Found the extent inode coresponding to this extent mft record.
 	 * Try to take the mft record lock.
 	 */
 	if (unlikely(!mutex_trylock(&eni->mrec_lock))) {
-		atomic_dec(&eni->count);
+		refcount_dec(&eni->count);
 		iput(vi);
 		ntfs_debug("Extent mft record 0x%lx is already locked, do "
 				"not write it.", mft_no);
@@ -2707,7 +2707,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
 		 * Manually map, pin, and lock the mft record as we already
 		 * have its page mapped and it is very easy to do.
 		 */
-		atomic_inc(&ni->count);
+		refcount_inc(&ni->count);
 		mutex_lock(&ni->mrec_lock);
 		ni->page = page;
 		ni->page_ofs = ofs;
@@ -2807,7 +2807,7 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m)
 	mutex_lock(&base_ni->extent_lock);
 
 	/* Make sure we are holding the only reference to the extent inode. */
-	if (atomic_read(&ni->count) > 2) {
+	if (refcount_read(&ni->count) > 2) {
 		ntfs_error(vol->sb, "Tried to free busy extent inode 0x%lx, "
 				"not freeing.", base_ni->mft_no);
 		mutex_unlock(&base_ni->extent_lock);
diff --git a/fs/ocfs2/filecheck.c b/fs/ocfs2/filecheck.c
index 2cabbcf..98835e8 100644
--- a/fs/ocfs2/filecheck.c
+++ b/fs/ocfs2/filecheck.c
@@ -26,6 +26,7 @@
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
 #include <linux/sysctl.h>
+#include <linux/refcount.h>
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
@@ -66,7 +67,7 @@ struct ocfs2_filecheck {
 
 struct ocfs2_filecheck_sysfs_entry {	/* sysfs entry per mounting */
 	struct list_head fs_list;
-	atomic_t fs_count;
+	refcount_t fs_count;
 	struct super_block *fs_sb;
 	struct kset *fs_devicekset;
 	struct kset *fs_fcheckkset;
@@ -140,8 +141,10 @@ ocfs2_filecheck_sysfs_free(struct ocfs2_filecheck_sysfs_entry *entry)
 {
 	struct ocfs2_filecheck_entry *p;
 
-	if (!atomic_dec_and_test(&entry->fs_count))
-		wait_on_atomic_t(&entry->fs_count, ocfs2_filecheck_sysfs_wait,
+	if (!refcount_dec_and_test(&entry->fs_count))
+		/* FIXME: Exposes refcount_t internals! */
+		wait_on_atomic_t(&entry->fs_count.refs,
+				 ocfs2_filecheck_sysfs_wait,
 				 TASK_UNINTERRUPTIBLE);
 
 	spin_lock(&entry->fs_fcheck->fc_lock);
@@ -188,8 +191,8 @@ static int ocfs2_filecheck_sysfs_del(const char *devname)
 static void
 ocfs2_filecheck_sysfs_put(struct ocfs2_filecheck_sysfs_entry *entry)
 {
-	if (atomic_dec_and_test(&entry->fs_count))
-		wake_up_atomic_t(&entry->fs_count);
+	if (refcount_dec_and_test(&entry->fs_count))
+		wake_up_atomic_t(&entry->fs_count.refs);
 }
 
 static struct ocfs2_filecheck_sysfs_entry *
@@ -200,7 +203,7 @@ ocfs2_filecheck_sysfs_get(const char *devname)
 	spin_lock(&ocfs2_filecheck_sysfs_lock);
 	list_for_each_entry(p, &ocfs2_filecheck_sysfs_list, fs_list) {
 		if (!strcmp(p->fs_sb->s_id, devname)) {
-			atomic_inc(&p->fs_count);
+			refcount_inc(&p->fs_count);
 			spin_unlock(&ocfs2_filecheck_sysfs_lock);
 			return p;
 		}
@@ -276,7 +279,7 @@ int ocfs2_filecheck_create_sysfs(struct super_block *sb)
 		ret = -ENOMEM;
 		goto error;
 	} else {
-		atomic_set(&entry->fs_count, 1);
+		refcount_set(&entry->fs_count, 1);
 		entry->fs_sb = sb;
 		entry->fs_devicekset = device_kset;
 		entry->fs_fcheckkset = fcheck_kset;
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 5955220..71d0774 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -42,7 +42,7 @@ struct posix_acl *get_cached_acl(struct inode *inode, int type)
 		rcu_read_lock();
 		acl = rcu_dereference(*p);
 		if (!acl || is_uncached_acl(acl) ||
-		    atomic_inc_not_zero(&acl->a_refcount))
+		    refcount_inc_not_zero(&acl->a_refcount))
 			break;
 		rcu_read_unlock();
 		cpu_relax();
@@ -163,7 +163,7 @@ EXPORT_SYMBOL(get_acl);
 void
 posix_acl_init(struct posix_acl *acl, int count)
 {
-	atomic_set(&acl->a_refcount, 1);
+	refcount_set(&acl->a_refcount, 1);
 	acl->a_count = count;
 }
 EXPORT_SYMBOL(posix_acl_init);
@@ -196,7 +196,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
 		           sizeof(struct posix_acl_entry);
 		clone = kmemdup(acl, size, flags);
 		if (clone)
-			atomic_set(&clone->a_refcount, 1);
+			refcount_set(&clone->a_refcount, 1);
 	}
 	return clone;
 }
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index f6a01f0..f7d462d 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -387,7 +387,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
 	ent->mode = mode;
 	ent->nlink = nlink;
 	ent->subdir = RB_ROOT;
-	atomic_set(&ent->count, 1);
+	refcount_set(&ent->count, 1);
 	spin_lock_init(&ent->pde_unload_lock);
 	INIT_LIST_HEAD(&ent->pde_openers);
 	proc_set_user(ent, (*parent)->uid, (*parent)->gid);
@@ -539,7 +539,7 @@ static void free_proc_entry(struct proc_dir_entry *de)
 
 void pde_put(struct proc_dir_entry *pde)
 {
-	if (atomic_dec_and_test(&pde->count))
+	if (refcount_dec_and_test(&pde->count))
 		free_proc_entry(pde);
 }
 
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 2de5194..1943a9b 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -13,6 +13,7 @@
 #include <linux/proc_ns.h>
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/binfmts.h>
 
 struct ctl_table_header;
@@ -41,7 +42,7 @@ struct proc_dir_entry {
 	struct rb_root subdir;
 	struct rb_node subdir_node;
 	void *data;
-	atomic_t count;		/* use count */
+	refcount_t count;	/* use count */
 	atomic_t in_use;	/* number of callers into module in progress; */
 			/* negative -> it's going away RSN */
 	struct completion *pde_unload_completion;
@@ -186,7 +187,7 @@ extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_co
 
 static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
 {
-	atomic_inc(&pde->count);
+	refcount_inc(&pde->count);
 	return pde;
 }
 extern void pde_put(struct proc_dir_entry *);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 1988440..ade9bd5 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -203,7 +203,7 @@ struct proc_dir_entry proc_root = {
 	.namelen	= 5, 
 	.mode		= S_IFDIR | S_IRUGO | S_IXUGO, 
 	.nlink		= 2, 
-	.count		= ATOMIC_INIT(1),
+	.count		= REFCOUNT_INIT(1),
 	.proc_iops	= &proc_root_inode_operations, 
 	.proc_fops	= &proc_root_operations,
 	.parent		= &proc_root,
diff --git a/fs/super.c b/fs/super.c
index 1709ed0..917995c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -240,7 +240,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
 	 */
 	down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);
 	s->s_count = 1;
-	atomic_set(&s->s_active, 1);
+	refcount_set(&s->s_active, 1);
 	mutex_init(&s->s_vfs_rename_mutex);
 	lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
 	mutex_init(&s->s_dquot.dqio_mutex);
@@ -303,7 +303,7 @@ static void put_super(struct super_block *sb)
 void deactivate_locked_super(struct super_block *s)
 {
 	struct file_system_type *fs = s->s_type;
-	if (atomic_dec_and_test(&s->s_active)) {
+	if (refcount_dec_and_test(&s->s_active)) {
 		cleancache_invalidate_fs(s);
 		unregister_shrinker(&s->s_shrink);
 		fs->kill_sb(s);
@@ -335,7 +335,7 @@ EXPORT_SYMBOL(deactivate_locked_super);
  */
 void deactivate_super(struct super_block *s)
 {
-        if (!atomic_add_unless(&s->s_active, -1, 1)) {
+	if (!refcount_dec_not_one(&s->s_active)) {
 		down_write(&s->s_umount);
 		deactivate_locked_super(s);
 	}
@@ -361,7 +361,7 @@ static int grab_super(struct super_block *s) __releases(sb_lock)
 	s->s_count++;
 	spin_unlock(&sb_lock);
 	down_write(&s->s_umount);
-	if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) {
+	if ((s->s_flags & MS_BORN) && refcount_inc_not_zero(&s->s_active)) {
 		put_super(s);
 		return 1;
 	}
@@ -1378,7 +1378,7 @@ int freeze_super(struct super_block *sb)
 {
 	int ret;
 
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	down_write(&sb->s_umount);
 	if (sb->s_writers.frozen != SB_UNFROZEN) {
 		deactivate_locked_super(sb);
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index a866d9a..2c14206 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -26,6 +26,7 @@
 #include <linux/mempolicy.h>
 #include <linux/ioctl.h>
 #include <linux/security.h>
+#include <linux/refcount.h>
 
 static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
 
@@ -48,7 +49,7 @@ struct userfaultfd_ctx {
 	/* a refile sequence protected by fault_pending_wqh lock */
 	struct seqcount refile_seq;
 	/* pseudo fd refcounting */
-	atomic_t refcount;
+	refcount_t refcount;
 	/* userfaultfd syscall flags */
 	unsigned int flags;
 	/* state machine */
@@ -116,7 +117,7 @@ static int userfaultfd_wake_function(wait_queue_t *wq, unsigned mode,
  */
 static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
 {
-	if (!atomic_inc_not_zero(&ctx->refcount))
+	if (!refcount_inc_not_zero(&ctx->refcount))
 		BUG();
 }
 
@@ -130,7 +131,7 @@ static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
  */
 static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx)
 {
-	if (atomic_dec_and_test(&ctx->refcount)) {
+	if (refcount_dec_and_test(&ctx->refcount)) {
 		VM_BUG_ON(spin_is_locked(&ctx->fault_pending_wqh.lock));
 		VM_BUG_ON(waitqueue_active(&ctx->fault_pending_wqh));
 		VM_BUG_ON(spin_is_locked(&ctx->fault_wqh.lock));
@@ -1300,7 +1301,7 @@ static struct file *userfaultfd_file_create(int flags)
 	if (!ctx)
 		goto out;
 
-	atomic_set(&ctx->refcount, 1);
+	refcount_set(&ctx->refcount, 1);
 	ctx->flags = flags;
 	ctx->state = UFFD_STATE_WAIT_API;
 	ctx->released = false;
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 9bf57c7..33104ad 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -199,7 +199,7 @@ xfs_bui_init(
 	buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
 	buip->bui_format.bui_id = (uintptr_t)(void *)buip;
 	atomic_set(&buip->bui_next_extent, 0);
-	atomic_set(&buip->bui_refcount, 2);
+	refcount_set(&buip->bui_refcount, 2);
 
 	return buip;
 }
@@ -215,7 +215,7 @@ void
 xfs_bui_release(
 	struct xfs_bui_log_item	*buip)
 {
-	if (atomic_dec_and_test(&buip->bui_refcount)) {
+	if (refcount_dec_and_test(&buip->bui_refcount)) {
 		xfs_trans_ail_remove(&buip->bui_item, SHUTDOWN_LOG_IO_ERROR);
 		xfs_bui_item_free(buip);
 	}
diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
index c867daa..988a6ae 100644
--- a/fs/xfs/xfs_bmap_item.h
+++ b/fs/xfs/xfs_bmap_item.h
@@ -20,6 +20,8 @@
 #ifndef	__XFS_BMAP_ITEM_H__
 #define	__XFS_BMAP_ITEM_H__
 
+#include <linux/refcount.h>
+
 /*
  * There are (currently) two pairs of bmap btree redo item types: map & unmap.
  * The common abbreviations for these are BUI (bmap update intent) and BUD
@@ -61,7 +63,7 @@ struct kmem_zone;
  */
 struct xfs_bui_log_item {
 	struct xfs_log_item		bui_item;
-	atomic_t			bui_refcount;
+	refcount_t			bui_refcount;
 	atomic_t			bui_next_extent;
 	unsigned long			bui_flags;	/* misc flags */
 	struct xfs_bui_log_format	bui_format;
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 7f0a01f..7f13c4b 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -151,12 +151,12 @@ xfs_buf_stale(
 	xfs_buf_ioacct_dec(bp);
 
 	spin_lock(&bp->b_lock);
-	atomic_set(&bp->b_lru_ref, 0);
+	refcount_set(&bp->b_lru_ref, 0);
 	if (!(bp->b_state & XFS_BSTATE_DISPOSE) &&
 	    (list_lru_del(&bp->b_target->bt_lru, &bp->b_lru)))
-		atomic_dec(&bp->b_hold);
+		refcount_dec(&bp->b_hold);
 
-	ASSERT(atomic_read(&bp->b_hold) >= 1);
+	ASSERT(refcount_read(&bp->b_hold) >= 1);
 	spin_unlock(&bp->b_lock);
 }
 
@@ -214,8 +214,8 @@ _xfs_buf_alloc(
 	 */
 	flags &= ~(XBF_UNMAPPED | XBF_TRYLOCK | XBF_ASYNC | XBF_READ_AHEAD);
 
-	atomic_set(&bp->b_hold, 1);
-	atomic_set(&bp->b_lru_ref, 1);
+	refcount_set(&bp->b_hold, 1);
+	refcount_set(&bp->b_lru_ref, 1);
 	init_completion(&bp->b_iowait);
 	INIT_LIST_HEAD(&bp->b_lru);
 	INIT_LIST_HEAD(&bp->b_list);
@@ -580,7 +580,7 @@ _xfs_buf_find(
 	bp = rhashtable_lookup_fast(&pag->pag_buf_hash, &cmap,
 				    xfs_buf_hash_params);
 	if (bp) {
-		atomic_inc(&bp->b_hold);
+		refcount_inc(&bp->b_hold);
 		goto found;
 	}
 
@@ -939,7 +939,7 @@ xfs_buf_hold(
 	xfs_buf_t		*bp)
 {
 	trace_xfs_buf_hold(bp, _RET_IP_);
-	atomic_inc(&bp->b_hold);
+	refcount_inc(&bp->b_hold);
 }
 
 /*
@@ -958,16 +958,16 @@ xfs_buf_rele(
 
 	if (!pag) {
 		ASSERT(list_empty(&bp->b_lru));
-		if (atomic_dec_and_test(&bp->b_hold)) {
+		if (refcount_dec_and_test(&bp->b_hold)) {
 			xfs_buf_ioacct_dec(bp);
 			xfs_buf_free(bp);
 		}
 		return;
 	}
 
-	ASSERT(atomic_read(&bp->b_hold) > 0);
+	ASSERT(refcount_read(&bp->b_hold) > 0);
 
-	release = atomic_dec_and_lock(&bp->b_hold, &pag->pag_buf_lock);
+	release = refcount_dec_and_lock(&bp->b_hold, &pag->pag_buf_lock);
 	spin_lock(&bp->b_lock);
 	if (!release) {
 		/*
@@ -976,14 +976,14 @@ xfs_buf_rele(
 		 * haven't acquired the pag lock, but the use of _XBF_IN_FLIGHT
 		 * ensures the decrement occurs only once per-buf.
 		 */
-		if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru))
+		if ((refcount_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru))
 			xfs_buf_ioacct_dec(bp);
 		goto out_unlock;
 	}
 
 	/* the last reference has been dropped ... */
 	xfs_buf_ioacct_dec(bp);
-	if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
+	if (!(bp->b_flags & XBF_STALE) && refcount_read(&bp->b_lru_ref)) {
 		/*
 		 * If the buffer is added to the LRU take a new reference to the
 		 * buffer for the LRU and clear the (now stale) dispose list
@@ -991,7 +991,7 @@ xfs_buf_rele(
 		 */
 		if (list_lru_add(&bp->b_target->bt_lru, &bp->b_lru)) {
 			bp->b_state &= ~XFS_BSTATE_DISPOSE;
-			atomic_inc(&bp->b_hold);
+			refcount_inc(&bp->b_hold);
 		}
 		spin_unlock(&pag->pag_buf_lock);
 	} else {
@@ -1597,7 +1597,7 @@ xfs_buftarg_wait_rele(
 	struct xfs_buf		*bp = container_of(item, struct xfs_buf, b_lru);
 	struct list_head	*dispose = arg;
 
-	if (atomic_read(&bp->b_hold) > 1) {
+	if (refcount_read(&bp->b_hold) > 1) {
 		/* need to wait, so skip it this pass */
 		trace_xfs_buf_wait_buftarg(bp, _RET_IP_);
 		return LRU_SKIP;
@@ -1609,7 +1609,7 @@ xfs_buftarg_wait_rele(
 	 * clear the LRU reference count so the buffer doesn't get
 	 * ignored in xfs_buf_rele().
 	 */
-	atomic_set(&bp->b_lru_ref, 0);
+	refcount_set(&bp->b_lru_ref, 0);
 	bp->b_state |= XFS_BSTATE_DISPOSE;
 	list_lru_isolate_move(lru, item, dispose);
 	spin_unlock(&bp->b_lock);
@@ -1683,7 +1683,7 @@ xfs_buftarg_isolate(
 	 * zero. If the value is already zero, we need to reclaim the
 	 * buffer, otherwise it gets another trip through the LRU.
 	 */
-	if (!atomic_add_unless(&bp->b_lru_ref, -1, 0)) {
+	if (!refcount_dec_and_test(&bp->b_lru_ref)) {
 		spin_unlock(&bp->b_lock);
 		return LRU_ROTATE;
 	}
@@ -1854,7 +1854,7 @@ xfs_buf_delwri_queue(
 	 */
 	bp->b_flags |= _XBF_DELWRI_Q;
 	if (list_empty(&bp->b_list)) {
-		atomic_inc(&bp->b_hold);
+		refcount_inc(&bp->b_hold);
 		list_add_tail(&bp->b_list, list);
 	}
 
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index 8a9d3a9..76acf28 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -27,6 +27,7 @@
 #include <linux/buffer_head.h>
 #include <linux/uio.h>
 #include <linux/list_lru.h>
+#include <linux/refcount.h>
 
 /*
  *	Base types
@@ -154,8 +155,8 @@ typedef struct xfs_buf {
 	struct rhash_head	b_rhash_head;	/* pag buffer hash node */
 	xfs_daddr_t		b_bn;		/* block number of buffer */
 	int			b_length;	/* size of buffer in BBs */
-	atomic_t		b_hold;		/* reference count */
-	atomic_t		b_lru_ref;	/* lru reclaim ref count */
+	refcount_t		b_hold;		/* reference count */
+	refcount_t		b_lru_ref;	/* lru reclaim ref count */
 	xfs_buf_flags_t		b_flags;	/* status flags */
 	struct semaphore	b_sema;		/* semaphore for lockables */
 
@@ -354,7 +355,7 @@ extern void xfs_buf_terminate(void);
 
 static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
 {
-	atomic_set(&bp->b_lru_ref, lru_ref);
+	refcount_set(&bp->b_lru_ref, lru_ref);
 }
 
 static inline int xfs_buf_ispinned(struct xfs_buf *bp)
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 2975cb2..7de4b72 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -137,7 +137,7 @@ xfs_buf_item_size(
 	struct xfs_buf_log_item	*bip = BUF_ITEM(lip);
 	int			i;
 
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 	if (bip->bli_flags & XFS_BLI_STALE) {
 		/*
 		 * The buffer is stale, so all we need to log
@@ -316,7 +316,7 @@ xfs_buf_item_format(
 	uint			offset = 0;
 	int			i;
 
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 	ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
 	       (bip->bli_flags & XFS_BLI_STALE));
 	ASSERT((bip->bli_flags & XFS_BLI_STALE) ||
@@ -383,14 +383,14 @@ xfs_buf_item_pin(
 {
 	struct xfs_buf_log_item	*bip = BUF_ITEM(lip);
 
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 	ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
 	       (bip->bli_flags & XFS_BLI_ORDERED) ||
 	       (bip->bli_flags & XFS_BLI_STALE));
 
 	trace_xfs_buf_item_pin(bip);
 
-	atomic_inc(&bip->bli_refcount);
+	refcount_inc(&bip->bli_refcount);
 	atomic_inc(&bip->bli_buf->b_pin_count);
 }
 
@@ -419,11 +419,11 @@ xfs_buf_item_unpin(
 	int		freed;
 
 	ASSERT(bp->b_fspriv == bip);
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	trace_xfs_buf_item_unpin(bip);
 
-	freed = atomic_dec_and_test(&bip->bli_refcount);
+	freed = refcount_dec_and_test(&bip->bli_refcount);
 
 	if (atomic_dec_and_test(&bp->b_pin_count))
 		wake_up_all(&bp->b_waiters);
@@ -605,7 +605,7 @@ xfs_buf_item_unlock(
 		trace_xfs_buf_item_unlock_stale(bip);
 		ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
 		if (!aborted) {
-			atomic_dec(&bip->bli_refcount);
+			refcount_dec(&bip->bli_refcount);
 			return;
 		}
 	}
@@ -642,7 +642,7 @@ xfs_buf_item_unlock(
 	 * it in this case, because an aborted transaction has already shut the
 	 * filesystem down and this is the last chance we will have to do so.
 	 */
-	if (atomic_dec_and_test(&bip->bli_refcount)) {
+	if (refcount_dec_and_test(&bip->bli_refcount)) {
 		if (clean)
 			xfs_buf_item_relse(bp);
 		else if (aborted) {
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index f7eba99..7bbdef7 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -18,6 +18,8 @@
 #ifndef	__XFS_BUF_ITEM_H__
 #define	__XFS_BUF_ITEM_H__
 
+#include <linux/refcount.h>
+
 /* kernel only definitions */
 
 /* buf log item flags */
@@ -55,7 +57,7 @@ typedef struct xfs_buf_log_item {
 	struct xfs_buf		*bli_buf;	/* real buffer pointer */
 	unsigned int		bli_flags;	/* misc flags */
 	unsigned int		bli_recur;	/* lock recursion count */
-	atomic_t		bli_refcount;	/* cnt of tp refs */
+	refcount_t		bli_refcount;	/* cnt of tp refs */
 	int			bli_format_count;	/* count of headers */
 	struct xfs_buf_log_format *bli_formats;	/* array of in-log header ptrs */
 	struct xfs_buf_log_format __bli_format;	/* embedded in-log header */
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index d7bc149..4e0acf0 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -220,7 +220,7 @@ xfs_efi_init(
 	efip->efi_format.efi_nextents = nextents;
 	efip->efi_format.efi_id = (uintptr_t)(void *)efip;
 	atomic_set(&efip->efi_next_extent, 0);
-	atomic_set(&efip->efi_refcount, 2);
+	refcount_set(&efip->efi_refcount, 2);
 
 	return efip;
 }
@@ -290,7 +290,7 @@ void
 xfs_efi_release(
 	struct xfs_efi_log_item	*efip)
 {
-	if (atomic_dec_and_test(&efip->efi_refcount)) {
+	if (refcount_dec_and_test(&efip->efi_refcount)) {
 		xfs_trans_ail_remove(&efip->efi_item, SHUTDOWN_LOG_IO_ERROR);
 		xfs_efi_item_free(efip);
 	}
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index a32c794..e6da63d 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -18,6 +18,8 @@
 #ifndef	__XFS_EXTFREE_ITEM_H__
 #define	__XFS_EXTFREE_ITEM_H__
 
+#include <linux/refcount.h>
+
 /* kernel only EFI/EFD definitions */
 
 struct xfs_mount;
@@ -64,7 +66,7 @@ struct kmem_zone;
  */
 typedef struct xfs_efi_log_item {
 	xfs_log_item_t		efi_item;
-	atomic_t		efi_refcount;
+	refcount_t		efi_refcount;
 	atomic_t		efi_next_extent;
 	unsigned long		efi_flags;	/* misc flags */
 	xfs_efi_log_format_t	efi_format;
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 10dcf27..75d7ca6 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -475,7 +475,7 @@ static inline void xfs_setup_existing_inode(struct xfs_inode *ip)
 
 #define IHOLD(ip) \
 do { \
-	ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \
+	ASSERT(refcount_read(&VFS_I(ip)->i_count) > 0) ; \
 	ihold(VFS_I(ip)); \
 	trace_xfs_ihold(ip, _THIS_IP_); \
 } while (0)
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index c39ac14..1215a45 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -859,7 +859,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
 
 		spin_lock(&log->l_icloglock);
 		iclog = log->l_iclog;
-		atomic_inc(&iclog->ic_refcnt);
+		refcount_inc(&iclog->ic_refcnt);
 		xlog_state_want_sync(log, iclog);
 		spin_unlock(&log->l_icloglock);
 		error = xlog_state_release_iclog(log, iclog);
@@ -897,7 +897,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
 		 */
 		spin_lock(&log->l_icloglock);
 		iclog = log->l_iclog;
-		atomic_inc(&iclog->ic_refcnt);
+		refcount_inc(&iclog->ic_refcnt);
 
 		xlog_state_want_sync(log, iclog);
 		spin_unlock(&log->l_icloglock);
@@ -1483,7 +1483,7 @@ xlog_alloc_log(
 		iclog->ic_size = BBTOB(bp->b_length) - log->l_iclog_hsize;
 		iclog->ic_state = XLOG_STATE_ACTIVE;
 		iclog->ic_log = log;
-		atomic_set(&iclog->ic_refcnt, 0);
+		refcount_set(&iclog->ic_refcnt, 0);
 		spin_lock_init(&iclog->ic_callback_lock);
 		iclog->ic_callback_tail = &(iclog->ic_callback);
 		iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
@@ -1773,7 +1773,7 @@ xlog_sync(
 	int		size;
 
 	XFS_STATS_INC(log->l_mp, xs_log_writes);
-	ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
+	ASSERT(refcount_read(&iclog->ic_refcnt) == 0);
 
 	/* Add for LR header */
 	count_init = log->l_iclog_hsize + iclog->ic_offset;
@@ -2826,7 +2826,7 @@ xlog_state_done_syncing(
 
 	ASSERT(iclog->ic_state == XLOG_STATE_SYNCING ||
 	       iclog->ic_state == XLOG_STATE_IOERROR);
-	ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
+	ASSERT(refcount_read(&iclog->ic_refcnt) == 0);
 	ASSERT(iclog->ic_bwritecnt == 1 || iclog->ic_bwritecnt == 2);
 
 
@@ -2905,7 +2905,7 @@ xlog_state_get_iclog_space(
 
 	head = &iclog->ic_header;
 
-	atomic_inc(&iclog->ic_refcnt);	/* prevents sync */
+	refcount_inc(&iclog->ic_refcnt);	/* prevents sync */
 	log_offset = iclog->ic_offset;
 
 	/* On the 1st write to an iclog, figure out lsn.  This works
@@ -2943,7 +2943,8 @@ xlog_state_get_iclog_space(
 		 * xlog_state_release_iclog() when there is more than one
 		 * reference to the iclog.
 		 */
-		if (!atomic_add_unless(&iclog->ic_refcnt, -1, 1)) {
+
+		if (!refcount_dec_not_one(&iclog->ic_refcnt)) {
 			/* we are the only one */
 			spin_unlock(&log->l_icloglock);
 			error = xlog_state_release_iclog(log, iclog);
@@ -3081,8 +3082,8 @@ xlog_state_release_iclog(
 	if (iclog->ic_state & XLOG_STATE_IOERROR)
 		return -EIO;
 
-	ASSERT(atomic_read(&iclog->ic_refcnt) > 0);
-	if (!atomic_dec_and_lock(&iclog->ic_refcnt, &log->l_icloglock))
+	ASSERT(refcount_read(&iclog->ic_refcnt) > 0);
+	if (!refcount_dec_and_lock(&iclog->ic_refcnt, &log->l_icloglock))
 		return 0;
 
 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
@@ -3228,7 +3229,7 @@ _xfs_log_force(
 		 * previous iclog and go to sleep.
 		 */
 		if (iclog->ic_state == XLOG_STATE_DIRTY ||
-		    (atomic_read(&iclog->ic_refcnt) == 0
+		    (refcount_read(&iclog->ic_refcnt) == 0
 		     && iclog->ic_offset == 0)) {
 			iclog = iclog->ic_prev;
 			if (iclog->ic_state == XLOG_STATE_ACTIVE ||
@@ -3237,14 +3238,14 @@ _xfs_log_force(
 			else
 				goto maybe_sleep;
 		} else {
-			if (atomic_read(&iclog->ic_refcnt) == 0) {
+			if (refcount_read(&iclog->ic_refcnt) == 0) {
 				/* We are the only one with access to this
 				 * iclog.  Flush it out now.  There should
 				 * be a roundoff of zero to show that someone
 				 * has already taken care of the roundoff from
 				 * the previous sync.
 				 */
-				atomic_inc(&iclog->ic_refcnt);
+				refcount_inc(&iclog->ic_refcnt);
 				lsn = be64_to_cpu(iclog->ic_header.h_lsn);
 				xlog_state_switch_iclogs(log, iclog, 0);
 				spin_unlock(&log->l_icloglock);
@@ -3411,7 +3412,7 @@ _xfs_log_force_lsn(
 				already_slept = 1;
 				goto try_again;
 			}
-			atomic_inc(&iclog->ic_refcnt);
+			refcount_inc(&iclog->ic_refcnt);
 			xlog_state_switch_iclogs(log, iclog, 0);
 			spin_unlock(&log->l_icloglock);
 			if (xlog_state_release_iclog(log, iclog))
@@ -3508,8 +3509,8 @@ void
 xfs_log_ticket_put(
 	xlog_ticket_t	*ticket)
 {
-	ASSERT(atomic_read(&ticket->t_ref) > 0);
-	if (atomic_dec_and_test(&ticket->t_ref))
+	ASSERT(refcount_read(&ticket->t_ref) > 0);
+	if (refcount_dec_and_test(&ticket->t_ref))
 		kmem_zone_free(xfs_log_ticket_zone, ticket);
 }
 
@@ -3517,8 +3518,8 @@ xlog_ticket_t *
 xfs_log_ticket_get(
 	xlog_ticket_t	*ticket)
 {
-	ASSERT(atomic_read(&ticket->t_ref) > 0);
-	atomic_inc(&ticket->t_ref);
+	ASSERT(refcount_read(&ticket->t_ref) > 0);
+	refcount_inc(&ticket->t_ref);
 	return ticket;
 }
 
@@ -3640,7 +3641,7 @@ xlog_ticket_alloc(
 
 	unit_res = xfs_log_calc_unit_res(log->l_mp, unit_bytes);
 
-	atomic_set(&tic->t_ref, 1);
+	refcount_set(&tic->t_ref, 1);
 	tic->t_task		= current;
 	INIT_LIST_HEAD(&tic->t_queue);
 	tic->t_unit_res		= unit_res;
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 2b6eec5..c94444c 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -18,6 +18,8 @@
 #ifndef	__XFS_LOG_PRIV_H__
 #define __XFS_LOG_PRIV_H__
 
+#include <linux/refcount.h>
+
 struct xfs_buf;
 struct xlog;
 struct xlog_ticket;
@@ -168,7 +170,7 @@ typedef struct xlog_ticket {
 	struct list_head   t_queue;	 /* reserve/write queue */
 	struct task_struct *t_task;	 /* task that owns this ticket */
 	xlog_tid_t	   t_tid;	 /* transaction identifier	 : 4  */
-	atomic_t	   t_ref;	 /* ticket reference count       : 4  */
+	refcount_t	   t_ref;	 /* ticket reference count       : 4  */
 	int		   t_curr_res;	 /* current reservation in bytes : 4  */
 	int		   t_unit_res;	 /* unit reservation in bytes    : 4  */
 	char		   t_ocnt;	 /* original count		 : 1  */
@@ -232,7 +234,7 @@ typedef struct xlog_in_core {
 	struct xfs_log_callback	**ic_callback_tail;
 
 	/* reference counts need their own cacheline */
-	atomic_t		ic_refcnt ____cacheline_aligned_in_smp;
+	refcount_t		ic_refcnt ____cacheline_aligned_in_smp;
 	xlog_in_core_2_t	*ic_data;
 #define ic_header	ic_data->hic_header
 } xlog_in_core_t;
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index fe86a66..3bd4866 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -205,7 +205,7 @@ xfs_cui_init(
 	cuip->cui_format.cui_nextents = nextents;
 	cuip->cui_format.cui_id = (uintptr_t)(void *)cuip;
 	atomic_set(&cuip->cui_next_extent, 0);
-	atomic_set(&cuip->cui_refcount, 2);
+	refcount_set(&cuip->cui_refcount, 2);
 
 	return cuip;
 }
@@ -221,7 +221,7 @@ void
 xfs_cui_release(
 	struct xfs_cui_log_item	*cuip)
 {
-	if (atomic_dec_and_test(&cuip->cui_refcount)) {
+	if (refcount_dec_and_test(&cuip->cui_refcount)) {
 		xfs_trans_ail_remove(&cuip->cui_item, SHUTDOWN_LOG_IO_ERROR);
 		xfs_cui_item_free(cuip);
 	}
diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
index 5b74ddd..7f23ff8 100644
--- a/fs/xfs/xfs_refcount_item.h
+++ b/fs/xfs/xfs_refcount_item.h
@@ -20,6 +20,8 @@
 #ifndef	__XFS_REFCOUNT_ITEM_H__
 #define	__XFS_REFCOUNT_ITEM_H__
 
+#include <linux/refcount.h>
+
 /*
  * There are (currently) two pairs of refcount btree redo item types:
  * increase and decrease.  The log items for these are CUI (refcount
@@ -63,7 +65,7 @@ struct kmem_zone;
  */
 struct xfs_cui_log_item {
 	struct xfs_log_item		cui_item;
-	atomic_t			cui_refcount;
+	refcount_t			cui_refcount;
 	atomic_t			cui_next_extent;
 	unsigned long			cui_flags;	/* misc flags */
 	struct xfs_cui_log_format	cui_format;
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index 73c8278..5e1664a 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -204,7 +204,7 @@ xfs_rui_init(
 	ruip->rui_format.rui_nextents = nextents;
 	ruip->rui_format.rui_id = (uintptr_t)(void *)ruip;
 	atomic_set(&ruip->rui_next_extent, 0);
-	atomic_set(&ruip->rui_refcount, 2);
+	refcount_set(&ruip->rui_refcount, 2);
 
 	return ruip;
 }
@@ -243,7 +243,7 @@ void
 xfs_rui_release(
 	struct xfs_rui_log_item	*ruip)
 {
-	if (atomic_dec_and_test(&ruip->rui_refcount)) {
+	if (refcount_dec_and_test(&ruip->rui_refcount)) {
 		xfs_trans_ail_remove(&ruip->rui_item, SHUTDOWN_LOG_IO_ERROR);
 		xfs_rui_item_free(ruip);
 	}
diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h
index 340c968..2529a35 100644
--- a/fs/xfs/xfs_rmap_item.h
+++ b/fs/xfs/xfs_rmap_item.h
@@ -20,6 +20,8 @@
 #ifndef	__XFS_RMAP_ITEM_H__
 #define	__XFS_RMAP_ITEM_H__
 
+#include <linux/refcount.h>
+
 /*
  * There are (currently) three pairs of rmap btree redo item types: map, unmap,
  * and convert.  The common abbreviations for these are RUI (rmap update
@@ -64,7 +66,7 @@ struct kmem_zone;
  */
 struct xfs_rui_log_item {
 	struct xfs_log_item		rui_item;
-	atomic_t			rui_refcount;
+	refcount_t			rui_refcount;
 	atomic_t			rui_next_extent;
 	unsigned long			rui_flags;	/* misc flags */
 	struct xfs_rui_log_format	rui_format;
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 69c5bcd..ba22888 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -326,7 +326,7 @@ DECLARE_EVENT_CLASS(xfs_buf_class,
 		__entry->dev = bp->b_target->bt_dev;
 		__entry->bno = bp->b_bn;
 		__entry->nblks = bp->b_length;
-		__entry->hold = atomic_read(&bp->b_hold);
+		__entry->hold = refcount_read(&bp->b_hold);
 		__entry->pincount = atomic_read(&bp->b_pin_count);
 		__entry->lockval = bp->b_sema.count;
 		__entry->flags = bp->b_flags;
@@ -395,7 +395,7 @@ DECLARE_EVENT_CLASS(xfs_buf_flags_class,
 		__entry->bno = bp->b_bn;
 		__entry->buffer_length = BBTOB(bp->b_length);
 		__entry->flags = flags;
-		__entry->hold = atomic_read(&bp->b_hold);
+		__entry->hold = refcount_read(&bp->b_hold);
 		__entry->pincount = atomic_read(&bp->b_pin_count);
 		__entry->lockval = bp->b_sema.count;
 		__entry->caller_ip = caller_ip;
@@ -438,7 +438,7 @@ TRACE_EVENT(xfs_buf_ioerror,
 		__entry->dev = bp->b_target->bt_dev;
 		__entry->bno = bp->b_bn;
 		__entry->buffer_length = BBTOB(bp->b_length);
-		__entry->hold = atomic_read(&bp->b_hold);
+		__entry->hold = refcount_read(&bp->b_hold);
 		__entry->pincount = atomic_read(&bp->b_pin_count);
 		__entry->lockval = bp->b_sema.count;
 		__entry->error = error;
@@ -479,11 +479,11 @@ DECLARE_EVENT_CLASS(xfs_buf_item_class,
 		__entry->dev = bip->bli_buf->b_target->bt_dev;
 		__entry->bli_flags = bip->bli_flags;
 		__entry->bli_recur = bip->bli_recur;
-		__entry->bli_refcount = atomic_read(&bip->bli_refcount);
+		__entry->bli_refcount = refcount_read(&bip->bli_refcount);
 		__entry->buf_bno = bip->bli_buf->b_bn;
 		__entry->buf_len = BBTOB(bip->bli_buf->b_length);
 		__entry->buf_flags = bip->bli_buf->b_flags;
-		__entry->buf_hold = atomic_read(&bip->bli_buf->b_hold);
+		__entry->buf_hold = refcount_read(&bip->bli_buf->b_hold);
 		__entry->buf_pincount = atomic_read(&bip->bli_buf->b_pin_count);
 		__entry->buf_lockval = bip->bli_buf->b_sema.count;
 		__entry->li_desc = bip->bli_item.li_desc;
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 8ee29ca..fa7f213 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -97,7 +97,7 @@ _xfs_trans_bjoin(
 	/*
 	 * Take a reference for this transaction on the buf item.
 	 */
-	atomic_inc(&bip->bli_refcount);
+	refcount_inc(&bip->bli_refcount);
 
 	/*
 	 * Get a log_item_desc to point at the new item.
@@ -161,7 +161,7 @@ xfs_trans_get_buf_map(
 		ASSERT(bp->b_transp == tp);
 		bip = bp->b_fspriv;
 		ASSERT(bip != NULL);
-		ASSERT(atomic_read(&bip->bli_refcount) > 0);
+		ASSERT(refcount_read(&bip->bli_refcount) > 0);
 		bip->bli_recur++;
 		trace_xfs_trans_get_buf_recur(bip);
 		return bp;
@@ -212,7 +212,7 @@ xfs_trans_getsb(xfs_trans_t	*tp,
 	if (bp->b_transp == tp) {
 		bip = bp->b_fspriv;
 		ASSERT(bip != NULL);
-		ASSERT(atomic_read(&bip->bli_refcount) > 0);
+		ASSERT(refcount_read(&bip->bli_refcount) > 0);
 		bip->bli_recur++;
 		trace_xfs_trans_getsb_recur(bip);
 		return bp;
@@ -282,7 +282,7 @@ xfs_trans_read_buf_map(
 		bip = bp->b_fspriv;
 		bip->bli_recur++;
 
-		ASSERT(atomic_read(&bip->bli_refcount) > 0);
+		ASSERT(refcount_read(&bip->bli_refcount) > 0);
 		trace_xfs_trans_read_buf_recur(bip);
 		*bpp = bp;
 		return 0;
@@ -371,7 +371,7 @@ xfs_trans_brelse(xfs_trans_t	*tp,
 	ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
 	ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	trace_xfs_trans_brelse(bip);
 
@@ -419,7 +419,7 @@ xfs_trans_brelse(xfs_trans_t	*tp,
 	/*
 	 * Drop our reference to the buf log item.
 	 */
-	atomic_dec(&bip->bli_refcount);
+	refcount_dec(&bip->bli_refcount);
 
 	/*
 	 * If the buf item is not tracking data in the log, then
@@ -432,7 +432,7 @@ xfs_trans_brelse(xfs_trans_t	*tp,
 /***
 		ASSERT(bp->b_pincount == 0);
 ***/
-		ASSERT(atomic_read(&bip->bli_refcount) == 0);
+		ASSERT(refcount_read(&bip->bli_refcount) == 0);
 		ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL));
 		ASSERT(!(bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF));
 		xfs_buf_item_relse(bp);
@@ -458,7 +458,7 @@ xfs_trans_bhold(xfs_trans_t	*tp,
 	ASSERT(bip != NULL);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
 	ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_HOLD;
 	trace_xfs_trans_bhold(bip);
@@ -478,7 +478,7 @@ xfs_trans_bhold_release(xfs_trans_t	*tp,
 	ASSERT(bip != NULL);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
 	ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 	ASSERT(bip->bli_flags & XFS_BLI_HOLD);
 
 	bip->bli_flags &= ~XFS_BLI_HOLD;
@@ -520,7 +520,7 @@ xfs_trans_log_buf(xfs_trans_t	*tp,
 	 */
 	bp->b_flags |= XBF_DONE;
 
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 	bp->b_iodone = xfs_buf_iodone_callbacks;
 	bip->bli_item.li_cb = xfs_buf_iodone;
 
@@ -591,7 +591,7 @@ xfs_trans_binval(
 
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	trace_xfs_trans_binval(bip);
 
@@ -645,7 +645,7 @@ xfs_trans_inode_buf(
 
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_INODE_BUF;
 	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
@@ -669,7 +669,7 @@ xfs_trans_stale_inode_buf(
 
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_STALE_INODE;
 	bip->bli_item.li_cb = xfs_buf_iodone;
@@ -694,7 +694,7 @@ xfs_trans_inode_alloc_buf(
 
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
 	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF);
@@ -717,7 +717,7 @@ xfs_trans_ordered_buf(
 
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_ORDERED;
 	trace_xfs_buf_item_ordered(bip);
@@ -740,7 +740,7 @@ xfs_trans_buf_set_type(
 
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
-	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+	ASSERT(refcount_read(&bip->bli_refcount) > 0);
 
 	xfs_blft_to_flags(&bip->__bli_format, type);
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2ba0743..8b81c1e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -31,6 +31,7 @@
 #include <linux/workqueue.h>
 #include <linux/percpu-rwsem.h>
 #include <linux/delayed_call.h>
+#include <linux/refcount.h>
 
 #include <asm/byteorder.h>
 #include <uapi/linux/fs.h>
@@ -1301,7 +1302,7 @@ struct super_block {
 	struct dentry		*s_root;
 	struct rw_semaphore	s_umount;
 	int			s_count;
-	atomic_t		s_active;
+	refcount_t		s_active;
 #ifdef CONFIG_SECURITY
 	void                    *s_security;
 #endif
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 13ba552..c0d4188 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -21,6 +21,7 @@
 #include <linux/fscache.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/refcount.h>
 
 #define NR_MAXCACHES BITS_PER_LONG
 
@@ -37,7 +38,7 @@ struct fscache_cache_tag {
 	struct fscache_cache	*cache;		/* cache referred to by this tag */
 	unsigned long		flags;
 #define FSCACHE_TAG_RESERVED	0		/* T if tag is reserved for a cache */
-	atomic_t		usage;
+	refcount_t		usage;
 	char			name[0];	/* tag name */
 };
 
@@ -102,7 +103,7 @@ struct fscache_operation {
 #define FSCACHE_OP_KEEP_FLAGS	0x00f0	/* flags to keep when repurposing an op */
 
 	enum fscache_operation_state state;
-	atomic_t		usage;
+	refcount_t		usage;
 	unsigned		debug_id;	/* debugging ID */
 
 	/* operation processor callback
@@ -160,7 +161,7 @@ typedef int (*fscache_pages_retrieval_func_t)(struct fscache_retrieval *op,
 static inline
 struct fscache_retrieval *fscache_get_retrieval(struct fscache_retrieval *op)
 {
-	atomic_inc(&op->op.usage);
+	refcount_inc(&op->op.usage);
 	return op;
 }
 
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 0cf34d6..c9014a7 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 
 /*
  * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
@@ -130,7 +131,7 @@ struct fsnotify_group {
 	 * inotify_init() and the refcnt will hit 0 only when that fd has been
 	 * closed.
 	 */
-	atomic_t refcnt;		/* things with interest in this group */
+	refcount_t refcnt;		/* things with interest in this group */
 
 	const struct fsnotify_ops *ops;	/* how this group handles things */
 
@@ -212,7 +213,7 @@ struct fsnotify_mark {
 	__u32 mask;
 	/* We hold one for presence in g_list. Also one ref for each 'thing'
 	 * in kernel that found and may be using this mark. */
-	atomic_t refcnt;
+	refcount_t refcnt;
 	/* Group this mark is for. Set on mark creation, stable until last ref
 	 * is dropped */
 	struct fsnotify_group *group;
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 7056238..58997b8 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -15,6 +15,7 @@
 #include <linux/lockdep.h>
 #include <linux/rbtree.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/wait.h>
 
 struct file;
@@ -104,7 +105,7 @@ struct kernfs_elem_attr {
  * active reference.
  */
 struct kernfs_node {
-	atomic_t		count;
+	refcount_t		count;
 	atomic_t		active;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map	dep_map;
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index c153738..850240f 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -16,6 +16,7 @@
 #include <net/ipv6.h>
 #include <linux/fs.h>
 #include <linux/kref.h>
+#include <linux/refcount.h>
 #include <linux/utsname.h>
 #include <linux/lockd/bind.h>
 #include <linux/lockd/xdr.h>
@@ -57,7 +58,7 @@ struct nlm_host {
 	u32			h_state;	/* pseudo-state counter */
 	u32			h_nsmstate;	/* true remote NSM state */
 	u32			h_pidcount;	/* Pseudopids */
-	atomic_t		h_count;	/* reference count */
+	refcount_t		h_count;	/* reference count */
 	struct mutex		h_mutex;	/* mutex for pmap binding */
 	unsigned long		h_nextrebind;	/* next portmap call */
 	unsigned long		h_expires;	/* eligible for GC */
@@ -81,7 +82,7 @@ struct nlm_host {
 
 struct nsm_handle {
 	struct list_head	sm_link;
-	atomic_t		sm_count;
+	refcount_t		sm_count;
 	char			*sm_mon_name;
 	char			*sm_name;
 	struct sockaddr_storage	sm_addr;
@@ -120,7 +121,7 @@ static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host)
  */
 struct nlm_lockowner {
 	struct list_head list;
-	atomic_t count;
+	refcount_t count;
 
 	struct nlm_host *host;
 	fl_owner_t owner;
@@ -134,7 +135,7 @@ struct nlm_wait;
  */
 #define NLMCLNT_OHSIZE		((__NEW_UTS_LEN) + 10u)
 struct nlm_rqst {
-	atomic_t		a_count;
+	refcount_t		a_count;
 	unsigned int		a_flags;	/* initial RPC task flags */
 	struct nlm_host *	a_host;		/* host handle */
 	struct nlm_args		a_args;		/* arguments */
diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h
index 86c9a8b..251e268 100644
--- a/include/linux/mbcache.h
+++ b/include/linux/mbcache.h
@@ -4,7 +4,7 @@
 #include <linux/hash.h>
 #include <linux/list_bl.h>
 #include <linux/list.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/fs.h>
 
 struct mb_cache;
@@ -14,7 +14,7 @@ struct mb_cache_entry {
 	struct list_head	e_list;
 	/* Hash table list - protected by hash chain bitlock */
 	struct hlist_bl_node	e_hash_list;
-	atomic_t		e_refcnt;
+	refcount_t		e_refcnt;
 	/* Key in hash - stable during lifetime of the entry */
 	u32			e_key;
 	u32			e_referenced:1;
@@ -32,7 +32,7 @@ void __mb_cache_entry_free(struct mb_cache_entry *entry);
 static inline int mb_cache_entry_put(struct mb_cache *cache,
 				     struct mb_cache_entry *entry)
 {
-	if (!atomic_dec_and_test(&entry->e_refcnt))
+	if (!refcount_dec_and_test(&entry->e_refcnt))
 		return 0;
 	__mb_cache_entry_free(entry);
 	return 1;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index f1da8c8..0437374 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 #include <linux/rwsem.h>
 #include <linux/wait.h>
 
@@ -56,7 +57,7 @@ struct nfs_access_entry {
 };
 
 struct nfs_lock_context {
-	atomic_t count;
+	refcount_t count;
 	struct list_head list;
 	struct nfs_open_context *open_context;
 	fl_owner_t lockowner;
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index b34097c..116b140 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -9,6 +9,7 @@
 #include <linux/sunrpc/xprt.h>
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct nfs4_session;
 struct nfs_iostats;
@@ -24,8 +25,8 @@ struct nfs41_impl_id;
  * The nfs_client identifies our client state to the server.
  */
 struct nfs_client {
-	atomic_t		cl_count;
-	atomic_t		cl_mds_count;
+	refcount_t		cl_count;
+	refcount_t		cl_mds_count;
 	int			cl_cons_state;	/* current construction state (-ve: init error) */
 #define NFS_CS_READY		0		/* ready to be used */
 #define NFS_CS_INITING		1		/* busy initialising */
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 5a9a739..e3a4fc9 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -11,6 +11,7 @@
 #include <linux/bug.h>
 #include <linux/slab.h>
 #include <linux/rcupdate.h>
+#include <linux/refcount.h>
 #include <uapi/linux/posix_acl.h>
 
 struct posix_acl_entry {
@@ -23,7 +24,7 @@ struct posix_acl_entry {
 };
 
 struct posix_acl {
-	atomic_t		a_refcount;
+	refcount_t		a_refcount;
 	struct rcu_head		a_rcu;
 	unsigned int		a_count;
 	struct posix_acl_entry	a_entries[0];
@@ -40,7 +41,7 @@ static inline struct posix_acl *
 posix_acl_dup(struct posix_acl *acl)
 {
 	if (acl)
-		atomic_inc(&acl->a_refcount);
+		refcount_inc(&acl->a_refcount);
 	return acl;
 }
 
@@ -50,7 +51,7 @@ posix_acl_dup(struct posix_acl *acl)
 static inline void
 posix_acl_release(struct posix_acl *acl)
 {
-	if (acl && atomic_dec_and_test(&acl->a_refcount))
+	if (acl && refcount_dec_and_test(&acl->a_refcount))
 		kfree_rcu(acl, a_rcu);
 }
 
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
index c14bed4..ce97ce7 100644
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -210,7 +210,7 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
 		__entry->block_start	= map->block_start;
 		__entry->block_len	= map->block_len;
 		__entry->flags		= map->flags;
-		__entry->refs		= atomic_read(&map->refs);
+		__entry->refs		= refcount_read(&map->refs);
 		__entry->compress_type	= map->compress_type;
 	),
 
@@ -270,7 +270,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
 		__entry->bytes_left	= ordered->bytes_left;
 		__entry->flags		= ordered->flags;
 		__entry->compress_type	= ordered->compress_type;
-		__entry->refs		= atomic_read(&ordered->refs);
+		__entry->refs		= refcount_read(&ordered->refs);
 		__entry->root_objectid	=
 				BTRFS_I(inode)->root->root_key.objectid;
 	),
@@ -765,7 +765,7 @@ TRACE_EVENT(btrfs_cow_block,
 	TP_fast_assign_btrfs(root->fs_info,
 		__entry->root_objectid	= root->root_key.objectid;
 		__entry->buf_start	= buf->start;
-		__entry->refs		= atomic_read(&buf->refs);
+		__entry->refs		= refcount_read(&buf->refs);
 		__entry->cow_start	= cow->start;
 		__entry->buf_level	= btrfs_header_level(buf);
 		__entry->cow_level	= btrfs_header_level(cow);
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index bf74eaa..8459802 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -29,7 +29,7 @@ DEFINE_SPINLOCK(mq_lock);
  * and not CONFIG_IPC_NS.
  */
 struct ipc_namespace init_ipc_ns = {
-	.count		= ATOMIC_INIT(1),
+	.count		= REFCOUNT_INIT(1),
 	.user_ns = &init_user_ns,
 	.ns.inum = PROC_IPC_INIT_INO,
 #ifdef CONFIG_IPC_NS
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 11/18] security: convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (9 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 10/18] fs: " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 12/18] sound: " Elena Reshetova
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/key.h              |  5 +++--
 security/keys/gc.c               |  2 +-
 security/keys/internal.h         |  3 ++-
 security/keys/key.c              | 12 ++++++------
 security/keys/keyring.c          |  8 ++++----
 security/keys/proc.c             |  4 ++--
 security/keys/process_keys.c     |  2 +-
 security/keys/request_key_auth.c |  2 +-
 security/selinux/hooks.c         |  9 +++++----
 security/selinux/include/xfrm.h  |  5 +++--
 security/selinux/xfrm.c          | 11 ++++++-----
 security/tomoyo/common.c         | 11 ++++++-----
 12 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/include/linux/key.h b/include/linux/key.h
index 7229147..43d468e 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -23,6 +23,7 @@
 #include <linux/rwsem.h>
 #include <linux/atomic.h>
 #include <linux/assoc_array.h>
+#include <linux/refcount.h>
 
 #ifdef __KERNEL__
 #include <linux/uidgid.h>
@@ -135,7 +136,7 @@ static inline bool is_key_possessed(const key_ref_t key_ref)
  *   - Kerberos TGTs and tickets
  */
 struct key {
-	atomic_t		usage;		/* number of references */
+	refcount_t		usage;		/* number of references */
 	key_serial_t		serial;		/* key serial number */
 	union {
 		struct list_head graveyard_link;
@@ -242,7 +243,7 @@ extern void key_put(struct key *key);
 
 static inline struct key *__key_get(struct key *key)
 {
-	atomic_inc(&key->usage);
+	refcount_inc(&key->usage);
 	return key;
 }
 
diff --git a/security/keys/gc.c b/security/keys/gc.c
index addf060..4478925 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -220,7 +220,7 @@ static void key_garbage_collector(struct work_struct *work)
 		key = rb_entry(cursor, struct key, serial_node);
 		cursor = rb_next(cursor);
 
-		if (atomic_read(&key->usage) == 0)
+		if (refcount_read(&key->usage) == 0)
 			goto found_unreferenced_key;
 
 		if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) {
diff --git a/security/keys/internal.h b/security/keys/internal.h
index a705a7d..110d661 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -16,6 +16,7 @@
 #include <linux/key-type.h>
 #include <linux/task_work.h>
 #include <linux/keyctl.h>
+#include <linux/refcount.h>
 
 struct iovec;
 
@@ -52,7 +53,7 @@ struct key_user {
 	struct rb_node		node;
 	struct mutex		cons_lock;	/* construction initiation lock */
 	spinlock_t		lock;
-	atomic_t		usage;		/* for accessing qnkeys & qnbytes */
+	refcount_t		usage;		/* for accessing qnkeys & qnbytes */
 	atomic_t		nkeys;		/* number of keys */
 	atomic_t		nikeys;		/* number of instantiated keys */
 	kuid_t			uid;
diff --git a/security/keys/key.c b/security/keys/key.c
index 346fbf2..b4958b3 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -93,7 +93,7 @@ struct key_user *key_user_lookup(kuid_t uid)
 
 	/* if we get here, then the user record still hadn't appeared on the
 	 * second pass - so we use the candidate record */
-	atomic_set(&candidate->usage, 1);
+	refcount_set(&candidate->usage, 1);
 	atomic_set(&candidate->nkeys, 0);
 	atomic_set(&candidate->nikeys, 0);
 	candidate->uid = uid;
@@ -110,7 +110,7 @@ struct key_user *key_user_lookup(kuid_t uid)
 
 	/* okay - we found a user record for this UID */
 found:
-	atomic_inc(&user->usage);
+	refcount_inc(&user->usage);
 	spin_unlock(&key_user_lock);
 	kfree(candidate);
 out:
@@ -122,7 +122,7 @@ struct key_user *key_user_lookup(kuid_t uid)
  */
 void key_user_put(struct key_user *user)
 {
-	if (atomic_dec_and_lock(&user->usage, &key_user_lock)) {
+	if (refcount_dec_and_lock(&user->usage, &key_user_lock)) {
 		rb_erase(&user->node, &key_user_tree);
 		spin_unlock(&key_user_lock);
 
@@ -285,7 +285,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
 	if (!key->index_key.description)
 		goto no_memory_3;
 
-	atomic_set(&key->usage, 1);
+	refcount_set(&key->usage, 1);
 	init_rwsem(&key->sem);
 	lockdep_set_class(&key->sem, &type->lock_class);
 	key->index_key.type = type;
@@ -621,7 +621,7 @@ void key_put(struct key *key)
 	if (key) {
 		key_check(key);
 
-		if (atomic_dec_and_test(&key->usage))
+		if (refcount_dec_and_test(&key->usage))
 			schedule_work(&key_gc_work);
 	}
 }
@@ -656,7 +656,7 @@ struct key *key_lookup(key_serial_t id)
 
 found:
 	/* pretend it doesn't exist if it is awaiting deletion */
-	if (atomic_read(&key->usage) == 0)
+	if (refcount_read(&key->usage) == 0)
 		goto not_found;
 
 	/* this races with key_put(), but that doesn't matter since key_put()
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index c91e4e0..3d95f7d 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1033,7 +1033,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
 			/* we've got a match but we might end up racing with
 			 * key_cleanup() if the keyring is currently 'dead'
 			 * (ie. it has a zero usage count) */
-			if (!atomic_inc_not_zero(&keyring->usage))
+			if (!refcount_inc_not_zero(&keyring->usage))
 				continue;
 			keyring->last_used_at = current_kernel_time().tv_sec;
 			goto out;
@@ -1250,14 +1250,14 @@ int key_link(struct key *keyring, struct key *key)
 	struct assoc_array_edit *edit;
 	int ret;
 
-	kenter("{%d,%d}", keyring->serial, atomic_read(&keyring->usage));
+	kenter("{%d,%d}", keyring->serial, refcount_read(&keyring->usage));
 
 	key_check(keyring);
 	key_check(key);
 
 	ret = __key_link_begin(keyring, &key->index_key, &edit);
 	if (ret == 0) {
-		kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage));
+		kdebug("begun {%d,%d}", keyring->serial, refcount_read(&keyring->usage));
 		ret = __key_link_check_restriction(keyring, key);
 		if (ret == 0)
 			ret = __key_link_check_live_key(keyring, key);
@@ -1266,7 +1266,7 @@ int key_link(struct key *keyring, struct key *key)
 		__key_link_end(keyring, &key->index_key, edit);
 	}
 
-	kleave(" = %d {%d,%d}", ret, keyring->serial, atomic_read(&keyring->usage));
+	kleave(" = %d {%d,%d}", ret, keyring->serial, refcount_read(&keyring->usage));
 	return ret;
 }
 EXPORT_SYMBOL(key_link);
diff --git a/security/keys/proc.c b/security/keys/proc.c
index b9f531c..bf08d02 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -252,7 +252,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
 		   showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
 		   showflag(key, 'N', KEY_FLAG_NEGATIVE),
 		   showflag(key, 'i', KEY_FLAG_INVALIDATED),
-		   atomic_read(&key->usage),
+		   refcount_read(&key->usage),
 		   xbuf,
 		   key->perm,
 		   from_kuid_munged(seq_user_ns(m), key->uid),
@@ -340,7 +340,7 @@ static int proc_key_users_show(struct seq_file *m, void *v)
 
 	seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
 		   from_kuid_munged(seq_user_ns(m), user->uid),
-		   atomic_read(&user->usage),
+		   refcount_read(&user->usage),
 		   atomic_read(&user->nkeys),
 		   atomic_read(&user->nikeys),
 		   user->qnkeys,
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 918cddc..16877c5 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -29,7 +29,7 @@ static DEFINE_MUTEX(key_user_keyring_mutex);
 
 /* The root user's tracking struct */
 struct key_user root_key_user = {
-	.usage		= ATOMIC_INIT(3),
+	.usage		= REFCOUNT_INIT(3),
 	.cons_lock	= __MUTEX_INITIALIZER(root_key_user.cons_lock),
 	.lock		= __SPIN_LOCK_UNLOCKED(root_key_user.lock),
 	.nkeys		= ATOMIC_INIT(2),
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 6bbe2f5..0f06215 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -213,7 +213,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 	if (ret < 0)
 		goto error_inst;
 
-	kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage));
+	kleave(" = {%d,%d}", authkey->serial, refcount_read(&authkey->usage));
 	return authkey;
 
 auth_key_revoked:
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c7c6619..1241b07 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -83,6 +83,7 @@
 #include <linux/export.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
+#include <linux/refcount.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -95,7 +96,7 @@
 #include "avc_ss.h"
 
 /* SECMARK reference count */
-static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
+static refcount_t selinux_secmark_refcount = REFCOUNT_INIT(0);
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 int selinux_enforcing;
@@ -141,7 +142,7 @@ static struct kmem_cache *file_security_cache;
  */
 static int selinux_secmark_enabled(void)
 {
-	return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
+	return (selinux_policycap_alwaysnetwork || refcount_read(&selinux_secmark_refcount));
 }
 
 /**
@@ -4915,12 +4916,12 @@ static int selinux_secmark_relabel_packet(u32 sid)
 
 static void selinux_secmark_refcount_inc(void)
 {
-	atomic_inc(&selinux_secmark_refcount);
+	refcount_inc(&selinux_secmark_refcount);
 }
 
 static void selinux_secmark_refcount_dec(void)
 {
-	atomic_dec(&selinux_secmark_refcount);
+	refcount_dec(&selinux_secmark_refcount);
 }
 
 static void selinux_req_classify_flow(const struct request_sock *req,
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 1450f85..182dc95 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -8,6 +8,7 @@
 #define _SELINUX_XFRM_H_
 
 #include <net/flow.h>
+#include <linux/refcount.h>
 
 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
 			      struct xfrm_user_sec_ctx *uctx,
@@ -28,11 +29,11 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
 				      const struct flowi *fl);
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
-extern atomic_t selinux_xfrm_refcount;
+extern refcount_t selinux_xfrm_refcount;
 
 static inline int selinux_xfrm_enabled(void)
 {
-	return (atomic_read(&selinux_xfrm_refcount) > 0);
+	return (refcount_read(&selinux_xfrm_refcount) > 0);
 }
 
 int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 56e354f..f485965 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -44,13 +44,14 @@
 #include <net/checksum.h>
 #include <net/udp.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include "avc.h"
 #include "objsec.h"
 #include "xfrm.h"
 
 /* Labeled XFRM instance counter */
-atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
+refcount_t selinux_xfrm_refcount = REFCOUNT_INIT(0);
 
 /*
  * Returns true if the context is an LSM/SELinux context.
@@ -111,7 +112,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
 		goto err;
 
 	*ctxp = ctx;
-	atomic_inc(&selinux_xfrm_refcount);
+	refcount_inc(&selinux_xfrm_refcount);
 	return 0;
 
 err:
@@ -127,7 +128,7 @@ static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
 	if (!ctx)
 		return;
 
-	atomic_dec(&selinux_xfrm_refcount);
+	refcount_dec(&selinux_xfrm_refcount);
 	kfree(ctx);
 }
 
@@ -302,7 +303,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
 			  GFP_ATOMIC);
 	if (!new_ctx)
 		return -ENOMEM;
-	atomic_inc(&selinux_xfrm_refcount);
+	refcount_inc(&selinux_xfrm_refcount);
 	*new_ctxp = new_ctx;
 
 	return 0;
@@ -369,7 +370,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
 	memcpy(ctx->ctx_str, ctx_str, str_len);
 
 	x->security = ctx;
-	atomic_inc(&selinux_xfrm_refcount);
+	refcount_inc(&selinux_xfrm_refcount);
 out:
 	kfree(ctx_str);
 	return rc;
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index e0fb750..9a7605a 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -7,6 +7,7 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <linux/refcount.h>
 #include "common.h"
 
 /* String table for operation mode. */
@@ -1907,7 +1908,7 @@ static DEFINE_SPINLOCK(tomoyo_query_list_lock);
  * Number of "struct file" referring /sys/kernel/security/tomoyo/query
  * interface.
  */
-static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
+static refcount_t tomoyo_query_observers = REFCOUNT_INIT(0);
 
 /**
  * tomoyo_truncate - Truncate a line.
@@ -2015,7 +2016,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
 	switch (r->mode) {
 	case TOMOYO_CONFIG_ENFORCING:
 		error = -EPERM;
-		if (atomic_read(&tomoyo_query_observers))
+		if (refcount_read(&tomoyo_query_observers))
 			break;
 		goto out;
 	case TOMOYO_CONFIG_LEARNING:
@@ -2059,7 +2060,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
 		wake_up_all(&tomoyo_query_wait);
 		if (wait_event_interruptible_timeout
 		    (tomoyo_answer_wait, entry.answer ||
-		     !atomic_read(&tomoyo_query_observers), HZ))
+		     !refcount_read(&tomoyo_query_observers), HZ))
 			break;
 		else
 			entry.timer++;
@@ -2437,7 +2438,7 @@ int tomoyo_open_control(const u8 type, struct file *file)
 	 * there is some process monitoring /sys/kernel/security/tomoyo/query.
 	 */
 	if (type == TOMOYO_QUERY)
-		atomic_inc(&tomoyo_query_observers);
+		refcount_inc(&tomoyo_query_observers);
 	file->private_data = head;
 	tomoyo_notify_gc(head, true);
 	return 0;
@@ -2687,7 +2688,7 @@ void tomoyo_close_control(struct tomoyo_io_buffer *head)
 	 * observer counter.
 	 */
 	if (head->type == TOMOYO_QUERY &&
-	    atomic_dec_and_test(&tomoyo_query_observers))
+	    refcount_dec_and_test(&tomoyo_query_observers))
 		wake_up_all(&tomoyo_answer_wait);
 	tomoyo_notify_gc(head, false);
 }
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 12/18] sound: convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (10 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 11/18] security: " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 13/18] ipc: covert " Elena Reshetova
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 sound/core/seq/seq_clientmgr.c |  2 +-
 sound/core/seq/seq_ports.c     |  8 ++++----
 sound/core/seq/seq_ports.h     |  3 ++-
 sound/usb/card.c               | 10 +++++-----
 sound/usb/usbaudio.h           |  4 +++-
 5 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 4c93520..3440f76 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -666,7 +666,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
 		down_read(&grp->list_mutex);
 	list_for_each_entry(subs, &grp->list_head, src_list) {
 		/* both ports ready? */
-		if (atomic_read(&subs->ref_count) != 2)
+		if (refcount_read(&subs->ref_count) != 2)
 			continue;
 		event->dest = subs->info.dest;
 		if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index fe686ee..d9b21a1 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -241,7 +241,7 @@ static void clear_subscriber_list(struct snd_seq_client *client,
 			 * we decrease the counter, and when both ports are deleted
 			 * remove the subscriber info
 			 */
-			if (atomic_dec_and_test(&subs->ref_count))
+			if (refcount_dec_and_test(&subs->ref_count))
 				kfree(subs);
 			continue;
 		}
@@ -520,7 +520,7 @@ static int check_and_subscribe_port(struct snd_seq_client *client,
 	else
 		list_add_tail(&subs->dest_list, &grp->list_head);
 	grp->exclusive = exclusive;
-	atomic_inc(&subs->ref_count);
+	refcount_inc(&subs->ref_count);
 	write_unlock_irq(&grp->list_lock);
 	err = 0;
 
@@ -570,7 +570,7 @@ int snd_seq_port_connect(struct snd_seq_client *connector,
 		return -ENOMEM;
 
 	subs->info = *info;
-	atomic_set(&subs->ref_count, 0);
+	refcount_set(&subs->ref_count, 0);
 	INIT_LIST_HEAD(&subs->src_list);
 	INIT_LIST_HEAD(&subs->dest_list);
 
@@ -613,7 +613,7 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
 	/* look for the connection */
 	list_for_each_entry(subs, &src->list_head, src_list) {
 		if (match_subs_info(info, &subs->info)) {
-			atomic_dec(&subs->ref_count); /* mark as not ready */
+			refcount_dec(&subs->ref_count); /* mark as not ready */
 			err = 0;
 			break;
 		}
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h
index 26bd71f..d09e396 100644
--- a/sound/core/seq/seq_ports.h
+++ b/sound/core/seq/seq_ports.h
@@ -21,6 +21,7 @@
 #ifndef __SND_SEQ_PORTS_H
 #define __SND_SEQ_PORTS_H
 
+#include <linux/refcount.h>
 #include <sound/seq_kernel.h>
 #include "seq_lock.h"
 
@@ -44,7 +45,7 @@ struct snd_seq_subscribers {
 	struct snd_seq_port_subscribe info;	/* additional info */
 	struct list_head src_list;	/* link of sources */
 	struct list_head dest_list;	/* link of destinations */
-	atomic_t ref_count;
+	refcount_t ref_count;
 };
 
 struct snd_seq_port_subs_info {
diff --git a/sound/usb/card.c b/sound/usb/card.c
index f36cb06..ff3a1d5 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -378,7 +378,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
 	chip->setup = device_setup[idx];
 	chip->autoclock = autoclock;
 	atomic_set(&chip->active, 1); /* avoid autopm during probing */
-	atomic_set(&chip->usage_count, 0);
+	refcount_set(&chip->usage_count, 0);
 	atomic_set(&chip->shutdown, 0);
 
 	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
@@ -657,7 +657,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		 * they are protected by snd_usb_lock_shutdown()
 		 */
 		wait_event(chip->shutdown_wait,
-			   !atomic_read(&chip->usage_count));
+			   !refcount_read(&chip->usage_count));
 		snd_card_disconnect(card);
 		/* release the pcm resources */
 		list_for_each_entry(as, &chip->pcm_list, list) {
@@ -692,7 +692,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip)
 {
 	int err;
 
-	atomic_inc(&chip->usage_count);
+	refcount_inc(&chip->usage_count);
 	if (atomic_read(&chip->shutdown)) {
 		err = -EIO;
 		goto error;
@@ -703,7 +703,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip)
 	return 0;
 
  error:
-	if (atomic_dec_and_test(&chip->usage_count))
+	if (refcount_dec_and_test(&chip->usage_count))
 		wake_up(&chip->shutdown_wait);
 	return err;
 }
@@ -712,7 +712,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip)
 void snd_usb_unlock_shutdown(struct snd_usb_audio *chip)
 {
 	snd_usb_autosuspend(chip);
-	if (atomic_dec_and_test(&chip->usage_count))
+	if (refcount_dec_and_test(&chip->usage_count))
 		wake_up(&chip->shutdown_wait);
 }
 
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 4d5c89a..74785d0 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -26,6 +26,8 @@
 #define USB_ID_VENDOR(id) ((id) >> 16)
 #define USB_ID_PRODUCT(id) ((u16)(id))
 
+#include <linux/refcount.h>
+
 /*
  *
  */
@@ -40,7 +42,7 @@ struct snd_usb_audio {
 	unsigned int autosuspended:1;	
 	atomic_t active;
 	atomic_t shutdown;
-	atomic_t usage_count;
+	refcount_t usage_count;
 	wait_queue_head_t shutdown_wait;
 	unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
 	unsigned int tx_length_quirk:1; /* Put length specifier in transfers */
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 13/18] ipc: covert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (11 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 12/18] sound: " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 14/18] tools: convert " Elena Reshetova
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/ipc_namespace.h | 5 +++--
 ipc/namespace.c               | 4 ++--
 ipc/sem.c                     | 8 ++++----
 ipc/util.c                    | 6 +++---
 ipc/util.h                    | 3 ++-
 5 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 848e579..7230638 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -7,6 +7,7 @@
 #include <linux/notifier.h>
 #include <linux/nsproxy.h>
 #include <linux/ns_common.h>
+#include <linux/refcount.h>
 
 struct user_namespace;
 
@@ -19,7 +20,7 @@ struct ipc_ids {
 };
 
 struct ipc_namespace {
-	atomic_t	count;
+	refcount_t	count;
 	struct ipc_ids	ids[3];
 
 	int		sem_ctls[4];
@@ -118,7 +119,7 @@ extern struct ipc_namespace *copy_ipcs(unsigned long flags,
 static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
 {
 	if (ns)
-		atomic_inc(&ns->count);
+		refcount_inc(&ns->count);
 	return ns;
 }
 
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 0abdea4..ed10bbc 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -48,7 +48,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
 		goto fail_free;
 	ns->ns.ops = &ipcns_operations;
 
-	atomic_set(&ns->count, 1);
+	refcount_set(&ns->count, 1);
 	ns->user_ns = get_user_ns(user_ns);
 	ns->ucounts = ucounts;
 
@@ -142,7 +142,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
  */
 void put_ipc_ns(struct ipc_namespace *ns)
 {
-	if (atomic_dec_and_lock(&ns->count, &mq_lock)) {
+	if (refcount_dec_and_lock(&ns->count, &mq_lock)) {
 		mq_clear_sbinfo(ns);
 		spin_unlock(&mq_lock);
 		mq_put_mnt(ns);
diff --git a/ipc/sem.c b/ipc/sem.c
index e08b948..04bab9b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -139,7 +139,7 @@ struct sem_undo {
  * that may be shared among all a CLONE_SYSVSEM task group.
  */
 struct sem_undo_list {
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	spinlock_t		lock;
 	struct list_head	list_proc;
 };
@@ -1629,7 +1629,7 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
 		if (undo_list == NULL)
 			return -ENOMEM;
 		spin_lock_init(&undo_list->lock);
-		atomic_set(&undo_list->refcnt, 1);
+		refcount_set(&undo_list->refcnt, 1);
 		INIT_LIST_HEAD(&undo_list->list_proc);
 
 		current->sysvsem.undo_list = undo_list;
@@ -2028,7 +2028,7 @@ int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
 		error = get_undo_list(&undo_list);
 		if (error)
 			return error;
-		atomic_inc(&undo_list->refcnt);
+		refcount_inc(&undo_list->refcnt);
 		tsk->sysvsem.undo_list = undo_list;
 	} else
 		tsk->sysvsem.undo_list = NULL;
@@ -2057,7 +2057,7 @@ void exit_sem(struct task_struct *tsk)
 		return;
 	tsk->sysvsem.undo_list = NULL;
 
-	if (!atomic_dec_and_test(&ulp->refcnt))
+	if (!refcount_dec_and_test(&ulp->refcnt))
 		return;
 
 	for (;;) {
diff --git a/ipc/util.c b/ipc/util.c
index 798cad1..24484a6 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -437,7 +437,7 @@ void *ipc_rcu_alloc(int size)
 	struct ipc_rcu *out = ipc_alloc(sizeof(struct ipc_rcu) + size);
 	if (unlikely(!out))
 		return NULL;
-	atomic_set(&out->refcount, 1);
+	refcount_set(&out->refcount, 1);
 	return out + 1;
 }
 
@@ -445,14 +445,14 @@ int ipc_rcu_getref(void *ptr)
 {
 	struct ipc_rcu *p = ((struct ipc_rcu *)ptr) - 1;
 
-	return atomic_inc_not_zero(&p->refcount);
+	return refcount_inc_not_zero(&p->refcount);
 }
 
 void ipc_rcu_putref(void *ptr, void (*func)(struct rcu_head *head))
 {
 	struct ipc_rcu *p = ((struct ipc_rcu *)ptr) - 1;
 
-	if (!atomic_dec_and_test(&p->refcount))
+	if (!refcount_dec_and_test(&p->refcount))
 		return;
 
 	call_rcu(&p->rcu, func);
diff --git a/ipc/util.h b/ipc/util.h
index 51f7ca5..274ec9b 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -12,6 +12,7 @@
 
 #include <linux/unistd.h>
 #include <linux/err.h>
+#include <linux/refcount.h>
 
 #define SEQ_MULTIPLIER	(IPCMNI)
 
@@ -49,7 +50,7 @@ static inline void shm_exit_ns(struct ipc_namespace *ns) { }
 
 struct ipc_rcu {
 	struct rcu_head rcu;
-	atomic_t refcount;
+	refcount_t refcount;
 } ____cacheline_aligned_in_smp;
 
 #define ipc_rcu_to_struct(p)  ((void *)(p+1))
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 14/18] tools: convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (12 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 13/18] ipc: covert " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 15/18] block: " Elena Reshetova
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 tools/perf/util/cgroup.c     |  6 +++---
 tools/perf/util/cgroup.h     |  4 ++--
 tools/perf/util/comm.c       | 10 +++++-----
 tools/perf/util/cpumap.c     | 16 ++++++++--------
 tools/perf/util/cpumap.h     |  4 ++--
 tools/perf/util/dso.c        |  6 +++---
 tools/perf/util/dso.h        |  4 ++--
 tools/perf/util/evlist.c     | 18 +++++++++---------
 tools/perf/util/evlist.h     |  4 ++--
 tools/perf/util/map.c        | 10 +++++-----
 tools/perf/util/map.h        | 10 +++++-----
 tools/perf/util/thread.c     |  6 +++---
 tools/perf/util/thread.h     |  4 ++--
 tools/perf/util/thread_map.c | 20 ++++++++++----------
 tools/perf/util/thread_map.h |  4 ++--
 15 files changed, 63 insertions(+), 63 deletions(-)

diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 8fdee24..87b9659 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -115,19 +115,19 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
 			goto found;
 		n++;
 	}
-	if (atomic_read(&cgrp->refcnt) == 0)
+	if (refcount_read(&cgrp->refcnt) == 0)
 		free(cgrp);
 
 	return -1;
 found:
-	atomic_inc(&cgrp->refcnt);
+	refcount_inc(&cgrp->refcnt);
 	counter->cgrp = cgrp;
 	return 0;
 }
 
 void close_cgroup(struct cgroup_sel *cgrp)
 {
-	if (cgrp && atomic_dec_and_test(&cgrp->refcnt)) {
+	if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) {
 		close(cgrp->fd);
 		zfree(&cgrp->name);
 		free(cgrp);
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index 31f8dcd..d91966b 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -1,14 +1,14 @@
 #ifndef __CGROUP_H__
 #define __CGROUP_H__
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct option;
 
 struct cgroup_sel {
 	char *name;
 	int fd;
-	atomic_t refcnt;
+	refcount_t refcnt;
 };
 
 
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index 21b7ff3..ef36402 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -2,12 +2,12 @@
 #include "util.h"
 #include <stdlib.h>
 #include <stdio.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct comm_str {
 	char *str;
 	struct rb_node rb_node;
-	atomic_t refcnt;
+	refcount_t refcnt;
 };
 
 /* Should perhaps be moved to struct machine */
@@ -16,13 +16,13 @@ static struct rb_root comm_str_root;
 static struct comm_str *comm_str__get(struct comm_str *cs)
 {
 	if (cs)
-		atomic_inc(&cs->refcnt);
+		refcount_inc(&cs->refcnt);
 	return cs;
 }
 
 static void comm_str__put(struct comm_str *cs)
 {
-	if (cs && atomic_dec_and_test(&cs->refcnt)) {
+	if (cs && refcount_dec_and_test(&cs->refcnt)) {
 		rb_erase(&cs->rb_node, &comm_str_root);
 		zfree(&cs->str);
 		free(cs);
@@ -43,7 +43,7 @@ static struct comm_str *comm_str__alloc(const char *str)
 		return NULL;
 	}
 
-	atomic_set(&cs->refcnt, 0);
+	refcount_set(&cs->refcnt, 0);
 
 	return cs;
 }
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 2c0b522..0e21e28 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -28,7 +28,7 @@ static struct cpu_map *cpu_map__default_new(void)
 			cpus->map[i] = i;
 
 		cpus->nr = nr_cpus;
-		atomic_set(&cpus->refcnt, 1);
+		refcount_set(&cpus->refcnt, 1);
 	}
 
 	return cpus;
@@ -42,7 +42,7 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
 	if (cpus != NULL) {
 		cpus->nr = nr_cpus;
 		memcpy(cpus->map, tmp_cpus, payload_size);
-		atomic_set(&cpus->refcnt, 1);
+		refcount_set(&cpus->refcnt, 1);
 	}
 
 	return cpus;
@@ -251,7 +251,7 @@ struct cpu_map *cpu_map__dummy_new(void)
 	if (cpus != NULL) {
 		cpus->nr = 1;
 		cpus->map[0] = -1;
-		atomic_set(&cpus->refcnt, 1);
+		refcount_set(&cpus->refcnt, 1);
 	}
 
 	return cpus;
@@ -268,7 +268,7 @@ struct cpu_map *cpu_map__empty_new(int nr)
 		for (i = 0; i < nr; i++)
 			cpus->map[i] = -1;
 
-		atomic_set(&cpus->refcnt, 1);
+		refcount_set(&cpus->refcnt, 1);
 	}
 
 	return cpus;
@@ -277,7 +277,7 @@ struct cpu_map *cpu_map__empty_new(int nr)
 static void cpu_map__delete(struct cpu_map *map)
 {
 	if (map) {
-		WARN_ONCE(atomic_read(&map->refcnt) != 0,
+		WARN_ONCE(refcount_read(&map->refcnt) != 0,
 			  "cpu_map refcnt unbalanced\n");
 		free(map);
 	}
@@ -286,13 +286,13 @@ static void cpu_map__delete(struct cpu_map *map)
 struct cpu_map *cpu_map__get(struct cpu_map *map)
 {
 	if (map)
-		atomic_inc(&map->refcnt);
+		refcount_inc(&map->refcnt);
 	return map;
 }
 
 void cpu_map__put(struct cpu_map *map)
 {
-	if (map && atomic_dec_and_test(&map->refcnt))
+	if (map && refcount_dec_and_test(&map->refcnt))
 		cpu_map__delete(map);
 }
 
@@ -356,7 +356,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
 	/* ensure we process id in increasing order */
 	qsort(c->map, c->nr, sizeof(int), cmp_ids);
 
-	atomic_set(&c->refcnt, 1);
+	refcount_set(&c->refcnt, 1);
 	*res = c;
 	return 0;
 }
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 06bd689..4f12a01 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -3,13 +3,13 @@
 
 #include <stdio.h>
 #include <stdbool.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include "perf.h"
 #include "util/debug.h"
 
 struct cpu_map {
-	atomic_t refcnt;
+	refcount_t refcnt;
 	int nr;
 	int map[];
 };
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index d2c6cdd..50f088da 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1083,7 +1083,7 @@ struct dso *dso__new(const char *name)
 		INIT_LIST_HEAD(&dso->node);
 		INIT_LIST_HEAD(&dso->data.open_entry);
 		pthread_mutex_init(&dso->lock, NULL);
-		atomic_set(&dso->refcnt, 1);
+		refcount_set(&dso->refcnt, 1);
 	}
 
 	return dso;
@@ -1121,13 +1121,13 @@ void dso__delete(struct dso *dso)
 struct dso *dso__get(struct dso *dso)
 {
 	if (dso)
-		atomic_inc(&dso->refcnt);
+		refcount_inc(&dso->refcnt);
 	return dso;
 }
 
 void dso__put(struct dso *dso)
 {
-	if (dso && atomic_dec_and_test(&dso->refcnt))
+	if (dso && refcount_dec_and_test(&dso->refcnt))
 		dso__delete(dso);
 }
 
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ecc4bbd..12350b1 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -1,7 +1,7 @@
 #ifndef __PERF_DSO
 #define __PERF_DSO
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/types.h>
 #include <linux/rbtree.h>
 #include <sys/types.h>
@@ -187,7 +187,7 @@ struct dso {
 		void	 *priv;
 		u64	 db_id;
 	};
-	atomic_t	 refcnt;
+	refcount_t	 refcnt;
 	char		 name[0];
 };
 
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d92e020..dba424d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -777,7 +777,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messu
 	/*
 	 * Check if event was unmapped due to a POLLHUP/POLLERR.
 	 */
-	if (!atomic_read(&md->refcnt))
+	if (!refcount_read(&md->refcnt))
 		return NULL;
 
 	head = perf_mmap__read_head(md);
@@ -794,7 +794,7 @@ perf_mmap__read_backward(struct perf_mmap *md)
 	/*
 	 * Check if event was unmapped due to a POLLHUP/POLLERR.
 	 */
-	if (!atomic_read(&md->refcnt))
+	if (!refcount_read(&md->refcnt))
 		return NULL;
 
 	head = perf_mmap__read_head(md);
@@ -856,7 +856,7 @@ void perf_mmap__read_catchup(struct perf_mmap *md)
 {
 	u64 head;
 
-	if (!atomic_read(&md->refcnt))
+	if (!refcount_read(&md->refcnt))
 		return;
 
 	head = perf_mmap__read_head(md);
@@ -875,14 +875,14 @@ static bool perf_mmap__empty(struct perf_mmap *md)
 
 static void perf_mmap__get(struct perf_mmap *map)
 {
-	atomic_inc(&map->refcnt);
+	refcount_inc(&map->refcnt);
 }
 
 static void perf_mmap__put(struct perf_mmap *md)
 {
-	BUG_ON(md->base && atomic_read(&md->refcnt) == 0);
+	BUG_ON(md->base && refcount_read(&md->refcnt) == 0);
 
-	if (atomic_dec_and_test(&md->refcnt))
+	if (refcount_dec_and_test(&md->refcnt))
 		perf_mmap__munmap(md);
 }
 
@@ -894,7 +894,7 @@ void perf_mmap__consume(struct perf_mmap *md, bool overwrite)
 		perf_mmap__write_tail(md, old);
 	}
 
-	if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
+	if (refcount_read(&md->refcnt) == 1 && perf_mmap__empty(md))
 		perf_mmap__put(md);
 }
 
@@ -937,7 +937,7 @@ static void perf_mmap__munmap(struct perf_mmap *map)
 		munmap(map->base, perf_mmap__mmap_len(map));
 		map->base = NULL;
 		map->fd = -1;
-		atomic_set(&map->refcnt, 0);
+		refcount_set(&map->refcnt, 0);
 	}
 	auxtrace_mmap__munmap(&map->auxtrace_mmap);
 }
@@ -1001,7 +1001,7 @@ static int perf_mmap__mmap(struct perf_mmap *map,
 	 * evlist layer can't just drop it when filtering events in
 	 * perf_evlist__filter_pollfd().
 	 */
-	atomic_set(&map->refcnt, 2);
+	refcount_set(&map->refcnt, 2);
 	map->prev = 0;
 	map->mask = mp->mask;
 	map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 4fd034f..7e6c558 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -1,7 +1,7 @@
 #ifndef __PERF_EVLIST_H
 #define __PERF_EVLIST_H 1
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/list.h>
 #include <api/fd/array.h>
 #include <stdio.h>
@@ -29,7 +29,7 @@ struct perf_mmap {
 	void		 *base;
 	int		 mask;
 	int		 fd;
-	atomic_t	 refcnt;
+	refcount_t	 refcnt;
 	u64		 prev;
 	struct auxtrace_mmap auxtrace_mmap;
 	char		 event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4f9a71c..5fa139d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -141,7 +141,7 @@ void map__init(struct map *map, enum map_type type,
 	RB_CLEAR_NODE(&map->rb_node);
 	map->groups   = NULL;
 	map->erange_warned = false;
-	atomic_set(&map->refcnt, 1);
+	refcount_set(&map->refcnt, 1);
 }
 
 struct map *map__new(struct machine *machine, u64 start, u64 len,
@@ -255,7 +255,7 @@ void map__delete(struct map *map)
 
 void map__put(struct map *map)
 {
-	if (map && atomic_dec_and_test(&map->refcnt))
+	if (map && refcount_dec_and_test(&map->refcnt))
 		map__delete(map);
 }
 
@@ -354,7 +354,7 @@ struct map *map__clone(struct map *from)
 	struct map *map = memdup(from, sizeof(*map));
 
 	if (map != NULL) {
-		atomic_set(&map->refcnt, 1);
+		refcount_set(&map->refcnt, 1);
 		RB_CLEAR_NODE(&map->rb_node);
 		dso__get(map->dso);
 		map->groups = NULL;
@@ -485,7 +485,7 @@ void map_groups__init(struct map_groups *mg, struct machine *machine)
 		maps__init(&mg->maps[i]);
 	}
 	mg->machine = machine;
-	atomic_set(&mg->refcnt, 1);
+	refcount_set(&mg->refcnt, 1);
 }
 
 static void __maps__purge(struct maps *maps)
@@ -547,7 +547,7 @@ void map_groups__delete(struct map_groups *mg)
 
 void map_groups__put(struct map_groups *mg)
 {
-	if (mg && atomic_dec_and_test(&mg->refcnt))
+	if (mg && refcount_dec_and_test(&mg->refcnt))
 		map_groups__delete(mg);
 }
 
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index abdacf8..c8a5a64 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -1,7 +1,7 @@
 #ifndef __PERF_MAP_H
 #define __PERF_MAP_H
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
@@ -51,7 +51,7 @@ struct map {
 
 	struct dso		*dso;
 	struct map_groups	*groups;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 struct kmap {
@@ -67,7 +67,7 @@ struct maps {
 struct map_groups {
 	struct maps	 maps[MAP__NR_TYPES];
 	struct machine	 *machine;
-	atomic_t	 refcnt;
+	refcount_t	 refcnt;
 };
 
 struct map_groups *map_groups__new(struct machine *machine);
@@ -77,7 +77,7 @@ bool map_groups__empty(struct map_groups *mg);
 static inline struct map_groups *map_groups__get(struct map_groups *mg)
 {
 	if (mg)
-		atomic_inc(&mg->refcnt);
+		refcount_inc(&mg->refcnt);
 	return mg;
 }
 
@@ -150,7 +150,7 @@ struct map *map__clone(struct map *map);
 static inline struct map *map__get(struct map *map)
 {
 	if (map)
-		atomic_inc(&map->refcnt);
+		refcount_inc(&map->refcnt);
 	return map;
 }
 
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index f5af87f..74e79d2 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -53,7 +53,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 			goto err_thread;
 
 		list_add(&comm->list, &thread->comm_list);
-		atomic_set(&thread->refcnt, 1);
+		refcount_set(&thread->refcnt, 1);
 		RB_CLEAR_NODE(&thread->rb_node);
 	}
 
@@ -88,13 +88,13 @@ void thread__delete(struct thread *thread)
 struct thread *thread__get(struct thread *thread)
 {
 	if (thread)
-		atomic_inc(&thread->refcnt);
+		refcount_inc(&thread->refcnt);
 	return thread;
 }
 
 void thread__put(struct thread *thread)
 {
-	if (thread && atomic_dec_and_test(&thread->refcnt)) {
+	if (thread && refcount_dec_and_test(&thread->refcnt)) {
 		/*
 		 * Remove it from the dead_threads list, as last reference
 		 * is gone.
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 99263cb..e571885 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -1,7 +1,7 @@
 #ifndef __PERF_THREAD_H
 #define __PERF_THREAD_H
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/rbtree.h>
 #include <linux/list.h>
 #include <unistd.h>
@@ -23,7 +23,7 @@ struct thread {
 	pid_t			tid;
 	pid_t			ppid;
 	int			cpu;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	char			shortname[3];
 	bool			comm_set;
 	int			comm_len;
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f9eab20..36a43c0 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -66,7 +66,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 		for (i = 0; i < items; i++)
 			thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
 		threads->nr = items;
-		atomic_set(&threads->refcnt, 1);
+		refcount_set(&threads->refcnt, 1);
 	}
 
 	for (i=0; i<items; i++)
@@ -83,7 +83,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
 	if (threads != NULL) {
 		thread_map__set_pid(threads, 0, tid);
 		threads->nr = 1;
-		atomic_set(&threads->refcnt, 1);
+		refcount_set(&threads->refcnt, 1);
 	}
 
 	return threads;
@@ -105,7 +105,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
 		goto out_free_threads;
 
 	threads->nr = 0;
-	atomic_set(&threads->refcnt, 1);
+	refcount_set(&threads->refcnt, 1);
 
 	while ((dirent = readdir(proc)) != NULL) {
 		char *end;
@@ -235,7 +235,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 out:
 	strlist__delete(slist);
 	if (threads)
-		atomic_set(&threads->refcnt, 1);
+		refcount_set(&threads->refcnt, 1);
 	return threads;
 
 out_free_namelist:
@@ -255,7 +255,7 @@ struct thread_map *thread_map__new_dummy(void)
 	if (threads != NULL) {
 		thread_map__set_pid(threads, 0, -1);
 		threads->nr = 1;
-		atomic_set(&threads->refcnt, 1);
+		refcount_set(&threads->refcnt, 1);
 	}
 	return threads;
 }
@@ -300,7 +300,7 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
 	}
 out:
 	if (threads)
-		atomic_set(&threads->refcnt, 1);
+		refcount_set(&threads->refcnt, 1);
 	return threads;
 
 out_free_threads:
@@ -326,7 +326,7 @@ static void thread_map__delete(struct thread_map *threads)
 	if (threads) {
 		int i;
 
-		WARN_ONCE(atomic_read(&threads->refcnt) != 0,
+		WARN_ONCE(refcount_read(&threads->refcnt) != 0,
 			  "thread map refcnt unbalanced\n");
 		for (i = 0; i < threads->nr; i++)
 			free(thread_map__comm(threads, i));
@@ -337,13 +337,13 @@ static void thread_map__delete(struct thread_map *threads)
 struct thread_map *thread_map__get(struct thread_map *map)
 {
 	if (map)
-		atomic_inc(&map->refcnt);
+		refcount_inc(&map->refcnt);
 	return map;
 }
 
 void thread_map__put(struct thread_map *map)
 {
-	if (map && atomic_dec_and_test(&map->refcnt))
+	if (map && refcount_dec_and_test(&map->refcnt))
 		thread_map__delete(map);
 }
 
@@ -423,7 +423,7 @@ static void thread_map__copy_event(struct thread_map *threads,
 		threads->map[i].comm = strndup(event->entries[i].comm, 16);
 	}
 
-	atomic_set(&threads->refcnt, 1);
+	refcount_set(&threads->refcnt, 1);
 }
 
 struct thread_map *thread_map__new_event(struct thread_map_event *event)
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index ea0ef08..bd34d7a 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -3,7 +3,7 @@
 
 #include <sys/types.h>
 #include <stdio.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct thread_map_data {
 	pid_t    pid;
@@ -11,7 +11,7 @@ struct thread_map_data {
 };
 
 struct thread_map {
-	atomic_t refcnt;
+	refcount_t refcnt;
 	int nr;
 	struct thread_map_data map[];
 };
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 15/18] block: convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (13 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 14/18] tools: convert " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 16/18] drivers: net " Elena Reshetova
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 block/bio.c                |  6 +++---
 block/blk-cgroup.c         |  2 +-
 block/blk-ioc.c            |  4 ++--
 block/blk-tag.c            |  8 ++++----
 block/bsg.c                |  9 +++++----
 block/cfq-iosched.c        |  4 ++--
 fs/btrfs/volumes.c         |  2 +-
 include/linux/bio.h        |  4 ++--
 include/linux/blk-cgroup.h | 11 ++++++-----
 include/linux/blk_types.h  |  3 ++-
 include/linux/blkdev.h     |  3 ++-
 include/linux/iocontext.h  |  7 ++++---
 12 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 2b37502..a8cdd62 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -275,7 +275,7 @@ void bio_init(struct bio *bio, struct bio_vec *table,
 {
 	memset(bio, 0, sizeof(*bio));
 	atomic_set(&bio->__bi_remaining, 1);
-	atomic_set(&bio->__bi_cnt, 1);
+	refcount_set(&bio->__bi_cnt, 1);
 
 	bio->bi_io_vec = table;
 	bio->bi_max_vecs = max_vecs;
@@ -543,12 +543,12 @@ void bio_put(struct bio *bio)
 	if (!bio_flagged(bio, BIO_REFFED))
 		bio_free(bio);
 	else {
-		BIO_BUG_ON(!atomic_read(&bio->__bi_cnt));
+		BIO_BUG_ON(!refcount_read(&bio->__bi_cnt));
 
 		/*
 		 * last put frees it
 		 */
-		if (atomic_dec_and_test(&bio->__bi_cnt))
+		if (refcount_dec_and_test(&bio->__bi_cnt))
 			bio_free(bio);
 	}
 }
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 8ba0af7..c3f1756 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -106,7 +106,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
 	blkg->q = q;
 	INIT_LIST_HEAD(&blkg->q_node);
 	blkg->blkcg = blkcg;
-	atomic_set(&blkg->refcnt, 1);
+	refcount_set(&blkg->refcnt, 1);
 
 	/* root blkg uses @q->root_rl, init rl only for !root blkgs */
 	if (blkcg != &blkcg_root) {
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 381cb50..36e4418 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -167,7 +167,7 @@ void put_io_context_active(struct io_context *ioc)
 	unsigned long flags;
 	struct io_cq *icq;
 
-	if (!atomic_dec_and_test(&ioc->active_ref)) {
+	if (!refcount_dec_and_test(&ioc->active_ref)) {
 		put_io_context(ioc);
 		return;
 	}
@@ -244,7 +244,7 @@ int create_task_io_context(struct task_struct *task, gfp_t gfp_flags, int node)
 	/* initialize */
 	atomic_long_set(&ioc->refcount, 1);
 	atomic_set(&ioc->nr_tasks, 1);
-	atomic_set(&ioc->active_ref, 1);
+	refcount_set(&ioc->active_ref, 1);
 	spin_lock_init(&ioc->lock);
 	INIT_RADIX_TREE(&ioc->icq_tree, GFP_ATOMIC | __GFP_HIGH);
 	INIT_HLIST_HEAD(&ioc->icq_list);
diff --git a/block/blk-tag.c b/block/blk-tag.c
index bae1dec..95bcd77 100644
--- a/block/blk-tag.c
+++ b/block/blk-tag.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL(blk_queue_find_tag);
  */
 void blk_free_tags(struct blk_queue_tag *bqt)
 {
-	if (atomic_dec_and_test(&bqt->refcnt)) {
+	if (refcount_dec_and_test(&bqt->refcnt)) {
 		BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) <
 							bqt->max_depth);
 
@@ -130,7 +130,7 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q,
 	if (init_tag_map(q, tags, depth))
 		goto fail;
 
-	atomic_set(&tags->refcnt, 1);
+	refcount_set(&tags->refcnt, 1);
 	tags->alloc_policy = alloc_policy;
 	tags->next_tag = 0;
 	return tags;
@@ -180,7 +180,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
 		queue_flag_set(QUEUE_FLAG_QUEUED, q);
 		return 0;
 	} else
-		atomic_inc(&tags->refcnt);
+		refcount_inc(&tags->refcnt);
 
 	/*
 	 * assign it, all done
@@ -225,7 +225,7 @@ int blk_queue_resize_tags(struct request_queue *q, int new_depth)
 	 * Currently cannot replace a shared tag map with a new
 	 * one, so error out if this is the case
 	 */
-	if (atomic_read(&bqt->refcnt) != 1)
+	if (refcount_read(&bqt->refcnt) != 1)
 		return -EBUSY;
 
 	/*
diff --git a/block/bsg.c b/block/bsg.c
index a57046d..987ac5f 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -21,6 +21,7 @@
 #include <linux/idr.h>
 #include <linux/bsg.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
@@ -38,7 +39,7 @@ struct bsg_device {
 	struct list_head busy_list;
 	struct list_head done_list;
 	struct hlist_node dev_list;
-	atomic_t ref_count;
+	refcount_t ref_count;
 	int queued_cmds;
 	int done_cmds;
 	wait_queue_head_t wq_done;
@@ -716,7 +717,7 @@ static int bsg_put_device(struct bsg_device *bd)
 
 	mutex_lock(&bsg_mutex);
 
-	do_free = atomic_dec_and_test(&bd->ref_count);
+	do_free = refcount_dec_and_test(&bd->ref_count);
 	if (!do_free) {
 		mutex_unlock(&bsg_mutex);
 		goto out;
@@ -768,7 +769,7 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
 
 	bsg_set_block(bd, file);
 
-	atomic_set(&bd->ref_count, 1);
+	refcount_set(&bd->ref_count, 1);
 	mutex_lock(&bsg_mutex);
 	hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));
 
@@ -788,7 +789,7 @@ static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
 
 	hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) {
 		if (bd->queue == q) {
-			atomic_inc(&bd->ref_count);
+			refcount_inc(&bd->ref_count);
 			goto found;
 		}
 	}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index c73a6fc..cc3dd60 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2957,7 +2957,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
 	 * task has exited, don't wait
 	 */
 	cic = cfqd->active_cic;
-	if (!cic || !atomic_read(&cic->icq.ioc->active_ref))
+	if (!cic || !refcount_read(&cic->icq.ioc->active_ref))
 		return;
 
 	/*
@@ -3955,7 +3955,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 
 	if (cfqq->next_rq && req_noidle(cfqq->next_rq))
 		enable_idle = 0;
-	else if (!atomic_read(&cic->icq.ioc->active_ref) ||
+	else if (!refcount_read(&cic->icq.ioc->active_ref) ||
 		 !cfqd->cfq_slice_idle ||
 		 (!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq)))
 		enable_idle = 0;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index c6b0424..1d0a7f9 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -442,7 +442,7 @@ static noinline void run_scheduled_bios(struct btrfs_device *device)
 		    waitqueue_active(&fs_info->async_submit_wait))
 			wake_up(&fs_info->async_submit_wait);
 
-		BUG_ON(atomic_read(&cur->__bi_cnt) == 0);
+		BUG_ON(refcount_read(&cur->__bi_cnt) == 0);
 
 		/*
 		 * if we're doing the sync list, record that our
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 7cf8a6c..6f7b865 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -229,7 +229,7 @@ static inline void bio_get(struct bio *bio)
 {
 	bio->bi_flags |= (1 << BIO_REFFED);
 	smp_mb__before_atomic();
-	atomic_inc(&bio->__bi_cnt);
+	refcount_inc(&bio->__bi_cnt);
 }
 
 static inline void bio_cnt_set(struct bio *bio, unsigned int count)
@@ -238,7 +238,7 @@ static inline void bio_cnt_set(struct bio *bio, unsigned int count)
 		bio->bi_flags |= (1 << BIO_REFFED);
 		smp_mb__before_atomic();
 	}
-	atomic_set(&bio->__bi_cnt, count);
+	refcount_set(&bio->__bi_cnt, count);
 }
 
 static inline bool bio_flagged(struct bio *bio, unsigned int bit)
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index 01b62e7..0d3efa9 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -19,6 +19,7 @@
 #include <linux/radix-tree.h>
 #include <linux/blkdev.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 
 /* percpu_counter batch for blkg_[rw]stats, per-cpu drift doesn't matter */
 #define BLKG_STAT_CPU_BATCH	(INT_MAX / 2)
@@ -122,7 +123,7 @@ struct blkcg_gq {
 	struct request_list		rl;
 
 	/* reference count */
-	atomic_t			refcnt;
+	refcount_t			refcnt;
 
 	/* is this blkg online? protected by both blkcg and q locks */
 	bool				online;
@@ -354,8 +355,8 @@ static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen)
  */
 static inline void blkg_get(struct blkcg_gq *blkg)
 {
-	WARN_ON_ONCE(atomic_read(&blkg->refcnt) <= 0);
-	atomic_inc(&blkg->refcnt);
+	WARN_ON_ONCE(refcount_read(&blkg->refcnt) == 0);
+	refcount_inc(&blkg->refcnt);
 }
 
 void __blkg_release_rcu(struct rcu_head *rcu);
@@ -366,8 +367,8 @@ void __blkg_release_rcu(struct rcu_head *rcu);
  */
 static inline void blkg_put(struct blkcg_gq *blkg)
 {
-	WARN_ON_ONCE(atomic_read(&blkg->refcnt) <= 0);
-	if (atomic_dec_and_test(&blkg->refcnt))
+	WARN_ON_ONCE(refcount_read(&blkg->refcnt) == 0);
+	if (refcount_dec_and_test(&blkg->refcnt))
 		call_rcu(&blkg->rcu_head, __blkg_release_rcu);
 }
 
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 519ea2c..baeec02 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -7,6 +7,7 @@
 
 #include <linux/types.h>
 #include <linux/bvec.h>
+#include <linux/refcount.h>
 
 struct bio_set;
 struct bio;
@@ -73,7 +74,7 @@ struct bio {
 
 	unsigned short		bi_max_vecs;	/* max bvl_vecs we can hold */
 
-	atomic_t		__bi_cnt;	/* pin count */
+	refcount_t		__bi_cnt;	/* pin count */
 
 	struct bio_vec		*bi_io_vec;	/* the actual vec list */
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 8369564..c39b0fb 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -25,6 +25,7 @@
 #include <linux/percpu-refcount.h>
 #include <linux/scatterlist.h>
 #include <linux/blkzoned.h>
+#include <linux/refcount.h>
 
 struct module;
 struct scsi_ioctl_command;
@@ -290,7 +291,7 @@ struct blk_queue_tag {
 	unsigned long *tag_map;		/* bit map of free/busy tags */
 	int max_depth;			/* what we will send to device */
 	int real_max_depth;		/* what the array can hold */
-	atomic_t refcnt;		/* map can be shared */
+	refcount_t refcnt;		/* map can be shared */
 	int alloc_policy;		/* tag allocation policy */
 	int next_tag;			/* next tag */
 };
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index df38db2..a1e28c3 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -3,6 +3,7 @@
 
 #include <linux/radix-tree.h>
 #include <linux/rcupdate.h>
+#include <linux/refcount.h>
 #include <linux/workqueue.h>
 
 enum {
@@ -96,7 +97,7 @@ struct io_cq {
  */
 struct io_context {
 	atomic_long_t refcount;
-	atomic_t active_ref;
+	refcount_t active_ref;
 	atomic_t nr_tasks;
 
 	/* all the fields below are protected by this lock */
@@ -128,9 +129,9 @@ struct io_context {
 static inline void get_io_context_active(struct io_context *ioc)
 {
 	WARN_ON_ONCE(atomic_long_read(&ioc->refcount) <= 0);
-	WARN_ON_ONCE(atomic_read(&ioc->active_ref) <= 0);
+	WARN_ON_ONCE(refcount_read(&ioc->active_ref) == 0);
 	atomic_long_inc(&ioc->refcount);
-	atomic_inc(&ioc->active_ref);
+	refcount_inc(&ioc->active_ref);
 }
 
 static inline void ioc_task_link(struct io_context *ioc)
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 16/18] drivers: net convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (14 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 15/18] block: " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 17/18] drivers: misc drivers " Elena Reshetova
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c      |  8 +++----
 drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h      |  4 +++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c        |  6 +++---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h        |  4 +++-
 drivers/net/ethernet/mellanox/mlx4/cq.c            | 12 +++++------
 drivers/net/ethernet/mellanox/mlx4/qp.c            |  8 +++----
 drivers/net/ethernet/mellanox/mlx4/srq.c           |  8 +++----
 drivers/net/ethernet/mellanox/mlx5/core/cq.c       | 16 +++++++-------
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  | 24 ++++++++++-----------
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.h  |  3 ++-
 drivers/net/ethernet/mellanox/mlx5/core/qp.c       |  6 +++---
 drivers/net/ethernet/mellanox/mlx5/core/srq.c      | 10 ++++-----
 drivers/net/ethernet/sun/niu.c                     |  6 +++---
 drivers/net/ethernet/sun/niu.h                     |  4 +++-
 drivers/net/hamradio/6pack.c                       | 12 +++++------
 drivers/net/macsec.c                               | 25 +++++++++++-----------
 drivers/net/ppp/ppp_async.c                        | 10 ++++-----
 drivers/net/ppp/ppp_generic.c                      | 17 ++++++++-------
 drivers/net/ppp/ppp_synctty.c                      | 11 +++++-----
 drivers/net/wireless/intersil/hostap/hostap_hw.c   | 12 +++++------
 drivers/net/wireless/intersil/hostap/hostap_wlan.h |  3 ++-
 .../net/wireless/intersil/orinoco/orinoco_usb.c    | 15 +++++++------
 include/linux/mlx4/device.h                        |  8 +++----
 include/linux/mlx5/cq.h                            |  4 ++--
 net/netfilter/nfnetlink_acct.c                     |  1 -
 25 files changed, 124 insertions(+), 113 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
index 7ad43af..211d97c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
@@ -108,7 +108,7 @@ int cxgb4_clip_get(const struct net_device *dev, const u32 *lip, u8 v6)
 		list_del(&ce->list);
 		INIT_LIST_HEAD(&ce->list);
 		spin_lock_init(&ce->lock);
-		atomic_set(&ce->refcnt, 0);
+		refcount_set(&ce->refcnt, 0);
 		atomic_dec(&ctbl->nfree);
 		list_add_tail(&ce->list, &ctbl->hash_list[hash]);
 		if (v6) {
@@ -139,7 +139,7 @@ int cxgb4_clip_get(const struct net_device *dev, const u32 *lip, u8 v6)
 	}
 	write_unlock_bh(&ctbl->lock);
 found:
-	atomic_inc(&ce->refcnt);
+	refcount_inc(&ce->refcnt);
 
 	return 0;
 }
@@ -179,7 +179,7 @@ void cxgb4_clip_release(const struct net_device *dev, const u32 *lip, u8 v6)
 found:
 	write_lock_bh(&ctbl->lock);
 	spin_lock_bh(&ce->lock);
-	if (atomic_dec_and_test(&ce->refcnt)) {
+	if (refcount_dec_and_test(&ce->refcnt)) {
 		list_del(&ce->list);
 		INIT_LIST_HEAD(&ce->list);
 		list_add_tail(&ce->list, &ctbl->ce_free_head);
@@ -266,7 +266,7 @@ int clip_tbl_show(struct seq_file *seq, void *v)
 			ip[0] = '\0';
 			sprintf(ip, "%pISc", &ce->addr);
 			seq_printf(seq, "%-25s   %u\n", ip,
-				   atomic_read(&ce->refcnt));
+				   refcount_read(&ce->refcnt));
 		}
 	}
 	seq_printf(seq, "Free clip entries : %d\n", atomic_read(&ctbl->nfree));
diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h
index 35eb43c..a0e0ae1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.h
@@ -10,9 +10,11 @@
  *  release for licensing terms and conditions.
  */
 
+#include <linux/refcount.h>
+
 struct clip_entry {
 	spinlock_t lock;	/* Hold while modifying clip reference */
-	atomic_t refcnt;
+	refcount_t refcnt;
 	struct list_head list;
 	union {
 		struct sockaddr_in addr;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 3dd8788..ebf0c06 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1727,7 +1727,7 @@ static int mtk_open(struct net_device *dev)
 	struct mtk_eth *eth = mac->hw;
 
 	/* we run 2 netdevs on the same dma ring so we only bring it up once */
-	if (!atomic_read(&eth->dma_refcnt)) {
+	if (!refcount_read(&eth->dma_refcnt)) {
 		int err = mtk_start_dma(eth);
 
 		if (err)
@@ -1738,7 +1738,7 @@ static int mtk_open(struct net_device *dev)
 		mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
 		mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
 	}
-	atomic_inc(&eth->dma_refcnt);
+	refcount_inc(&eth->dma_refcnt);
 
 	phy_start(dev->phydev);
 	netif_start_queue(dev);
@@ -1778,7 +1778,7 @@ static int mtk_stop(struct net_device *dev)
 	phy_stop(dev->phydev);
 
 	/* only shutdown DMA if this is the last user */
-	if (!atomic_dec_and_test(&eth->dma_refcnt))
+	if (!refcount_dec_and_test(&eth->dma_refcnt))
 		return 0;
 
 	mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 99b1c8e..e5b99b7 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -15,6 +15,8 @@
 #ifndef MTK_ETH_H
 #define MTK_ETH_H
 
+#include <linux/refcount.h>
+
 #define MTK_QDMA_PAGE_SIZE	2048
 #define	MTK_MAX_RX_LENGTH	1536
 #define MTK_TX_DMA_BUF_LEN	0x3fff
@@ -541,7 +543,7 @@ struct mtk_eth {
 	struct regmap			*pctl;
 	u32				chip_id;
 	bool				hwlro;
-	atomic_t			dma_refcnt;
+	refcount_t			dma_refcnt;
 	struct mtk_tx_ring		tx_ring;
 	struct mtk_rx_ring		rx_ring[MTK_MAX_RX_RING_NUM];
 	struct napi_struct		tx_napi;
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index a849da9..7691cac 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -69,7 +69,7 @@ void mlx4_cq_tasklet_cb(unsigned long data)
 	list_for_each_entry_safe(mcq, temp, &ctx->process_list, tasklet_ctx.list) {
 		list_del_init(&mcq->tasklet_ctx.list);
 		mcq->tasklet_ctx.comp(mcq);
-		if (atomic_dec_and_test(&mcq->refcount))
+		if (refcount_dec_and_test(&mcq->refcount))
 			complete(&mcq->free);
 		if (time_after(jiffies, end))
 			break;
@@ -91,7 +91,7 @@ static void mlx4_add_cq_to_tasklet(struct mlx4_cq *cq)
 	 * still arrive.
 	 */
 	if (list_empty_careful(&cq->tasklet_ctx.list)) {
-		atomic_inc(&cq->refcount);
+		refcount_inc(&cq->refcount);
 		list_add_tail(&cq->tasklet_ctx.list, &tasklet_ctx->list);
 	}
 	spin_unlock_irqrestore(&tasklet_ctx->lock, flags);
@@ -122,7 +122,7 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
 
 	cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
 	if (cq)
-		atomic_inc(&cq->refcount);
+		refcount_inc(&cq->refcount);
 
 	spin_unlock(&cq_table->lock);
 
@@ -133,7 +133,7 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
 
 	cq->event(cq, event_type);
 
-	if (atomic_dec_and_test(&cq->refcount))
+	if (refcount_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 }
 
@@ -337,7 +337,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
 	cq->cons_index = 0;
 	cq->arm_sn     = 1;
 	cq->uar        = uar;
-	atomic_set(&cq->refcount, 1);
+	refcount_set(&cq->refcount, 1);
 	init_completion(&cq->free);
 	cq->comp = mlx4_add_cq_to_tasklet;
 	cq->tasklet_ctx.priv =
@@ -379,7 +379,7 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq)
 	radix_tree_delete(&cq_table->tree, cq->cqn);
 	spin_unlock_irq(&cq_table->lock);
 
-	if (atomic_dec_and_test(&cq->refcount))
+	if (refcount_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 	wait_for_completion(&cq->free);
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index d1cd9c3..6d15227 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -55,7 +55,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)
 
 	qp = __mlx4_qp_lookup(dev, qpn);
 	if (qp)
-		atomic_inc(&qp->refcount);
+		refcount_inc(&qp->refcount);
 
 	spin_unlock(&qp_table->lock);
 
@@ -66,7 +66,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)
 
 	qp->event(qp, event_type);
 
-	if (atomic_dec_and_test(&qp->refcount))
+	if (refcount_dec_and_test(&qp->refcount))
 		complete(&qp->free);
 }
 
@@ -406,7 +406,7 @@ int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, gfp_t gfp)
 	if (err)
 		goto err_icm;
 
-	atomic_set(&qp->refcount, 1);
+	refcount_set(&qp->refcount, 1);
 	init_completion(&qp->free);
 
 	return 0;
@@ -500,7 +500,7 @@ EXPORT_SYMBOL_GPL(mlx4_qp_remove);
 
 void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
 {
-	if (atomic_dec_and_test(&qp->refcount))
+	if (refcount_dec_and_test(&qp->refcount))
 		complete(&qp->free);
 	wait_for_completion(&qp->free);
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/srq.c b/drivers/net/ethernet/mellanox/mlx4/srq.c
index f44d089..3369f65 100644
--- a/drivers/net/ethernet/mellanox/mlx4/srq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/srq.c
@@ -49,7 +49,7 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
 	srq = radix_tree_lookup(&srq_table->tree, srqn & (dev->caps.num_srqs - 1));
 	rcu_read_unlock();
 	if (srq)
-		atomic_inc(&srq->refcount);
+		refcount_inc(&srq->refcount);
 	else {
 		mlx4_warn(dev, "Async event for bogus SRQ %08x\n", srqn);
 		return;
@@ -57,7 +57,7 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
 
 	srq->event(srq, event_type);
 
-	if (atomic_dec_and_test(&srq->refcount))
+	if (refcount_dec_and_test(&srq->refcount))
 		complete(&srq->free);
 }
 
@@ -203,7 +203,7 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
 	if (err)
 		goto err_radix;
 
-	atomic_set(&srq->refcount, 1);
+	refcount_set(&srq->refcount, 1);
 	init_completion(&srq->free);
 
 	return 0;
@@ -232,7 +232,7 @@ void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq)
 	radix_tree_delete(&srq_table->tree, srq->srqn);
 	spin_unlock_irq(&srq_table->lock);
 
-	if (atomic_dec_and_test(&srq->refcount))
+	if (refcount_dec_and_test(&srq->refcount))
 		complete(&srq->free);
 	wait_for_completion(&srq->free);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
index 32d4af9..fa2917f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
@@ -58,7 +58,7 @@ void mlx5_cq_tasklet_cb(unsigned long data)
 				 tasklet_ctx.list) {
 		list_del_init(&mcq->tasklet_ctx.list);
 		mcq->tasklet_ctx.comp(mcq);
-		if (atomic_dec_and_test(&mcq->refcount))
+		if (refcount_dec_and_test(&mcq->refcount))
 			complete(&mcq->free);
 		if (time_after(jiffies, end))
 			break;
@@ -80,7 +80,7 @@ static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq)
 	 * still arrive.
 	 */
 	if (list_empty_careful(&cq->tasklet_ctx.list)) {
-		atomic_inc(&cq->refcount);
+		refcount_inc(&cq->refcount);
 		list_add_tail(&cq->tasklet_ctx.list, &tasklet_ctx->list);
 	}
 	spin_unlock_irqrestore(&tasklet_ctx->lock, flags);
@@ -94,7 +94,7 @@ void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn)
 	spin_lock(&table->lock);
 	cq = radix_tree_lookup(&table->tree, cqn);
 	if (likely(cq))
-		atomic_inc(&cq->refcount);
+		refcount_inc(&cq->refcount);
 	spin_unlock(&table->lock);
 
 	if (!cq) {
@@ -106,7 +106,7 @@ void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn)
 
 	cq->comp(cq);
 
-	if (atomic_dec_and_test(&cq->refcount))
+	if (refcount_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 }
 
@@ -119,7 +119,7 @@ void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type)
 
 	cq = radix_tree_lookup(&table->tree, cqn);
 	if (cq)
-		atomic_inc(&cq->refcount);
+		refcount_inc(&cq->refcount);
 
 	spin_unlock(&table->lock);
 
@@ -130,7 +130,7 @@ void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type)
 
 	cq->event(cq, event_type);
 
-	if (atomic_dec_and_test(&cq->refcount))
+	if (refcount_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 }
 
@@ -159,7 +159,7 @@ int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
 	cq->cqn = MLX5_GET(create_cq_out, out, cqn);
 	cq->cons_index = 0;
 	cq->arm_sn     = 0;
-	atomic_set(&cq->refcount, 1);
+	refcount_set(&cq->refcount, 1);
 	init_completion(&cq->free);
 	if (!cq->comp)
 		cq->comp = mlx5_add_cq_to_tasklet;
@@ -220,7 +220,7 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq)
 	synchronize_irq(cq->irqn);
 
 	mlx5_debug_cq_remove(dev, cq);
-	if (atomic_dec_and_test(&cq->refcount))
+	if (refcount_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 	wait_for_completion(&cq->free);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index a263d89..affba72 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -163,7 +163,7 @@ static void tree_init_node(struct fs_node *node,
 			   unsigned int refcount,
 			   void (*remove_func)(struct fs_node *))
 {
-	atomic_set(&node->refcount, refcount);
+	refcount_set(&node->refcount, refcount);
 	INIT_LIST_HEAD(&node->list);
 	INIT_LIST_HEAD(&node->children);
 	mutex_init(&node->lock);
@@ -173,7 +173,7 @@ static void tree_init_node(struct fs_node *node,
 static void tree_add_node(struct fs_node *node, struct fs_node *parent)
 {
 	if (parent)
-		atomic_inc(&parent->refcount);
+		refcount_inc(&parent->refcount);
 	node->parent = parent;
 
 	/* Parent is the root */
@@ -185,7 +185,7 @@ static void tree_add_node(struct fs_node *node, struct fs_node *parent)
 
 static void tree_get_node(struct fs_node *node)
 {
-	atomic_inc(&node->refcount);
+	refcount_inc(&node->refcount);
 }
 
 static void nested_lock_ref_node(struct fs_node *node,
@@ -193,7 +193,7 @@ static void nested_lock_ref_node(struct fs_node *node,
 {
 	if (node) {
 		mutex_lock_nested(&node->lock, class);
-		atomic_inc(&node->refcount);
+		refcount_inc(&node->refcount);
 	}
 }
 
@@ -201,14 +201,14 @@ static void lock_ref_node(struct fs_node *node)
 {
 	if (node) {
 		mutex_lock(&node->lock);
-		atomic_inc(&node->refcount);
+		refcount_inc(&node->refcount);
 	}
 }
 
 static void unlock_ref_node(struct fs_node *node)
 {
 	if (node) {
-		atomic_dec(&node->refcount);
+		refcount_dec(&node->refcount);
 		mutex_unlock(&node->lock);
 	}
 }
@@ -218,7 +218,7 @@ static void tree_put_node(struct fs_node *node)
 	struct fs_node *parent_node = node->parent;
 
 	lock_ref_node(parent_node);
-	if (atomic_dec_and_test(&node->refcount)) {
+	if (refcount_dec_and_test(&node->refcount)) {
 		if (parent_node)
 			list_del_init(&node->list);
 		if (node->remove_func)
@@ -233,8 +233,8 @@ static void tree_put_node(struct fs_node *node)
 
 static int tree_remove_node(struct fs_node *node)
 {
-	if (atomic_read(&node->refcount) > 1) {
-		atomic_dec(&node->refcount);
+	if (refcount_read(&node->refcount) > 1) {
+		refcount_dec(&node->refcount);
 		return -EEXIST;
 	}
 	tree_put_node(node);
@@ -982,7 +982,7 @@ static void destroy_flow_handle(struct fs_fte *fte,
 				int i)
 {
 	for (; --i >= 0;) {
-		if (atomic_dec_and_test(&handle->rule[i]->node.refcount)) {
+		if (refcount_dec_and_test(&handle->rule[i]->node.refcount)) {
 			fte->dests_size--;
 			list_del(&handle->rule[i]->node.list);
 			kfree(handle->rule[i]);
@@ -1013,7 +1013,7 @@ create_flow_handle(struct fs_fte *fte,
 		if (dest) {
 			rule = find_flow_rule(fte, dest + i);
 			if (rule) {
-				atomic_inc(&rule->node.refcount);
+				refcount_inc(&rule->node.refcount);
 				goto rule_found;
 			}
 		}
@@ -1273,7 +1273,7 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
 	list_add(&fte->node.list, prev);
 add_rules:
 	for (i = 0; i < handle->num_rules; i++) {
-		if (atomic_read(&handle->rule[i]->node.refcount) == 1)
+		if (refcount_read(&handle->rule[i]->node.refcount) == 1)
 			tree_add_node(&handle->rule[i]->node, &fte->node);
 	}
 unlock_fte:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index 8e668c6..86bc743 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -33,6 +33,7 @@
 #ifndef _MLX5_FS_CORE_
 #define _MLX5_FS_CORE_
 
+#include <linux/refcount.h>
 #include <linux/mlx5/fs.h>
 
 enum fs_node_type {
@@ -80,7 +81,7 @@ struct fs_node {
 	struct fs_node		*root;
 	/* lock the node for writing and traversing */
 	struct mutex		lock;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	void			(*remove_func)(struct fs_node *);
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
index d0a4005..4af636f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
@@ -50,7 +50,7 @@ static struct mlx5_core_rsc_common *mlx5_get_rsc(struct mlx5_core_dev *dev,
 
 	common = radix_tree_lookup(&table->tree, rsn);
 	if (common)
-		atomic_inc(&common->refcount);
+		refcount_inc(&common->refcount);
 
 	spin_unlock(&table->lock);
 
@@ -64,7 +64,7 @@ static struct mlx5_core_rsc_common *mlx5_get_rsc(struct mlx5_core_dev *dev,
 
 void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common)
 {
-	if (atomic_dec_and_test(&common->refcount))
+	if (refcount_dec_and_test(&common->refcount))
 		complete(&common->free);
 }
 
@@ -248,7 +248,7 @@ static int create_qprqsq_common(struct mlx5_core_dev *dev,
 	if (err)
 		return err;
 
-	atomic_set(&qp->common.refcount, 1);
+	refcount_set(&qp->common.refcount, 1);
 	init_completion(&qp->common.free);
 	qp->pid = current->pid;
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/srq.c b/drivers/net/ethernet/mellanox/mlx5/core/srq.c
index 30996300..8d6c1d4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/srq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/srq.c
@@ -48,7 +48,7 @@ void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type)
 
 	srq = radix_tree_lookup(&table->tree, srqn);
 	if (srq)
-		atomic_inc(&srq->refcount);
+		refcount_inc(&srq->refcount);
 
 	spin_unlock(&table->lock);
 
@@ -59,7 +59,7 @@ void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type)
 
 	srq->event(srq, event_type);
 
-	if (atomic_dec_and_test(&srq->refcount))
+	if (refcount_dec_and_test(&srq->refcount))
 		complete(&srq->free);
 }
 
@@ -141,7 +141,7 @@ struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn)
 
 	srq = radix_tree_lookup(&table->tree, srqn);
 	if (srq)
-		atomic_inc(&srq->refcount);
+		refcount_inc(&srq->refcount);
 
 	spin_unlock(&table->lock);
 
@@ -473,7 +473,7 @@ int mlx5_core_create_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
 	if (err)
 		return err;
 
-	atomic_set(&srq->refcount, 1);
+	refcount_set(&srq->refcount, 1);
 	init_completion(&srq->free);
 
 	spin_lock_irq(&table->lock);
@@ -515,7 +515,7 @@ int mlx5_core_destroy_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq)
 	if (err)
 		return err;
 
-	if (atomic_dec_and_test(&srq->refcount))
+	if (refcount_dec_and_test(&srq->refcount))
 		complete(&srq->free);
 	wait_for_completion(&srq->free);
 
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index f90d1af..7c39e39 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9480,7 +9480,7 @@ static struct niu_parent *niu_new_parent(struct niu *np,
 	memcpy(&p->id, id, sizeof(*id));
 	p->plat_type = ptype;
 	INIT_LIST_HEAD(&p->list);
-	atomic_set(&p->refcnt, 0);
+	refcount_set(&p->refcnt, 0);
 	list_add(&p->list, &niu_parent_list);
 	spin_lock_init(&p->lock);
 
@@ -9540,7 +9540,7 @@ static struct niu_parent *niu_get_parent(struct niu *np,
 					port_name);
 		if (!err) {
 			p->ports[port] = np;
-			atomic_inc(&p->refcnt);
+			refcount_inc(&p->refcnt);
 		}
 	}
 	mutex_unlock(&niu_parent_lock);
@@ -9568,7 +9568,7 @@ static void niu_put_parent(struct niu *np)
 	p->ports[port] = NULL;
 	np->parent = NULL;
 
-	if (atomic_dec_and_test(&p->refcnt)) {
+	if (refcount_dec_and_test(&p->refcnt)) {
 		list_del(&p->list);
 		platform_device_unregister(p->plat_dev);
 	}
diff --git a/drivers/net/ethernet/sun/niu.h b/drivers/net/ethernet/sun/niu.h
index 51e177e..fc3d2b7 100644
--- a/drivers/net/ethernet/sun/niu.h
+++ b/drivers/net/ethernet/sun/niu.h
@@ -6,6 +6,8 @@
 #ifndef _NIU_H
 #define _NIU_H
 
+#include <linux/refcount.h>
+
 #define PIO			0x000000UL
 #define FZC_PIO			0x080000UL
 #define FZC_MAC			0x180000UL
@@ -3070,7 +3072,7 @@ struct niu_parent {
 
 	struct niu		*ports[NIU_MAX_PORTS];
 
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	struct list_head	list;
 
 	spinlock_t		lock;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 922bf44..ea6c975 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -35,7 +35,7 @@
 #include <linux/tcp.h>
 #include <linux/semaphore.h>
 #include <linux/compat.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #define SIXPACK_VERSION    "Revision: 0.3.0"
 
@@ -120,7 +120,7 @@ struct sixpack {
 
 	struct timer_list	tx_t;
 	struct timer_list	resync_t;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	struct semaphore	dead_sem;
 	spinlock_t		lock;
 };
@@ -381,7 +381,7 @@ static struct sixpack *sp_get(struct tty_struct *tty)
 	read_lock(&disc_data_lock);
 	sp = tty->disc_data;
 	if (sp)
-		atomic_inc(&sp->refcnt);
+		refcount_inc(&sp->refcnt);
 	read_unlock(&disc_data_lock);
 
 	return sp;
@@ -389,7 +389,7 @@ static struct sixpack *sp_get(struct tty_struct *tty)
 
 static void sp_put(struct sixpack *sp)
 {
-	if (atomic_dec_and_test(&sp->refcnt))
+	if (refcount_dec_and_test(&sp->refcnt))
 		up(&sp->dead_sem);
 }
 
@@ -580,7 +580,7 @@ static int sixpack_open(struct tty_struct *tty)
 	sp->dev = dev;
 
 	spin_lock_init(&sp->lock);
-	atomic_set(&sp->refcnt, 1);
+	refcount_set(&sp->refcnt, 1);
 	sema_init(&sp->dead_sem, 0);
 
 	/* !!! length of the buffers. MTU is IP MTU, not PACLEN!  */
@@ -676,7 +676,7 @@ static void sixpack_close(struct tty_struct *tty)
 	 * We have now ensured that nobody can start using ap from now on, but
 	 * we have to wait for all existing users to finish.
 	 */
-	if (!atomic_dec_and_test(&sp->refcnt))
+	if (!refcount_dec_and_test(&sp->refcnt))
 		down(&sp->dead_sem);
 
 	/* We must stop the queue to avoid potentially scribbling
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index f83cf66..ec7b017 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -16,6 +16,7 @@
 #include <crypto/aead.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
+#include <linux/refcount.h>
 #include <net/genetlink.h>
 #include <net/sock.h>
 #include <net/gro_cells.h>
@@ -146,7 +147,7 @@ struct macsec_rx_sa {
 	struct macsec_key key;
 	spinlock_t lock;
 	u32 next_pn;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	bool active;
 	struct macsec_rx_sa_stats __percpu *stats;
 	struct macsec_rx_sc *sc;
@@ -171,7 +172,7 @@ struct macsec_rx_sc {
 	bool active;
 	struct macsec_rx_sa __rcu *sa[MACSEC_NUM_AN];
 	struct pcpu_rx_sc_stats __percpu *stats;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	struct rcu_head rcu_head;
 };
 
@@ -187,7 +188,7 @@ struct macsec_tx_sa {
 	struct macsec_key key;
 	spinlock_t lock;
 	u32 next_pn;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	bool active;
 	struct macsec_tx_sa_stats __percpu *stats;
 	struct rcu_head rcu;
@@ -314,7 +315,7 @@ static struct macsec_rx_sa *macsec_rxsa_get(struct macsec_rx_sa __rcu *ptr)
 	if (!sa || !sa->active)
 		return NULL;
 
-	if (!atomic_inc_not_zero(&sa->refcnt))
+	if (!refcount_inc_not_zero(&sa->refcnt))
 		return NULL;
 
 	return sa;
@@ -330,12 +331,12 @@ static void free_rx_sc_rcu(struct rcu_head *head)
 
 static struct macsec_rx_sc *macsec_rxsc_get(struct macsec_rx_sc *sc)
 {
-	return atomic_inc_not_zero(&sc->refcnt) ? sc : NULL;
+	return refcount_inc_not_zero(&sc->refcnt) ? sc : NULL;
 }
 
 static void macsec_rxsc_put(struct macsec_rx_sc *sc)
 {
-	if (atomic_dec_and_test(&sc->refcnt))
+	if (refcount_dec_and_test(&sc->refcnt))
 		call_rcu(&sc->rcu_head, free_rx_sc_rcu);
 }
 
@@ -350,7 +351,7 @@ static void free_rxsa(struct rcu_head *head)
 
 static void macsec_rxsa_put(struct macsec_rx_sa *sa)
 {
-	if (atomic_dec_and_test(&sa->refcnt))
+	if (refcount_dec_and_test(&sa->refcnt))
 		call_rcu(&sa->rcu, free_rxsa);
 }
 
@@ -361,7 +362,7 @@ static struct macsec_tx_sa *macsec_txsa_get(struct macsec_tx_sa __rcu *ptr)
 	if (!sa || !sa->active)
 		return NULL;
 
-	if (!atomic_inc_not_zero(&sa->refcnt))
+	if (!refcount_inc_not_zero(&sa->refcnt))
 		return NULL;
 
 	return sa;
@@ -378,7 +379,7 @@ static void free_txsa(struct rcu_head *head)
 
 static void macsec_txsa_put(struct macsec_tx_sa *sa)
 {
-	if (atomic_dec_and_test(&sa->refcnt))
+	if (refcount_dec_and_test(&sa->refcnt))
 		call_rcu(&sa->rcu, free_txsa);
 }
 
@@ -1321,7 +1322,7 @@ static int init_rx_sa(struct macsec_rx_sa *rx_sa, char *sak, int key_len,
 
 	rx_sa->active = false;
 	rx_sa->next_pn = 1;
-	atomic_set(&rx_sa->refcnt, 1);
+	refcount_set(&rx_sa->refcnt, 1);
 	spin_lock_init(&rx_sa->lock);
 
 	return 0;
@@ -1392,7 +1393,7 @@ static struct macsec_rx_sc *create_rx_sc(struct net_device *dev, sci_t sci)
 
 	rx_sc->sci = sci;
 	rx_sc->active = true;
-	atomic_set(&rx_sc->refcnt, 1);
+	refcount_set(&rx_sc->refcnt, 1);
 
 	secy = &macsec_priv(dev)->secy;
 	rcu_assign_pointer(rx_sc->next, secy->rx_sc);
@@ -1418,7 +1419,7 @@ static int init_tx_sa(struct macsec_tx_sa *tx_sa, char *sak, int key_len,
 	}
 
 	tx_sa->active = false;
-	atomic_set(&tx_sa->refcnt, 1);
+	refcount_set(&tx_sa->refcnt, 1);
 	spin_lock_init(&tx_sa->lock);
 
 	return 0;
diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
index feb9569..2d08f7e 100644
--- a/drivers/net/ppp/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
@@ -69,7 +69,7 @@ struct asyncppp {
 
 	struct tasklet_struct tsk;
 
-	atomic_t	refcnt;
+	refcount_t	refcnt;
 	struct semaphore dead_sem;
 	struct ppp_channel chan;	/* interface to generic ppp layer */
 	unsigned char	obuf[OBUFSIZE];
@@ -140,14 +140,14 @@ static struct asyncppp *ap_get(struct tty_struct *tty)
 	read_lock(&disc_data_lock);
 	ap = tty->disc_data;
 	if (ap != NULL)
-		atomic_inc(&ap->refcnt);
+		refcount_inc(&ap->refcnt);
 	read_unlock(&disc_data_lock);
 	return ap;
 }
 
 static void ap_put(struct asyncppp *ap)
 {
-	if (atomic_dec_and_test(&ap->refcnt))
+	if (refcount_dec_and_test(&ap->refcnt))
 		up(&ap->dead_sem);
 }
 
@@ -185,7 +185,7 @@ ppp_asynctty_open(struct tty_struct *tty)
 	skb_queue_head_init(&ap->rqueue);
 	tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
 
-	atomic_set(&ap->refcnt, 1);
+	refcount_set(&ap->refcnt, 1);
 	sema_init(&ap->dead_sem, 0);
 
 	ap->chan.private = ap;
@@ -234,7 +234,7 @@ ppp_asynctty_close(struct tty_struct *tty)
 	 * our channel ops (i.e. ppp_async_send/ioctl) are in progress
 	 * by the time it returns.
 	 */
-	if (!atomic_dec_and_test(&ap->refcnt))
+	if (!refcount_dec_and_test(&ap->refcnt))
 		down(&ap->dead_sem);
 	tasklet_kill(&ap->tsk);
 
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 3d3b1f4..474a7ec 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -50,6 +50,7 @@
 #include <asm/unaligned.h>
 #include <net/slhc_vj.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include <linux/nsproxy.h>
 #include <net/net_namespace.h>
@@ -83,7 +84,7 @@ struct ppp_file {
 	struct sk_buff_head xq;		/* pppd transmit queue */
 	struct sk_buff_head rq;		/* receive queue for pppd */
 	wait_queue_head_t rwait;	/* for poll on reading /dev/ppp */
-	atomic_t	refcnt;		/* # refs (incl /dev/ppp attached) */
+	refcount_t	refcnt;		/* # refs (incl /dev/ppp attached) */
 	int		hdrlen;		/* space to leave for headers */
 	int		index;		/* interface unit / channel number */
 	int		dead;		/* unit/channel has been shut down */
@@ -406,7 +407,7 @@ static int ppp_release(struct inode *unused, struct file *file)
 				unregister_netdevice(ppp->dev);
 			rtnl_unlock();
 		}
-		if (atomic_dec_and_test(&pf->refcnt)) {
+		if (refcount_dec_and_test(&pf->refcnt)) {
 			switch (pf->kind) {
 			case INTERFACE:
 				ppp_destroy_interface(PF_TO_PPP(pf));
@@ -879,7 +880,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
 		mutex_lock(&pn->all_ppp_mutex);
 		ppp = ppp_find_unit(pn, unit);
 		if (ppp) {
-			atomic_inc(&ppp->file.refcnt);
+			refcount_inc(&ppp->file.refcnt);
 			file->private_data = &ppp->file;
 			err = 0;
 		}
@@ -894,7 +895,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
 		spin_lock_bh(&pn->all_channels_lock);
 		chan = ppp_find_channel(pn, unit);
 		if (chan) {
-			atomic_inc(&chan->file.refcnt);
+			refcount_inc(&chan->file.refcnt);
 			file->private_data = &chan->file;
 			err = 0;
 		}
@@ -2642,7 +2643,7 @@ ppp_unregister_channel(struct ppp_channel *chan)
 
 	pch->file.dead = 1;
 	wake_up_interruptible(&pch->file.rwait);
-	if (atomic_dec_and_test(&pch->file.refcnt))
+	if (refcount_dec_and_test(&pch->file.refcnt))
 		ppp_destroy_channel(pch);
 }
 
@@ -3012,7 +3013,7 @@ init_ppp_file(struct ppp_file *pf, int kind)
 	pf->kind = kind;
 	skb_queue_head_init(&pf->xq);
 	skb_queue_head_init(&pf->rq);
-	atomic_set(&pf->refcnt, 1);
+	refcount_set(&pf->refcnt, 1);
 	init_waitqueue_head(&pf->rwait);
 }
 
@@ -3129,7 +3130,7 @@ ppp_connect_channel(struct channel *pch, int unit)
 	list_add_tail(&pch->clist, &ppp->channels);
 	++ppp->n_channels;
 	pch->ppp = ppp;
-	atomic_inc(&ppp->file.refcnt);
+	refcount_inc(&ppp->file.refcnt);
 	ppp_unlock(ppp);
 	ret = 0;
 
@@ -3160,7 +3161,7 @@ ppp_disconnect_channel(struct channel *pch)
 		if (--ppp->n_channels == 0)
 			wake_up_interruptible(&ppp->file.rwait);
 		ppp_unlock(ppp);
-		if (atomic_dec_and_test(&ppp->file.refcnt))
+		if (refcount_dec_and_test(&ppp->file.refcnt))
 			ppp_destroy_interface(ppp);
 		err = 0;
 	}
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index 9ae5398..4a643f8 100644
--- a/drivers/net/ppp/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
@@ -46,6 +46,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 #include <asm/unaligned.h>
 #include <linux/uaccess.h>
 
@@ -72,7 +73,7 @@ struct syncppp {
 
 	struct tasklet_struct tsk;
 
-	atomic_t	refcnt;
+	refcount_t	refcnt;
 	struct completion dead_cmp;
 	struct ppp_channel chan;	/* interface to generic ppp layer */
 };
@@ -141,14 +142,14 @@ static struct syncppp *sp_get(struct tty_struct *tty)
 	read_lock(&disc_data_lock);
 	ap = tty->disc_data;
 	if (ap != NULL)
-		atomic_inc(&ap->refcnt);
+		refcount_inc(&ap->refcnt);
 	read_unlock(&disc_data_lock);
 	return ap;
 }
 
 static void sp_put(struct syncppp *ap)
 {
-	if (atomic_dec_and_test(&ap->refcnt))
+	if (refcount_dec_and_test(&ap->refcnt))
 		complete(&ap->dead_cmp);
 }
 
@@ -182,7 +183,7 @@ ppp_sync_open(struct tty_struct *tty)
 	skb_queue_head_init(&ap->rqueue);
 	tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap);
 
-	atomic_set(&ap->refcnt, 1);
+	refcount_set(&ap->refcnt, 1);
 	init_completion(&ap->dead_cmp);
 
 	ap->chan.private = ap;
@@ -232,7 +233,7 @@ ppp_sync_close(struct tty_struct *tty)
 	 * our channel ops (i.e. ppp_sync_send/ioctl) are in progress
 	 * by the time it returns.
 	 */
-	if (!atomic_dec_and_test(&ap->refcnt))
+	if (!refcount_dec_and_test(&ap->refcnt))
 		wait_for_completion(&ap->dead_cmp);
 	tasklet_kill(&ap->tsk);
 
diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c
index 544ef7a..d147bcd 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_hw.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c
@@ -190,7 +190,7 @@ static inline void __hostap_cmd_queue_free(local_info_t *local,
 		}
 	}
 
-	if (atomic_dec_and_test(&entry->usecnt) && entry->del_req)
+	if (refcount_dec_and_test(&entry->usecnt) && entry->del_req)
 		kfree(entry);
 }
 
@@ -228,7 +228,7 @@ static void prism2_clear_cmd_queue(local_info_t *local)
 	spin_lock_irqsave(&local->cmdlock, flags);
 	list_for_each_safe(ptr, n, &local->cmd_queue) {
 		entry = list_entry(ptr, struct hostap_cmd_queue, list);
-		atomic_inc(&entry->usecnt);
+		refcount_inc(&entry->usecnt);
 		printk(KERN_DEBUG "%s: removed pending cmd_queue entry "
 		       "(type=%d, cmd=0x%04x, param0=0x%04x)\n",
 		       local->dev->name, entry->type, entry->cmd,
@@ -350,7 +350,7 @@ static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0,
 	if (entry == NULL)
 		return -ENOMEM;
 
-	atomic_set(&entry->usecnt, 1);
+	refcount_set(&entry->usecnt, 1);
 	entry->type = CMD_SLEEP;
 	entry->cmd = cmd;
 	entry->param0 = param0;
@@ -516,7 +516,7 @@ static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0,
 	if (entry == NULL)
 		return -ENOMEM;
 
-	atomic_set(&entry->usecnt, 1);
+	refcount_set(&entry->usecnt, 1);
 	entry->type = CMD_CALLBACK;
 	entry->cmd = cmd;
 	entry->param0 = param0;
@@ -666,7 +666,7 @@ static void prism2_cmd_ev(struct net_device *dev)
 	if (!list_empty(&local->cmd_queue)) {
 		entry = list_entry(local->cmd_queue.next,
 				   struct hostap_cmd_queue, list);
-		atomic_inc(&entry->usecnt);
+		refcount_inc(&entry->usecnt);
 		list_del_init(&entry->list);
 		local->cmd_queue_len--;
 
@@ -718,7 +718,7 @@ static void prism2_cmd_ev(struct net_device *dev)
 			entry = NULL;
 		}
 		if (entry)
-			atomic_inc(&entry->usecnt);
+			refcount_inc(&entry->usecnt);
 	}
 	spin_unlock(&local->cmdlock);
 
diff --git a/drivers/net/wireless/intersil/hostap/hostap_wlan.h b/drivers/net/wireless/intersil/hostap/hostap_wlan.h
index ca25283..5352adb 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/intersil/hostap/hostap_wlan.h
@@ -6,6 +6,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <net/iw_handler.h>
 #include <net/ieee80211_radiotap.h>
 #include <net/lib80211.h>
@@ -557,7 +558,7 @@ struct hostap_cmd_queue {
 	u16 resp0, res;
 	volatile int issued, issuing;
 
-	atomic_t usecnt;
+	refcount_t usecnt;
 	int del_req;
 };
 
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
index bca6935..465ea53 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
@@ -64,6 +64,7 @@
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/firmware.h>
+#include <linux/refcount.h>
 
 #include "mic.h"
 #include "orinoco.h"
@@ -268,7 +269,7 @@ enum ezusb_state {
 
 struct request_context {
 	struct list_head list;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct completion done;	/* Signals that CTX is dead */
 	int killed;
 	struct urb *outurb;	/* OUT for req pkt */
@@ -298,7 +299,7 @@ static inline u8 ezusb_reply_inc(u8 count)
 
 static void ezusb_request_context_put(struct request_context *ctx)
 {
-	if (!atomic_dec_and_test(&ctx->refcount))
+	if (!refcount_dec_and_test(&ctx->refcount))
 		return;
 
 	WARN_ON(!ctx->done.done);
@@ -328,7 +329,7 @@ static void ezusb_request_timerfn(u_long _ctx)
 	} else {
 		ctx->state = EZUSB_CTX_RESP_TIMEOUT;
 		dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
-		atomic_inc(&ctx->refcount);
+		refcount_inc(&ctx->refcount);
 		ctx->killed = 1;
 		ezusb_ctx_complete(ctx);
 		ezusb_request_context_put(ctx);
@@ -361,7 +362,7 @@ static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv,
 	ctx->out_rid = out_rid;
 	ctx->in_rid = in_rid;
 
-	atomic_set(&ctx->refcount, 1);
+	refcount_set(&ctx->refcount, 1);
 	init_completion(&ctx->done);
 
 	setup_timer(&ctx->timer, ezusb_request_timerfn, (u_long)ctx);
@@ -470,7 +471,7 @@ static void ezusb_req_queue_run(struct ezusb_priv *upriv)
 	list_move_tail(&ctx->list, &upriv->req_active);
 
 	if (ctx->state == EZUSB_CTX_QUEUED) {
-		atomic_inc(&ctx->refcount);
+		refcount_inc(&ctx->refcount);
 		result = usb_submit_urb(ctx->outurb, GFP_ATOMIC);
 		if (result) {
 			ctx->state = EZUSB_CTX_REQSUBMIT_FAIL;
@@ -508,7 +509,7 @@ static void ezusb_req_enqueue_run(struct ezusb_priv *upriv,
 		spin_unlock_irqrestore(&upriv->req_lock, flags);
 		goto done;
 	}
-	atomic_inc(&ctx->refcount);
+	refcount_inc(&ctx->refcount);
 	list_add_tail(&ctx->list, &upriv->req_pending);
 	spin_unlock_irqrestore(&upriv->req_lock, flags);
 
@@ -1465,7 +1466,7 @@ static inline void ezusb_delete(struct ezusb_priv *upriv)
 		int err;
 
 		ctx = list_entry(item, struct request_context, list);
-		atomic_inc(&ctx->refcount);
+		refcount_inc(&ctx->refcount);
 
 		ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
 		err = usb_unlink_urb(ctx->outurb);
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 93bdb34..d65d06f 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -40,7 +40,7 @@
 #include <linux/cpu_rmap.h>
 #include <linux/crash_dump.h>
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include <linux/timecounter.h>
 
@@ -738,7 +738,7 @@ struct mlx4_cq {
 	int			cqn;
 	unsigned		vector;
 
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 	struct {
 		struct list_head list;
@@ -754,7 +754,7 @@ struct mlx4_qp {
 
 	int			qpn;
 
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 };
 
@@ -766,7 +766,7 @@ struct mlx4_srq {
 	int			max_gs;
 	int			wqe_shift;
 
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 };
 
diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h
index 7c3c0d3..8a783ee 100644
--- a/include/linux/mlx5/cq.h
+++ b/include/linux/mlx5/cq.h
@@ -35,14 +35,14 @@
 
 #include <rdma/ib_verbs.h>
 #include <linux/mlx5/driver.h>
-
+#include <linux/refcount.h>
 
 struct mlx5_core_cq {
 	u32			cqn;
 	int			cqe_sz;
 	__be32		       *set_ci_db;
 	__be32		       *arm_db;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 	unsigned		vector;
 	unsigned int		irqn;
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index f44cbd3..c86da17 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -326,7 +326,6 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
 static int nfnl_acct_try_del(struct nf_acct *cur)
 {
 	int ret = 0;
-	unsigned int refcount;
 
 	/* We want to avoid races with nfnl_acct_put. So only when the current
 	 * refcnt is 1, we decrease it to 0.
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 17/18] drivers: misc drivers convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (15 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 16/18] drivers: net " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 18/18] drivers: infiniband " Elena Reshetova
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/block/xen-blkback/common.h             |  7 +--
 drivers/block/xen-blkback/xenbus.c             |  2 +-
 drivers/char/mspec.c                           |  9 ++--
 drivers/connector/cn_queue.c                   |  4 +-
 drivers/connector/connector.c                  |  2 +-
 drivers/firewire/core-topology.c               |  2 +-
 drivers/firewire/core.h                        |  8 ++--
 drivers/gpu/drm/amd/amdkfd/kfd_process.c       |  4 +-
 drivers/gpu/drm/i915/i915_gem_object.h         |  2 +-
 drivers/md/bcache/alloc.c                      |  2 +-
 drivers/md/bcache/bcache.h                     |  9 ++--
 drivers/md/bcache/btree.c                      |  8 ++--
 drivers/md/bcache/super.c                      |  6 +--
 drivers/md/bcache/writeback.h                  |  2 +-
 drivers/md/dm-cache-metadata.c                 |  9 ++--
 drivers/md/dm-core.h                           |  3 +-
 drivers/md/dm-table.c                          |  6 +--
 drivers/md/dm.c                                | 19 ++++----
 drivers/md/dm.h                                |  3 +-
 drivers/md/md.c                                |  6 +--
 drivers/md/md.h                                |  3 +-
 drivers/md/raid5-cache.c                       |  8 ++--
 drivers/md/raid5.c                             | 66 +++++++++++++-------------
 drivers/md/raid5.h                             |  3 +-
 drivers/media/pci/cx88/cx88-cards.c            |  2 +-
 drivers/media/pci/cx88/cx88-core.c             |  4 +-
 drivers/media/pci/cx88/cx88.h                  |  3 +-
 drivers/media/usb/s2255/s2255drv.c             | 21 ++++----
 drivers/media/usb/uvc/uvc_ctrl.c               |  7 +--
 drivers/media/usb/uvc/uvc_driver.c             | 12 ++---
 drivers/media/usb/uvc/uvcvideo.h               |  5 +-
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 11 +++--
 drivers/media/v4l2-core/videobuf2-dma-sg.c     | 11 +++--
 drivers/media/v4l2-core/videobuf2-memops.c     |  6 +--
 drivers/media/v4l2-core/videobuf2-vmalloc.c    | 11 +++--
 drivers/pci/host/pci-hyperv.c                  |  7 +--
 drivers/s390/char/vmur.c                       |  8 ++--
 drivers/s390/char/vmur.h                       |  4 +-
 drivers/s390/net/lcs.c                         | 10 ++--
 drivers/s390/net/lcs.h                         |  3 +-
 drivers/s390/net/qeth_core.h                   |  3 +-
 drivers/s390/net/qeth_core_main.c              | 10 ++--
 drivers/scsi/libfc/fc_exch.c                   | 10 ++--
 drivers/scsi/libfc/fc_fcp.c                    |  6 +--
 drivers/scsi/libiscsi.c                        |  8 ++--
 drivers/scsi/qedi/qedi_iscsi.c                 |  2 +-
 drivers/staging/vme/devices/vme_user.c         | 10 ++--
 drivers/target/target_core_iblock.c            | 12 ++---
 drivers/target/target_core_iblock.h            |  3 +-
 drivers/tty/serial/dz.c                        | 31 +++++-------
 drivers/tty/serial/sb1250-duart.c              | 18 +++----
 drivers/usb/gadget/function/f_fs.c             |  8 ++--
 drivers/usb/gadget/function/u_fs.h             |  3 +-
 drivers/usb/gadget/legacy/inode.c              | 17 +++----
 drivers/xen/gntdev.c                           | 11 +++--
 include/linux/connector.h                      |  4 +-
 include/media/videobuf2-memops.h               |  3 +-
 include/scsi/libfc.h                           |  5 +-
 include/scsi/libiscsi.h                        |  3 +-
 include/trace/events/bcache.h                  |  2 +-
 60 files changed, 252 insertions(+), 235 deletions(-)

diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index dea61f6..2ccfd62 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -35,6 +35,7 @@
 #include <linux/wait.h>
 #include <linux/io.h>
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 #include <asm/setup.h>
 #include <asm/pgalloc.h>
 #include <asm/hypervisor.h>
@@ -333,7 +334,7 @@ struct xen_blkif {
 	struct xen_vbd		vbd;
 	/* Back pointer to the backend_info. */
 	struct backend_info	*be;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 	/* for barrier (drain) requests */
 	struct completion	drain_complete;
 	atomic_t		drain;
@@ -386,10 +387,10 @@ struct pending_req {
 			 (_v)->bdev->bd_part->nr_sects : \
 			  get_capacity((_v)->bdev->bd_disk))
 
-#define xen_blkif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define xen_blkif_get(_b) (refcount_inc(&(_b)->refcnt))
 #define xen_blkif_put(_b)				\
 	do {						\
-		if (atomic_dec_and_test(&(_b)->refcnt))	\
+		if (refcount_dec_and_test(&(_b)->refcnt))	\
 			schedule_work(&(_b)->free_work);\
 	} while (0)
 
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 415e79b..4b22e47 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -176,7 +176,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
 		return ERR_PTR(-ENOMEM);
 
 	blkif->domid = domid;
-	atomic_set(&blkif->refcnt, 1);
+	refcount_set(&blkif->refcnt, 1);
 	init_completion(&blkif->drain_complete);
 	INIT_WORK(&blkif->free_work, xen_blkif_deferred_free);
 
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index a697ca0..6c164cc 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -43,6 +43,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/numa.h>
+#include <linux/refcount.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <linux/atomic.h>
@@ -89,7 +90,7 @@ static int is_sn2;
  * protect in fork case where multiple tasks share the vma_data.
  */
 struct vma_data {
-	atomic_t refcnt;	/* Number of vmas sharing the data. */
+	refcount_t refcnt;	/* Number of vmas sharing the data. */
 	spinlock_t lock;	/* Serialize access to this structure. */
 	int count;		/* Number of pages allocated. */
 	enum mspec_page_type type; /* Type of pages allocated. */
@@ -144,7 +145,7 @@ mspec_open(struct vm_area_struct *vma)
 	struct vma_data *vdata;
 
 	vdata = vma->vm_private_data;
-	atomic_inc(&vdata->refcnt);
+	refcount_inc(&vdata->refcnt);
 }
 
 /*
@@ -162,7 +163,7 @@ mspec_close(struct vm_area_struct *vma)
 
 	vdata = vma->vm_private_data;
 
-	if (!atomic_dec_and_test(&vdata->refcnt))
+	if (!refcount_dec_and_test(&vdata->refcnt))
 		return;
 
 	last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT;
@@ -274,7 +275,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma,
 	vdata->vm_end = vma->vm_end;
 	vdata->type = type;
 	spin_lock_init(&vdata->lock);
-	atomic_set(&vdata->refcnt, 1);
+	refcount_set(&vdata->refcnt, 1);
 	vma->vm_private_data = vdata;
 
 	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index 1f8bf05..9c54fdf 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -45,7 +45,7 @@ cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name,
 		return NULL;
 	}
 
-	atomic_set(&cbq->refcnt, 1);
+	refcount_set(&cbq->refcnt, 1);
 
 	atomic_inc(&dev->refcnt);
 	cbq->pdev = dev;
@@ -58,7 +58,7 @@ cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name,
 
 void cn_queue_release_callback(struct cn_callback_entry *cbq)
 {
-	if (!atomic_dec_and_test(&cbq->refcnt))
+	if (!refcount_dec_and_test(&cbq->refcnt))
 		return;
 
 	atomic_dec(&cbq->pdev->refcnt);
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 25693b0..8615594b 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -157,7 +157,7 @@ static int cn_call_callback(struct sk_buff *skb)
 	spin_lock_bh(&dev->cbdev->queue_lock);
 	list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) {
 		if (cn_cb_equal(&i->id.id, &msg->id)) {
-			atomic_inc(&i->refcnt);
+			refcount_inc(&i->refcnt);
 			cbq = i;
 			break;
 		}
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index 0de8350..939d259 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -124,7 +124,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
 	node->initiated_reset = SELF_ID_PHY_INITIATOR(sid);
 	node->port_count = port_count;
 
-	atomic_set(&node->ref_count, 1);
+	refcount_set(&node->ref_count, 1);
 	INIT_LIST_HEAD(&node->link);
 
 	return node;
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index e1480ff6..c07962e 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -12,7 +12,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct device;
 struct fw_card;
@@ -184,7 +184,7 @@ struct fw_node {
 			 * local node to this node. */
 	u8 max_depth:4;	/* Maximum depth to any leaf node */
 	u8 max_hops:4;	/* Max hops in this sub tree */
-	atomic_t ref_count;
+	refcount_t ref_count;
 
 	/* For serializing node topology into a list. */
 	struct list_head link;
@@ -197,14 +197,14 @@ struct fw_node {
 
 static inline struct fw_node *fw_node_get(struct fw_node *node)
 {
-	atomic_inc(&node->ref_count);
+	refcount_inc(&node->ref_count);
 
 	return node;
 }
 
 static inline void fw_node_put(struct fw_node *node)
 {
-	if (atomic_dec_and_test(&node->ref_count))
+	if (refcount_dec_and_test(&node->ref_count))
 		kfree(node);
 }
 
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index ef7c8de..04115fc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -204,7 +204,7 @@ static void kfd_process_destroy_delayed(struct rcu_head *rcu)
 	BUG_ON(!kfd_process_wq);
 
 	p = container_of(rcu, struct kfd_process, rcu);
-	BUG_ON(atomic_read(&p->mm->mm_count) <= 0);
+	BUG_ON(refcount_read(&p->mm->mm_count) == 0);
 
 	mmdrop(p->mm);
 
@@ -262,7 +262,7 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
 	 * and because the mmu_notifier_unregister function also drop
 	 * mm_count we need to take an extra count here.
 	 */
-	atomic_inc(&p->mm->mm_count);
+	refcount_inc(&p->mm->mm_count);
 	mmu_notifier_unregister_no_release(&p->mmu_notifier, p->mm);
 	mmu_notifier_call_srcu(&p->rcu, &kfd_process_destroy_delayed);
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
index 6a368de..ecfefb9 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -256,7 +256,7 @@ extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *);
 static inline bool
 i915_gem_object_is_dead(const struct drm_i915_gem_object *obj)
 {
-	return atomic_read(&obj->base.refcount.refcount) == 0;
+	return kref_read(&obj->base.refcount) == 0;
 }
 
 static inline bool
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index ca4abe1..705933a 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -353,7 +353,7 @@ static int bch_allocator_thread(void *arg)
 		 * Now, we write their new gens to disk so we can start writing
 		 * new stuff to them:
 		 */
-		allocator_wait(ca, !atomic_read(&ca->set->prio_blocked));
+		allocator_wait(ca, !refcount_read(&ca->set->prio_blocked));
 		if (CACHE_SYNC(&ca->set->sb)) {
 			/*
 			 * This could deadlock if an allocation with a btree
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index c3ea03c..031c03e 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -184,6 +184,7 @@
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
 #include <linux/rwsem.h>
+#include <linux/refcount.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
@@ -299,7 +300,7 @@ struct cached_dev {
 	struct semaphore	sb_write_mutex;
 
 	/* Refcount on the cache set. Always nonzero when we're caching. */
-	atomic_t		count;
+	refcount_t		count;
 	struct work_struct	detach;
 
 	/*
@@ -557,7 +558,7 @@ struct cache_set {
 	 * This is a refcount that blocks prio_write() until the new keys are
 	 * written.
 	 */
-	atomic_t		prio_blocked;
+	refcount_t		prio_blocked;
 	wait_queue_head_t	bucket_wait;
 
 	/*
@@ -805,13 +806,13 @@ do {									\
 
 static inline void cached_dev_put(struct cached_dev *dc)
 {
-	if (atomic_dec_and_test(&dc->count))
+	if (refcount_dec_and_test(&dc->count))
 		schedule_work(&dc->detach);
 }
 
 static inline bool cached_dev_get(struct cached_dev *dc)
 {
-	if (!atomic_inc_not_zero(&dc->count))
+	if (!refcount_inc_not_zero(&dc->count))
 		return false;
 
 	/* Paired with the mb in cached_dev_attach */
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index a43eedd..7ee76f3 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -324,8 +324,8 @@ static void bch_btree_node_read(struct btree *b)
 static void btree_complete_write(struct btree *b, struct btree_write *w)
 {
 	if (w->prio_blocked &&
-	    !atomic_sub_return(w->prio_blocked, &b->c->prio_blocked))
-		wake_up_allocators(b->c);
+		refcount_sub_and_test(w->prio_blocked, &b->c->prio_blocked))
+				wake_up_allocators(b->c);
 
 	if (w->journal) {
 		atomic_dec_bug(w->journal);
@@ -1126,7 +1126,7 @@ static void make_btree_freeing_key(struct btree *b, struct bkey *k)
 
 	mutex_lock(&b->c->bucket_lock);
 
-	atomic_inc(&b->c->prio_blocked);
+	refcount_inc(&b->c->prio_blocked);
 
 	bkey_copy(k, &b->key);
 	bkey_copy_key(k, &ZERO_KEY);
@@ -1446,7 +1446,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
 
 	while ((k = bch_keylist_pop(&keylist)))
 		if (!bkey_cmp(k, &ZERO_KEY))
-			atomic_dec(&b->c->prio_blocked);
+			refcount_dec(&b->c->prio_blocked);
 
 	for (i = 0; i < nodes; i++)
 		if (!IS_ERR_OR_NULL(new_nodes[i])) {
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 3a19cbc..e04621f 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -891,7 +891,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
 	closure_init_stack(&cl);
 
 	BUG_ON(!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags));
-	BUG_ON(atomic_read(&dc->count));
+	BUG_ON(refcount_read(&dc->count));
 
 	mutex_lock(&bch_register_lock);
 
@@ -1018,7 +1018,7 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
 	 * dc->c must be set before dc->count != 0 - paired with the mb in
 	 * cached_dev_get()
 	 */
-	atomic_set(&dc->count, 1);
+	refcount_set(&dc->count, 1);
 
 	/* Block writeback thread, but spawn it */
 	down_write(&dc->writeback_lock);
@@ -1030,7 +1030,7 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
 	if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
 		bch_sectors_dirty_init(dc);
 		atomic_set(&dc->has_dirty, 1);
-		atomic_inc(&dc->count);
+		refcount_inc(&dc->count);
 		bch_writeback_queue(dc);
 	}
 
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h
index 629bd1a..5bac1b0 100644
--- a/drivers/md/bcache/writeback.h
+++ b/drivers/md/bcache/writeback.h
@@ -70,7 +70,7 @@ static inline void bch_writeback_add(struct cached_dev *dc)
 {
 	if (!atomic_read(&dc->has_dirty) &&
 	    !atomic_xchg(&dc->has_dirty, 1)) {
-		atomic_inc(&dc->count);
+		refcount_inc(&dc->count);
 
 		if (BDEV_STATE(&dc->sb) != BDEV_STATE_DIRTY) {
 			SET_BDEV_STATE(&dc->sb, BDEV_STATE_DIRTY);
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 624fe43..d20cc79 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -13,6 +13,7 @@
 #include "persistent-data/dm-transaction-manager.h"
 
 #include <linux/device-mapper.h>
+#include <linux/refcount.h>
 
 /*----------------------------------------------------------------*/
 
@@ -96,7 +97,7 @@ struct cache_disk_superblock {
 } __packed;
 
 struct dm_cache_metadata {
-	atomic_t ref_count;
+	refcount_t ref_count;
 	struct list_head list;
 
 	struct block_device *bdev;
@@ -709,7 +710,7 @@ static struct dm_cache_metadata *metadata_open(struct block_device *bdev,
 		return ERR_PTR(-ENOMEM);
 	}
 
-	atomic_set(&cmd->ref_count, 1);
+	refcount_set(&cmd->ref_count, 1);
 	init_rwsem(&cmd->root_lock);
 	cmd->bdev = bdev;
 	cmd->data_block_size = data_block_size;
@@ -747,7 +748,7 @@ static struct dm_cache_metadata *lookup(struct block_device *bdev)
 
 	list_for_each_entry(cmd, &table, list)
 		if (cmd->bdev == bdev) {
-			atomic_inc(&cmd->ref_count);
+			refcount_inc(&cmd->ref_count);
 			return cmd;
 		}
 
@@ -815,7 +816,7 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
 
 void dm_cache_metadata_close(struct dm_cache_metadata *cmd)
 {
-	if (atomic_dec_and_test(&cmd->ref_count)) {
+	if (refcount_dec_and_test(&cmd->ref_count)) {
 		mutex_lock(&table_lock);
 		list_del(&cmd->list);
 		mutex_unlock(&table_lock);
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index 40ceba1..3fa0ac9 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -12,6 +12,7 @@
 #include <linux/kthread.h>
 #include <linux/ktime.h>
 #include <linux/blk-mq.h>
+#include <linux/refcount.h>
 
 #include <trace/events/block.h>
 
@@ -52,7 +53,7 @@ struct mapped_device {
 	struct mutex type_lock;
 
 	atomic_t holders;
-	atomic_t open_count;
+	refcount_t open_count;
 
 	struct dm_target *immutable_target;
 	struct target_type *immutable_target_type;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 0a427de..d2ba05a 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -416,7 +416,7 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 			return r;
 		}
 
-		atomic_set(&dd->count, 0);
+		refcount_set(&dd->count, 0);
 		list_add(&dd->list, &t->devices);
 
 	} else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) {
@@ -424,7 +424,7 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 		if (r)
 			return r;
 	}
-	atomic_inc(&dd->count);
+	refcount_inc(&dd->count);
 
 	*result = dd->dm_dev;
 	return 0;
@@ -478,7 +478,7 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d)
 		       dm_device_name(ti->table->md), d->name);
 		return;
 	}
-	if (atomic_dec_and_test(&dd->count)) {
+	if (refcount_dec_and_test(&dd->count)) {
 		dm_put_table_device(ti->table->md, d);
 		list_del(&dd->list);
 		kfree(dd);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 3086da5..6c891e4 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -21,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/pr.h>
+#include <linux/refcount.h>
 
 #define DM_MSG_PREFIX "core"
 
@@ -97,7 +98,7 @@ struct dm_md_mempools {
 
 struct table_device {
 	struct list_head list;
-	atomic_t count;
+	refcount_t count;
 	struct dm_dev dm_dev;
 };
 
@@ -313,7 +314,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode)
 	}
 
 	dm_get(md);
-	atomic_inc(&md->open_count);
+	refcount_inc(&md->open_count);
 out:
 	spin_unlock(&_minor_lock);
 
@@ -330,7 +331,7 @@ static void dm_blk_close(struct gendisk *disk, fmode_t mode)
 	if (WARN_ON(!md))
 		goto out;
 
-	if (atomic_dec_and_test(&md->open_count) &&
+	if (refcount_dec_and_test(&md->open_count) &&
 	    (test_bit(DMF_DEFERRED_REMOVE, &md->flags)))
 		queue_work(deferred_remove_workqueue, &deferred_remove_work);
 
@@ -341,7 +342,7 @@ static void dm_blk_close(struct gendisk *disk, fmode_t mode)
 
 int dm_open_count(struct mapped_device *md)
 {
-	return atomic_read(&md->open_count);
+	return refcount_read(&md->open_count);
 }
 
 /*
@@ -678,10 +679,10 @@ int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
 
 		format_dev_t(td->dm_dev.name, dev);
 
-		atomic_set(&td->count, 0);
+		refcount_set(&td->count, 0);
 		list_add(&td->list, &md->table_devices);
 	}
-	atomic_inc(&td->count);
+	refcount_inc(&td->count);
 	mutex_unlock(&md->table_devices_lock);
 
 	*result = &td->dm_dev;
@@ -694,7 +695,7 @@ void dm_put_table_device(struct mapped_device *md, struct dm_dev *d)
 	struct table_device *td = container_of(d, struct table_device, dm_dev);
 
 	mutex_lock(&md->table_devices_lock);
-	if (atomic_dec_and_test(&td->count)) {
+	if (refcount_dec_and_test(&td->count)) {
 		close_table_device(td, md);
 		list_del(&td->list);
 		kfree(td);
@@ -711,7 +712,7 @@ static void free_table_devices(struct list_head *devices)
 		struct table_device *td = list_entry(tmp, struct table_device, list);
 
 		DMWARN("dm_destroy: %s still exists with %d references",
-		       td->dm_dev.name, atomic_read(&td->count));
+		       td->dm_dev.name, refcount_read(&td->count));
 		kfree(td);
 	}
 }
@@ -1483,7 +1484,7 @@ static struct mapped_device *alloc_dev(int minor)
 	mutex_init(&md->table_devices_lock);
 	spin_lock_init(&md->deferred_lock);
 	atomic_set(&md->holders, 1);
-	atomic_set(&md->open_count, 0);
+	refcount_set(&md->open_count, 0);
 	atomic_set(&md->event_nr, 0);
 	atomic_set(&md->uevent_seq, 0);
 	INIT_LIST_HEAD(&md->uevent_list);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index f0aad08..26e560a 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -19,6 +19,7 @@
 #include <linux/hdreg.h>
 #include <linux/completion.h>
 #include <linux/kobject.h>
+#include <linux/refcount.h>
 
 #include "dm-stats.h"
 
@@ -38,7 +39,7 @@
  */
 struct dm_dev_internal {
 	struct list_head list;
-	atomic_t count;
+	refcount_t count;
 	struct dm_dev *dm_dev;
 };
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 82821ee..6c9b9ff 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -459,7 +459,7 @@ EXPORT_SYMBOL(md_unplug);
 
 static inline struct mddev *mddev_get(struct mddev *mddev)
 {
-	atomic_inc(&mddev->active);
+	refcount_inc(&mddev->active);
 	return mddev;
 }
 
@@ -469,7 +469,7 @@ static void mddev_put(struct mddev *mddev)
 {
 	struct bio_set *bs = NULL;
 
-	if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock))
+	if (!refcount_dec_and_lock(&mddev->active, &all_mddevs_lock))
 		return;
 	if (!mddev->raid_disks && list_empty(&mddev->disks) &&
 	    mddev->ctime == 0 && !mddev->hold_active) {
@@ -505,7 +505,7 @@ void mddev_init(struct mddev *mddev)
 	INIT_LIST_HEAD(&mddev->all_mddevs);
 	setup_timer(&mddev->safemode_timer, md_safemode_timeout,
 		    (unsigned long) mddev);
-	atomic_set(&mddev->active, 1);
+	refcount_set(&mddev->active, 1);
 	atomic_set(&mddev->openers, 0);
 	atomic_set(&mddev->active_io, 0);
 	spin_lock_init(&mddev->lock);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index e38936d..0c1ec5f 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
@@ -359,7 +360,7 @@ struct mddev {
 	 */
 	struct mutex			open_mutex;
 	struct mutex			reconfig_mutex;
-	atomic_t			active;		/* general refcount */
+	refcount_t			active;		/* general refcount */
 	atomic_t			openers;	/* number of active opens */
 
 	int				changed;	/* True if we might need to
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index d7bfb6f..a647d4b 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -906,7 +906,7 @@ int r5l_write_stripe(struct r5l_log *log, struct stripe_head *sh)
 	 * don't delay.
 	 */
 	clear_bit(STRIPE_DELAYED, &sh->state);
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 
 	mutex_lock(&log->io_mutex);
 	/* meta + data */
@@ -1248,7 +1248,7 @@ static void r5c_flush_stripe(struct r5conf *conf, struct stripe_head *sh)
 	assert_spin_locked(&conf->device_lock);
 
 	list_del_init(&sh->lru);
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 
 	set_bit(STRIPE_HANDLE, &sh->state);
 	atomic_inc(&conf->active_stripes);
@@ -1343,7 +1343,7 @@ static void r5c_do_reclaim(struct r5conf *conf)
 			 */
 			if (!list_empty(&sh->lru) &&
 			    !test_bit(STRIPE_HANDLE, &sh->state) &&
-			    atomic_read(&sh->count) == 0) {
+			    refcount_read(&sh->count) == 0) {
 				r5c_flush_stripe(conf, sh);
 			}
 			if (count++ >= R5C_RECLAIM_STRIPE_GROUP)
@@ -2459,7 +2459,7 @@ r5c_cache_data(struct r5l_log *log, struct stripe_head *sh,
 	 * don't delay.
 	 */
 	clear_bit(STRIPE_DELAYED, &sh->state);
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 
 	mutex_lock(&log->io_mutex);
 	/* meta + data */
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 06d7279..f14fe3d 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -294,7 +294,7 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh,
 static void __release_stripe(struct r5conf *conf, struct stripe_head *sh,
 			     struct list_head *temp_inactive_list)
 {
-	if (atomic_dec_and_test(&sh->count))
+	if (refcount_dec_and_test(&sh->count))
 		do_release_stripe(conf, sh, temp_inactive_list);
 }
 
@@ -388,7 +388,7 @@ void raid5_release_stripe(struct stripe_head *sh)
 
 	/* Avoid release_list until the last reference.
 	 */
-	if (atomic_add_unless(&sh->count, -1, 1))
+	if (refcount_dec_not_one(&sh->count))
 		return;
 
 	if (unlikely(!conf->mddev->thread) ||
@@ -401,7 +401,7 @@ void raid5_release_stripe(struct stripe_head *sh)
 slow_path:
 	local_irq_save(flags);
 	/* we are ok here if STRIPE_ON_RELEASE_LIST is set or not */
-	if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) {
+	if (refcount_dec_and_lock(&sh->count, &conf->device_lock)) {
 		INIT_LIST_HEAD(&list);
 		hash = sh->hash_lock_index;
 		do_release_stripe(conf, sh, &list);
@@ -491,7 +491,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 	struct r5conf *conf = sh->raid_conf;
 	int i, seq;
 
-	BUG_ON(atomic_read(&sh->count) != 0);
+	BUG_ON(refcount_read(&sh->count) != 0);
 	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
 	BUG_ON(stripe_operations_active(sh));
 	BUG_ON(sh->batch_head);
@@ -668,11 +668,11 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
 					  &conf->cache_state);
 			} else {
 				init_stripe(sh, sector, previous);
-				atomic_inc(&sh->count);
+				refcount_inc(&sh->count);
 			}
-		} else if (!atomic_inc_not_zero(&sh->count)) {
+		} else if (!refcount_inc_not_zero(&sh->count)) {
 			spin_lock(&conf->device_lock);
-			if (!atomic_read(&sh->count)) {
+			if (!refcount_read(&sh->count)) {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
 				BUG_ON(list_empty(&sh->lru) &&
@@ -688,7 +688,7 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
 					sh->group = NULL;
 				}
 			}
-			atomic_inc(&sh->count);
+			refcount_inc(&sh->count);
 			spin_unlock(&conf->device_lock);
 		}
 	} while (sh == NULL);
@@ -752,9 +752,9 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
 	hash = stripe_hash_locks_hash(head_sector);
 	spin_lock_irq(conf->hash_locks + hash);
 	head = __find_stripe(conf, head_sector, conf->generation);
-	if (head && !atomic_inc_not_zero(&head->count)) {
+	if (head && !refcount_inc_not_zero(&head->count)) {
 		spin_lock(&conf->device_lock);
-		if (!atomic_read(&head->count)) {
+		if (!refcount_read(&head->count)) {
 			if (!test_bit(STRIPE_HANDLE, &head->state))
 				atomic_inc(&conf->active_stripes);
 			BUG_ON(list_empty(&head->lru) &&
@@ -770,7 +770,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
 				head->group = NULL;
 			}
 		}
-		atomic_inc(&head->count);
+		refcount_inc(&head->count);
 		spin_unlock(&conf->device_lock);
 	}
 	spin_unlock_irq(conf->hash_locks + hash);
@@ -833,7 +833,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
 		sh->batch_head->bm_seq = seq;
 	}
 
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 unlock_out:
 	unlock_two_stripes(head, sh);
 out:
@@ -999,9 +999,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			pr_debug("%s: for %llu schedule op %d on disc %d\n",
 				__func__, (unsigned long long)sh->sector,
 				bi->bi_opf, i);
-			atomic_inc(&sh->count);
+			refcount_inc(&sh->count);
 			if (sh != head_sh)
-				atomic_inc(&head_sh->count);
+				refcount_inc(&head_sh->count);
 			if (use_new_offset(conf, sh))
 				bi->bi_iter.bi_sector = (sh->sector
 						 + rdev->new_data_offset);
@@ -1050,9 +1050,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 				 "replacement disc %d\n",
 				__func__, (unsigned long long)sh->sector,
 				rbi->bi_opf, i);
-			atomic_inc(&sh->count);
+			refcount_inc(&sh->count);
 			if (sh != head_sh)
-				atomic_inc(&head_sh->count);
+				refcount_inc(&head_sh->count);
 			if (use_new_offset(conf, sh))
 				rbi->bi_iter.bi_sector = (sh->sector
 						  + rrdev->new_data_offset);
@@ -1228,7 +1228,7 @@ static void ops_run_biofill(struct stripe_head *sh)
 		}
 	}
 
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 	init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_biofill, sh, NULL);
 	async_trigger_callback(&submit);
 }
@@ -1306,7 +1306,7 @@ ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)
 		if (i != target)
 			xor_srcs[count++] = sh->dev[i].page;
 
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 
 	init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, NULL,
 			  ops_complete_compute, sh, to_addr_conv(sh, percpu, 0));
@@ -1394,7 +1394,7 @@ ops_run_compute6_1(struct stripe_head *sh, struct raid5_percpu *percpu)
 	BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
 	dest = tgt->page;
 
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 
 	if (target == qd_idx) {
 		count = set_syndrome_sources(blocks, sh, SYNDROME_SRC_ALL);
@@ -1469,7 +1469,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
 	pr_debug("%s: stripe: %llu faila: %d failb: %d\n",
 		 __func__, (unsigned long long)sh->sector, faila, failb);
 
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 
 	if (failb == syndrome_disks+1) {
 		/* Q disk is one of the missing disks */
@@ -1737,7 +1737,7 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
 			break;
 	}
 	if (i >= sh->disks) {
-		atomic_inc(&sh->count);
+		refcount_inc(&sh->count);
 		set_bit(R5_Discard, &sh->dev[pd_idx].flags);
 		ops_complete_reconstruct(sh);
 		return;
@@ -1778,7 +1778,7 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
 		flags = ASYNC_TX_ACK |
 			(prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
 
-		atomic_inc(&head_sh->count);
+		refcount_inc(&head_sh->count);
 		init_async_submit(&submit, flags, tx, ops_complete_reconstruct, head_sh,
 				  to_addr_conv(sh, percpu, j));
 	} else {
@@ -1820,7 +1820,7 @@ ops_run_reconstruct6(struct stripe_head *sh, struct raid5_percpu *percpu,
 			break;
 	}
 	if (i >= sh->disks) {
-		atomic_inc(&sh->count);
+		refcount_inc(&sh->count);
 		set_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
 		set_bit(R5_Discard, &sh->dev[sh->qd_idx].flags);
 		ops_complete_reconstruct(sh);
@@ -1844,7 +1844,7 @@ ops_run_reconstruct6(struct stripe_head *sh, struct raid5_percpu *percpu,
 				 struct stripe_head, batch_list) == head_sh;
 
 	if (last_stripe) {
-		atomic_inc(&head_sh->count);
+		refcount_inc(&head_sh->count);
 		init_async_submit(&submit, txflags, tx, ops_complete_reconstruct,
 				  head_sh, to_addr_conv(sh, percpu, j));
 	} else
@@ -1901,7 +1901,7 @@ static void ops_run_check_p(struct stripe_head *sh, struct raid5_percpu *percpu)
 	tx = async_xor_val(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
 			   &sh->ops.zero_sum_result, &submit);
 
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 	init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_check, sh, NULL);
 	tx = async_trigger_callback(&submit);
 }
@@ -1920,7 +1920,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu
 	if (!checkp)
 		srcs[count] = NULL;
 
-	atomic_inc(&sh->count);
+	refcount_inc(&sh->count);
 	init_async_submit(&submit, ASYNC_TX_ACK, NULL, ops_complete_check,
 			  sh, to_addr_conv(sh, percpu, 0));
 	async_syndrome_val(srcs, 0, count+2, STRIPE_SIZE,
@@ -2010,7 +2010,7 @@ static struct stripe_head *alloc_stripe(struct kmem_cache *sc, gfp_t gfp,
 		INIT_LIST_HEAD(&sh->lru);
 		INIT_LIST_HEAD(&sh->r5c);
 		INIT_LIST_HEAD(&sh->log_list);
-		atomic_set(&sh->count, 1);
+		refcount_set(&sh->count, 1);
 		sh->log_start = MaxSector;
 		for (i = 0; i < disks; i++) {
 			struct r5dev *dev = &sh->dev[i];
@@ -2307,7 +2307,7 @@ static int drop_one_stripe(struct r5conf *conf)
 	spin_unlock_irq(conf->hash_locks + hash);
 	if (!sh)
 		return 0;
-	BUG_ON(atomic_read(&sh->count));
+	BUG_ON(refcount_read(&sh->count));
 	shrink_buffers(sh);
 	kmem_cache_free(conf->slab_cache, sh);
 	atomic_dec(&conf->active_stripes);
@@ -2339,7 +2339,7 @@ static void raid5_end_read_request(struct bio * bi)
 			break;
 
 	pr_debug("end_read_request %llu/%d, count: %d, error %d.\n",
-		(unsigned long long)sh->sector, i, atomic_read(&sh->count),
+		(unsigned long long)sh->sector, i, refcount_read(&sh->count),
 		bi->bi_error);
 	if (i == disks) {
 		bio_reset(bi);
@@ -2469,7 +2469,7 @@ static void raid5_end_write_request(struct bio *bi)
 		}
 	}
 	pr_debug("end_write_request %llu/%d, count %d, error: %d.\n",
-		(unsigned long long)sh->sector, i, atomic_read(&sh->count),
+		(unsigned long long)sh->sector, i, refcount_read(&sh->count),
 		bi->bi_error);
 	if (i == disks) {
 		bio_reset(bi);
@@ -4417,7 +4417,7 @@ static void handle_stripe(struct stripe_head *sh)
 	pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
 		"pd_idx=%d, qd_idx=%d\n, check:%d, reconstruct:%d\n",
 	       (unsigned long long)sh->sector, sh->state,
-	       atomic_read(&sh->count), sh->pd_idx, sh->qd_idx,
+	       refcount_read(&sh->count), sh->pd_idx, sh->qd_idx,
 	       sh->check_state, sh->reconstruct_state);
 
 	analyse_stripe(sh, &s);
@@ -4796,7 +4796,7 @@ static void activate_bit_delay(struct r5conf *conf,
 		struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
 		int hash;
 		list_del_init(&sh->lru);
-		atomic_inc(&sh->count);
+		refcount_inc(&sh->count);
 		hash = sh->hash_lock_index;
 		__release_stripe(conf, sh, &temp_inactive_list[hash]);
 	}
@@ -5105,7 +5105,7 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf, int group)
 		sh->group = NULL;
 	}
 	list_del_init(&sh->lru);
-	BUG_ON(atomic_inc_return(&sh->count) != 1);
+	BUG_ON(refcount_inc_not_zero(&sh->count));
 	return sh;
 }
 
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index ed8e136..178f842 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -3,6 +3,7 @@
 
 #include <linux/raid/xor.h>
 #include <linux/dmaengine.h>
+#include <linux/refcount.h>
 
 /*
  *
@@ -207,7 +208,7 @@ struct stripe_head {
 	short			ddf_layout;/* use DDF ordering to calculate Q */
 	short			hash_lock_index;
 	unsigned long		state;		/* state flags */
-	atomic_t		count;	      /* nr of active thread/requests */
+	refcount_t		count;	      /* nr of active thread/requests */
 	int			bm_seq;	/* sequence number for bitmap flushes */
 	int			disks;		/* disks in stripe */
 	int			overwrite_disks; /* total overwrite disks in stripe,
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index cdfbde2..7537dc4 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -3670,7 +3670,7 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
 	if (!core)
 		return NULL;
 
-	atomic_inc(&core->refcount);
+	refcount_inc(&core->refcount);
 	core->pci_bus  = pci->bus->number;
 	core->pci_slot = PCI_SLOT(pci->devfn);
 	core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT |
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index 973a9cd4..8bfa5b7 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -1052,7 +1052,7 @@ struct cx88_core *cx88_core_get(struct pci_dev *pci)
 			mutex_unlock(&devlist);
 			return NULL;
 		}
-		atomic_inc(&core->refcount);
+		refcount_inc(&core->refcount);
 		mutex_unlock(&devlist);
 		return core;
 	}
@@ -1073,7 +1073,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
 	release_mem_region(pci_resource_start(pci, 0),
 			   pci_resource_len(pci, 0));
 
-	if (!atomic_dec_and_test(&core->refcount))
+	if (!refcount_dec_and_test(&core->refcount))
 		return;
 
 	mutex_lock(&devlist);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 115414c..16c1313 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -24,6 +24,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/videodev2.h>
 #include <linux/kdev_t.h>
+#include <linux/refcount.h>
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-fh.h>
@@ -339,7 +340,7 @@ struct cx8802_dev;
 
 struct cx88_core {
 	struct list_head           devlist;
-	atomic_t                   refcount;
+	refcount_t                   refcount;
 
 	/* board name */
 	int                        nr;
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index f7bb78c..d682fb4b 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -40,6 +40,7 @@
 #include <linux/firmware.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/mm.h>
@@ -260,7 +261,7 @@ struct s2255_vc {
 struct s2255_dev {
 	struct s2255_vc         vc[MAX_CHANNELS];
 	struct v4l2_device      v4l2_dev;
-	atomic_t                num_channels;
+	refcount_t                num_channels;
 	int			frames;
 	struct mutex		lock;	/* channels[].vdev.lock */
 	struct mutex		cmdlock; /* protects cmdbuf */
@@ -1585,11 +1586,11 @@ static void s2255_video_device_release(struct video_device *vdev)
 		container_of(vdev, struct s2255_vc, vdev);
 
 	dprintk(dev, 4, "%s, chnls: %d\n", __func__,
-		atomic_read(&dev->num_channels));
+		refcount_read(&dev->num_channels));
 
 	v4l2_ctrl_handler_free(&vc->hdl);
 
-	if (atomic_dec_and_test(&dev->num_channels))
+	if (refcount_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
 	return;
 }
@@ -1692,7 +1693,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
 				"failed to register video device!\n");
 			break;
 		}
-		atomic_inc(&dev->num_channels);
+		refcount_inc(&dev->num_channels);
 		v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
 			  video_device_node_name(&vc->vdev));
 
@@ -1700,11 +1701,11 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
 	pr_info("Sensoray 2255 V4L driver Revision: %s\n",
 		S2255_VERSION);
 	/* if no channels registered, return error and probe will fail*/
-	if (atomic_read(&dev->num_channels) == 0) {
+	if (refcount_read(&dev->num_channels) == 0) {
 		v4l2_device_unregister(&dev->v4l2_dev);
 		return ret;
 	}
-	if (atomic_read(&dev->num_channels) != MAX_CHANNELS)
+	if (refcount_read(&dev->num_channels) != MAX_CHANNELS)
 		pr_warn("s2255: Not all channels available.\n");
 	return 0;
 }
@@ -2252,7 +2253,7 @@ static int s2255_probe(struct usb_interface *interface,
 		goto errorFWDATA1;
 	}
 
-	atomic_set(&dev->num_channels, 0);
+	refcount_set(&dev->num_channels, 0);
 	dev->pid = id->idProduct;
 	dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
 	if (!dev->fw_data)
@@ -2372,12 +2373,12 @@ static void s2255_disconnect(struct usb_interface *interface)
 {
 	struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface));
 	int i;
-	int channels = atomic_read(&dev->num_channels);
+	int channels = refcount_read(&dev->num_channels);
 	mutex_lock(&dev->lock);
 	v4l2_device_disconnect(&dev->v4l2_dev);
 	mutex_unlock(&dev->lock);
 	/*see comments in the uvc_driver.c usb disconnect function */
-	atomic_inc(&dev->num_channels);
+	refcount_inc(&dev->num_channels);
 	/* unregister each video device. */
 	for (i = 0; i < channels; i++)
 		video_unregister_device(&dev->vc[i].vdev);
@@ -2390,7 +2391,7 @@ static void s2255_disconnect(struct usb_interface *interface)
 		dev->vc[i].vidstatus_ready = 1;
 		wake_up(&dev->vc[i].wait_vidstatus);
 	}
-	if (atomic_dec_and_test(&dev->num_channels))
+	if (refcount_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
 	dev_info(&interface->dev, "%s\n", __func__);
 }
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index c2ee6e3..b96d8c1 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -2012,9 +2012,10 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
 		}
 	}
 
+	refcount_inc(&dev->nmappings);
 	/* Prevent excess memory consumption */
-	if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) {
-		atomic_dec(&dev->nmappings);
+	if (refcount_read(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) {
+		refcount_dec(&dev->nmappings);
 		uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', maximum "
 			"mappings count (%u) exceeded.\n", mapping->name,
 			UVC_MAX_CONTROL_MAPPINGS);
@@ -2024,7 +2025,7 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
 
 	ret = __uvc_ctrl_add_mapping(dev, ctrl, mapping);
 	if (ret < 0)
-		atomic_dec(&dev->nmappings);
+		refcount_dec(&dev->nmappings);
 
 done:
 	mutex_unlock(&chain->ctrl_mutex);
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 04bf350..9d6258e 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1842,7 +1842,7 @@ static void uvc_release(struct video_device *vdev)
 	/* Decrement the registered streams count and delete the device when it
 	 * reaches zero.
 	 */
-	if (atomic_dec_and_test(&dev->nstreams))
+	if (refcount_dec_and_test(&dev->nstreams))
 		uvc_delete(dev);
 }
 
@@ -1858,7 +1858,7 @@ static void uvc_unregister_video(struct uvc_device *dev)
 	 * that, increment the stream count before iterating over the streams
 	 * and decrement it when done.
 	 */
-	atomic_inc(&dev->nstreams);
+	refcount_inc(&dev->nstreams);
 
 	list_for_each_entry(stream, &dev->streams, list) {
 		if (!video_is_registered(&stream->vdev))
@@ -1872,7 +1872,7 @@ static void uvc_unregister_video(struct uvc_device *dev)
 	/* Decrement the stream count and call uvc_delete explicitly if there
 	 * are no stream left.
 	 */
-	if (atomic_dec_and_test(&dev->nstreams))
+	if (refcount_dec_and_test(&dev->nstreams))
 		uvc_delete(dev);
 }
 
@@ -1931,7 +1931,7 @@ static int uvc_register_video(struct uvc_device *dev,
 	else
 		stream->chain->caps |= V4L2_CAP_VIDEO_OUTPUT;
 
-	atomic_inc(&dev->nstreams);
+	refcount_inc(&dev->nstreams);
 	return 0;
 }
 
@@ -2015,8 +2015,8 @@ static int uvc_probe(struct usb_interface *intf,
 	INIT_LIST_HEAD(&dev->entities);
 	INIT_LIST_HEAD(&dev->chains);
 	INIT_LIST_HEAD(&dev->streams);
-	atomic_set(&dev->nstreams, 0);
-	atomic_set(&dev->nmappings, 0);
+	refcount_set(&dev->nstreams, 0);
+	refcount_set(&dev->nmappings, 0);
 	mutex_init(&dev->lock);
 
 	dev->udev = usb_get_dev(udev);
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 3d6cc62..289321e 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -7,6 +7,7 @@
 
 #include <linux/kernel.h>
 #include <linux/poll.h>
+#include <linux/refcount.h>
 #include <linux/usb.h>
 #include <linux/usb/video.h>
 #include <linux/uvcvideo.h>
@@ -551,7 +552,7 @@ struct uvc_device {
 
 	struct mutex lock;		/* Protects users */
 	unsigned int users;
-	atomic_t nmappings;
+	refcount_t nmappings;
 
 	/* Video control interface */
 #ifdef CONFIG_MEDIA_CONTROLLER
@@ -566,7 +567,7 @@ struct uvc_device {
 
 	/* Video Streaming interfaces */
 	struct list_head streams;
-	atomic_t nstreams;
+	refcount_t nstreams;
 
 	/* Status Interrupt Endpoint */
 	struct usb_host_endpoint *int_ep;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..ed2176e 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -12,6 +12,7 @@
 
 #include <linux/dma-buf.h>
 #include <linux/module.h>
+#include <linux/refcount.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -34,7 +35,7 @@ struct vb2_dc_buf {
 
 	/* MMAP related */
 	struct vb2_vmarea_handler	handler;
-	atomic_t			refcount;
+	refcount_t			refcount;
 	struct sg_table			*sgt_base;
 
 	/* DMABUF related */
@@ -86,7 +87,7 @@ static unsigned int vb2_dc_num_users(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
-	return atomic_read(&buf->refcount);
+	return refcount_read(&buf->refcount);
 }
 
 static void vb2_dc_prepare(void *buf_priv)
@@ -122,7 +123,7 @@ static void vb2_dc_put(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
-	if (!atomic_dec_and_test(&buf->refcount))
+	if (!refcount_dec_and_test(&buf->refcount))
 		return;
 
 	if (buf->sgt_base) {
@@ -170,7 +171,7 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs,
 	buf->handler.put = vb2_dc_put;
 	buf->handler.arg = buf;
 
-	atomic_inc(&buf->refcount);
+	refcount_inc(&buf->refcount);
 
 	return buf;
 }
@@ -407,7 +408,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 		return NULL;
 
 	/* dmabuf keeps reference to vb2 buffer */
-	atomic_inc(&buf->refcount);
+	refcount_inc(&buf->refcount);
 
 	return dbuf;
 }
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f4..f5ab6c2 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/refcount.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -46,7 +47,7 @@ struct vb2_dma_sg_buf {
 	struct sg_table			*dma_sgt;
 	size_t				size;
 	unsigned int			num_pages;
-	atomic_t			refcount;
+	refcount_t			refcount;
 	struct vb2_vmarea_handler	handler;
 
 	struct dma_buf_attachment	*db_attach;
@@ -150,7 +151,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs,
 	buf->handler.put = vb2_dma_sg_put;
 	buf->handler.arg = buf;
 
-	atomic_inc(&buf->refcount);
+	refcount_inc(&buf->refcount);
 
 	dprintk(1, "%s: Allocated buffer of %d pages\n",
 		__func__, buf->num_pages);
@@ -176,7 +177,7 @@ static void vb2_dma_sg_put(void *buf_priv)
 	struct sg_table *sgt = &buf->sg_table;
 	int i = buf->num_pages;
 
-	if (atomic_dec_and_test(&buf->refcount)) {
+	if (refcount_dec_and_test(&buf->refcount)) {
 		dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
 			buf->num_pages);
 		dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
@@ -320,7 +321,7 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
 
-	return atomic_read(&buf->refcount);
+	return refcount_read(&buf->refcount);
 }
 
 static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
@@ -530,7 +531,7 @@ static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags
 		return NULL;
 
 	/* dmabuf keeps reference to vb2 buffer */
-	atomic_inc(&buf->refcount);
+	refcount_inc(&buf->refcount);
 
 	return dbuf;
 }
diff --git a/drivers/media/v4l2-core/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c
index 1cd322e..4bb8424 100644
--- a/drivers/media/v4l2-core/videobuf2-memops.c
+++ b/drivers/media/v4l2-core/videobuf2-memops.c
@@ -96,10 +96,10 @@ static void vb2_common_vm_open(struct vm_area_struct *vma)
 	struct vb2_vmarea_handler *h = vma->vm_private_data;
 
 	pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
-	       __func__, h, atomic_read(h->refcount), vma->vm_start,
+	       __func__, h, refcount_read(h->refcount), vma->vm_start,
 	       vma->vm_end);
 
-	atomic_inc(h->refcount);
+	refcount_inc(h->refcount);
 }
 
 /**
@@ -114,7 +114,7 @@ static void vb2_common_vm_close(struct vm_area_struct *vma)
 	struct vb2_vmarea_handler *h = vma->vm_private_data;
 
 	pr_debug("%s: %p, refcount: %d, vma: %08lx-%08lx\n",
-	       __func__, h, atomic_read(h->refcount), vma->vm_start,
+	       __func__, h, refcount_read(h->refcount), vma->vm_start,
 	       vma->vm_end);
 
 	h->put(h->arg);
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 3f77814..b00eea4 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/refcount.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
@@ -26,7 +27,7 @@ struct vb2_vmalloc_buf {
 	struct frame_vector		*vec;
 	enum dma_data_direction		dma_dir;
 	unsigned long			size;
-	atomic_t			refcount;
+	refcount_t			refcount;
 	struct vb2_vmarea_handler	handler;
 	struct dma_buf			*dbuf;
 };
@@ -56,7 +57,7 @@ static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs,
 		return ERR_PTR(-ENOMEM);
 	}
 
-	atomic_inc(&buf->refcount);
+	refcount_inc(&buf->refcount);
 	return buf;
 }
 
@@ -64,7 +65,7 @@ static void vb2_vmalloc_put(void *buf_priv)
 {
 	struct vb2_vmalloc_buf *buf = buf_priv;
 
-	if (atomic_dec_and_test(&buf->refcount)) {
+	if (refcount_dec_and_test(&buf->refcount)) {
 		vfree(buf->vaddr);
 		kfree(buf);
 	}
@@ -161,7 +162,7 @@ static void *vb2_vmalloc_vaddr(void *buf_priv)
 static unsigned int vb2_vmalloc_num_users(void *buf_priv)
 {
 	struct vb2_vmalloc_buf *buf = buf_priv;
-	return atomic_read(&buf->refcount);
+	return refcount_read(&buf->refcount);
 }
 
 static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
@@ -368,7 +369,7 @@ static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flag
 		return NULL;
 
 	/* dmabuf keeps reference to vb2 buffer */
-	atomic_inc(&buf->refcount);
+	refcount_inc(&buf->refcount);
 
 	return dbuf;
 }
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
index 3efcc7b..3a3ed2b 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/host/pci-hyperv.c
@@ -56,6 +56,7 @@
 #include <asm/apic.h>
 #include <linux/msi.h>
 #include <linux/hyperv.h>
+#include <linux/refcount.h>
 #include <asm/mshyperv.h>
 
 /*
@@ -420,7 +421,7 @@ enum hv_pcidev_ref_reason {
 struct hv_pci_dev {
 	/* List protected by pci_rescan_remove_lock */
 	struct list_head list_entry;
-	atomic_t refs;
+	refcount_t refs;
 	enum hv_pcichild_state state;
 	struct pci_function_description desc;
 	bool reported_missing;
@@ -1252,13 +1253,13 @@ static void q_resource_requirements(void *context, struct pci_response *resp,
 static void get_pcichild(struct hv_pci_dev *hpdev,
 			    enum hv_pcidev_ref_reason reason)
 {
-	atomic_inc(&hpdev->refs);
+	refcount_inc(&hpdev->refs);
 }
 
 static void put_pcichild(struct hv_pci_dev *hpdev,
 			    enum hv_pcidev_ref_reason reason)
 {
-	if (atomic_dec_and_test(&hpdev->refs))
+	if (refcount_dec_and_test(&hpdev->refs))
 		kfree(hpdev);
 }
 
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 04aceb6..ced8151 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -110,7 +110,7 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
 	mutex_init(&urd->io_mutex);
 	init_waitqueue_head(&urd->wait);
 	spin_lock_init(&urd->open_lock);
-	atomic_set(&urd->ref_count,  1);
+	refcount_set(&urd->ref_count,  1);
 	urd->cdev = cdev;
 	get_device(&cdev->dev);
 	return urd;
@@ -126,7 +126,7 @@ static void urdev_free(struct urdev *urd)
 
 static void urdev_get(struct urdev *urd)
 {
-	atomic_inc(&urd->ref_count);
+	refcount_inc(&urd->ref_count);
 }
 
 static struct urdev *urdev_get_from_cdev(struct ccw_device *cdev)
@@ -159,7 +159,7 @@ static struct urdev *urdev_get_from_devno(u16 devno)
 
 static void urdev_put(struct urdev *urd)
 {
-	if (atomic_dec_and_test(&urd->ref_count))
+	if (refcount_dec_and_test(&urd->ref_count))
 		urdev_free(urd);
 }
 
@@ -946,7 +946,7 @@ static int ur_set_offline_force(struct ccw_device *cdev, int force)
 		rc = -EBUSY;
 		goto fail_urdev_put;
 	}
-	if (!force && (atomic_read(&urd->ref_count) > 2)) {
+	if (!force && (refcount_read(&urd->ref_count) > 2)) {
 		/* There is still a user of urd (e.g. ur_open) */
 		TRACE("ur_set_offline: BUSY\n");
 		rc = -EBUSY;
diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h
index fa320ad..35ea9d1 100644
--- a/drivers/s390/char/vmur.h
+++ b/drivers/s390/char/vmur.h
@@ -11,6 +11,8 @@
 #ifndef _VMUR_H_
 #define _VMUR_H_
 
+#include <linux/refcount.h>
+
 #define DEV_CLASS_UR_I 0x20 /* diag210 unit record input device class */
 #define DEV_CLASS_UR_O 0x10 /* diag210 unit record output device class */
 /*
@@ -69,7 +71,7 @@ struct urdev {
 	size_t reclen;			/* Record length for *write* CCWs */
 	int class;			/* VM device class */
 	int io_request_rc;		/* return code from I/O request */
-	atomic_t ref_count;		/* reference counter */
+	refcount_t ref_count;		/* reference counter */
 	wait_queue_head_t wait;		/* wait queue to serialize open */
 	int open_flag;			/* "urdev is open" flag */
 	spinlock_t open_lock;		/* serialize critical sections */
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 211b31d..fd68f67 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -774,15 +774,15 @@ lcs_get_lancmd(struct lcs_card *card, int count)
 static void
 lcs_get_reply(struct lcs_reply *reply)
 {
-	WARN_ON(atomic_read(&reply->refcnt) <= 0);
-	atomic_inc(&reply->refcnt);
+	WARN_ON(refcount_read(&reply->refcnt) == 0);
+	refcount_inc(&reply->refcnt);
 }
 
 static void
 lcs_put_reply(struct lcs_reply *reply)
 {
-        WARN_ON(atomic_read(&reply->refcnt) <= 0);
-        if (atomic_dec_and_test(&reply->refcnt)) {
+        WARN_ON(refcount_read(&reply->refcnt) == 0);
+        if (refcount_dec_and_test(&reply->refcnt)) {
 		kfree(reply);
 	}
 
@@ -798,7 +798,7 @@ lcs_alloc_reply(struct lcs_cmd *cmd)
 	reply = kzalloc(sizeof(struct lcs_reply), GFP_ATOMIC);
 	if (!reply)
 		return NULL;
-	atomic_set(&reply->refcnt,1);
+	refcount_set(&reply->refcnt,1);
 	reply->sequence_no = cmd->sequence_no;
 	reply->received = 0;
 	reply->rc = 0;
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 150fcb4..3802f4f 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -4,6 +4,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
+#include <linux/refcount.h>
 #include <asm/ccwdev.h>
 
 #define LCS_DBF_TEXT(level, name, text) \
@@ -270,7 +271,7 @@ struct lcs_buffer {
 struct lcs_reply {
 	struct list_head list;
 	__u16 sequence_no;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	/* Callback for completion notification. */
 	void (*callback)(struct lcs_card *, struct lcs_cmd *);
 	wait_queue_head_t wait_q;
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 6d4b68c4..99cdcfc 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -20,6 +20,7 @@
 #include <linux/ethtool.h>
 #include <linux/hashtable.h>
 #include <linux/ip.h>
+#include <linux/refcount.h>
 
 #include <net/ipv6.h>
 #include <net/if_inet6.h>
@@ -643,7 +644,7 @@ struct qeth_reply {
 	int rc;
 	void *param;
 	struct qeth_card *card;
-	atomic_t refcnt;
+	refcount_t refcnt;
 };
 
 
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index e6ebcd7..efd92fb 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -555,7 +555,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
 
 	reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
 	if (reply) {
-		atomic_set(&reply->refcnt, 1);
+		refcount_set(&reply->refcnt, 1);
 		atomic_set(&reply->received, 0);
 		reply->card = card;
 	}
@@ -564,14 +564,14 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
 
 static void qeth_get_reply(struct qeth_reply *reply)
 {
-	WARN_ON(atomic_read(&reply->refcnt) <= 0);
-	atomic_inc(&reply->refcnt);
+	WARN_ON(refcount_read(&reply->refcnt) == 0);
+	refcount_inc(&reply->refcnt);
 }
 
 static void qeth_put_reply(struct qeth_reply *reply)
 {
-	WARN_ON(atomic_read(&reply->refcnt) <= 0);
-	if (atomic_dec_and_test(&reply->refcnt))
+	WARN_ON(refcount_read(&reply->refcnt) == 0);
+	if (refcount_dec_and_test(&reply->refcnt))
 		kfree(reply);
 }
 
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 42bcf7f..cff268b 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -257,7 +257,7 @@ static const char *fc_exch_rctl_name(unsigned int op)
  */
 static inline void fc_exch_hold(struct fc_exch *ep)
 {
-	atomic_inc(&ep->ex_refcnt);
+	refcount_inc(&ep->ex_refcnt);
 }
 
 /**
@@ -323,7 +323,7 @@ static void fc_exch_release(struct fc_exch *ep)
 {
 	struct fc_exch_mgr *mp;
 
-	if (atomic_dec_and_test(&ep->ex_refcnt)) {
+	if (refcount_dec_and_test(&ep->ex_refcnt)) {
 		mp = ep->em;
 		if (ep->destructor)
 			ep->destructor(&ep->seq, ep->arg);
@@ -340,7 +340,7 @@ static inline void fc_exch_timer_cancel(struct fc_exch *ep)
 {
 	if (cancel_delayed_work(&ep->timeout_work)) {
 		FC_EXCH_DBG(ep, "Exchange timer canceled\n");
-		atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
+		refcount_dec(&ep->ex_refcnt); /* drop hold for timer */
 	}
 }
 
@@ -1899,7 +1899,7 @@ static void fc_exch_reset(struct fc_exch *ep)
 	ep->state |= FC_EX_RST_CLEANUP;
 	fc_exch_timer_cancel(ep);
 	if (ep->esb_stat & ESB_ST_REC_QUAL)
-		atomic_dec(&ep->ex_refcnt);	/* drop hold for rec_qual */
+		refcount_dec(&ep->ex_refcnt);	/* drop hold for rec_qual */
 	ep->esb_stat &= ~ESB_ST_REC_QUAL;
 	sp = &ep->seq;
 	rc = fc_exch_done_locked(ep);
@@ -2328,7 +2328,7 @@ static void fc_exch_els_rrq(struct fc_frame *fp)
 	 */
 	if (ep->esb_stat & ESB_ST_REC_QUAL) {
 		ep->esb_stat &= ~ESB_ST_REC_QUAL;
-		atomic_dec(&ep->ex_refcnt);	/* drop hold for rec qual */
+		refcount_dec(&ep->ex_refcnt);	/* drop hold for rec qual */
 	}
 	if (ep->esb_stat & ESB_ST_COMPLETE)
 		fc_exch_timer_cancel(ep);
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 0e67621..a808e8e 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -154,7 +154,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
 		memset(fsp, 0, sizeof(*fsp));
 		fsp->lp = lport;
 		fsp->xfer_ddp = FC_XID_UNKNOWN;
-		atomic_set(&fsp->ref_cnt, 1);
+		refcount_set(&fsp->ref_cnt, 1);
 		init_timer(&fsp->timer);
 		fsp->timer.data = (unsigned long)fsp;
 		INIT_LIST_HEAD(&fsp->list);
@@ -175,7 +175,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
  */
 static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp)
 {
-	if (atomic_dec_and_test(&fsp->ref_cnt)) {
+	if (refcount_dec_and_test(&fsp->ref_cnt)) {
 		struct fc_fcp_internal *si = fc_get_scsi_internal(fsp->lp);
 
 		mempool_free(fsp, si->scsi_pkt_pool);
@@ -188,7 +188,7 @@ static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp)
  */
 static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp)
 {
-	atomic_inc(&fsp->ref_cnt);
+	refcount_inc(&fsp->ref_cnt);
 }
 
 /**
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index f9b6fba..400b978 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -516,13 +516,13 @@ static void iscsi_free_task(struct iscsi_task *task)
 
 void __iscsi_get_task(struct iscsi_task *task)
 {
-	atomic_inc(&task->refcount);
+	refcount_inc(&task->refcount);
 }
 EXPORT_SYMBOL_GPL(__iscsi_get_task);
 
 void __iscsi_put_task(struct iscsi_task *task)
 {
-	if (atomic_dec_and_test(&task->refcount))
+	if (refcount_dec_and_test(&task->refcount))
 		iscsi_free_task(task);
 }
 EXPORT_SYMBOL_GPL(__iscsi_put_task);
@@ -744,7 +744,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 	 * released by the lld when it has transmitted the task for
 	 * pdus we do not expect a response for.
 	 */
-	atomic_set(&task->refcount, 1);
+	refcount_set(&task->refcount, 1);
 	task->conn = conn;
 	task->sc = NULL;
 	INIT_LIST_HEAD(&task->running);
@@ -1616,7 +1616,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
 	sc->SCp.phase = conn->session->age;
 	sc->SCp.ptr = (char *) task;
 
-	atomic_set(&task->refcount, 1);
+	refcount_set(&task->refcount, 1);
 	task->state = ISCSI_TASK_PENDING;
 	task->conn = conn;
 	task->sc = sc;
diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
index d6a2054..68517c4 100644
--- a/drivers/scsi/qedi/qedi_iscsi.c
+++ b/drivers/scsi/qedi/qedi_iscsi.c
@@ -1375,7 +1375,7 @@ static void qedi_cleanup_task(struct iscsi_task *task)
 {
 	if (!task->sc || task->state == ISCSI_TASK_PENDING) {
 		QEDI_INFO(NULL, QEDI_LOG_IO, "Returning ref_cnt=%d\n",
-			  atomic_read(&task->refcount));
+			  refcount_read(&task->refcount));
 		return;
 	}
 
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index 87aa517..f2a3c17 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -17,7 +17,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/cdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -117,7 +117,7 @@ static const int type[VME_DEVS] = {	MASTER_MINOR,	MASTER_MINOR,
 
 struct vme_user_vma_priv {
 	unsigned int minor;
-	atomic_t refcnt;
+	refcount_t refcnt;
 };
 
 static ssize_t resource_to_user(int minor, char __user *buf, size_t count,
@@ -429,7 +429,7 @@ static void vme_user_vm_open(struct vm_area_struct *vma)
 {
 	struct vme_user_vma_priv *vma_priv = vma->vm_private_data;
 
-	atomic_inc(&vma_priv->refcnt);
+	refcount_inc(&vma_priv->refcnt);
 }
 
 static void vme_user_vm_close(struct vm_area_struct *vma)
@@ -437,7 +437,7 @@ static void vme_user_vm_close(struct vm_area_struct *vma)
 	struct vme_user_vma_priv *vma_priv = vma->vm_private_data;
 	unsigned int minor = vma_priv->minor;
 
-	if (!atomic_dec_and_test(&vma_priv->refcnt))
+	if (!refcount_dec_and_test(&vma_priv->refcnt))
 		return;
 
 	mutex_lock(&image[minor].mutex);
@@ -472,7 +472,7 @@ static int vme_user_master_mmap(unsigned int minor, struct vm_area_struct *vma)
 	}
 
 	vma_priv->minor = minor;
-	atomic_set(&vma_priv->refcnt, 1);
+	refcount_set(&vma_priv->refcnt, 1);
 	vma->vm_ops = &vme_user_vm_ops;
 	vma->vm_private_data = vma_priv;
 
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index d316ed5..bb069eb 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -279,7 +279,7 @@ static void iblock_complete_cmd(struct se_cmd *cmd)
 	struct iblock_req *ibr = cmd->priv;
 	u8 status;
 
-	if (!atomic_dec_and_test(&ibr->pending))
+	if (!refcount_dec_and_test(&ibr->pending))
 		return;
 
 	if (atomic_read(&ibr->ib_bio_err_cnt))
@@ -487,7 +487,7 @@ iblock_execute_write_same(struct se_cmd *cmd)
 	bio_list_init(&list);
 	bio_list_add(&list, bio);
 
-	atomic_set(&ibr->pending, 1);
+	refcount_set(&ibr->pending, 1);
 
 	while (sectors) {
 		while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
@@ -498,7 +498,7 @@ iblock_execute_write_same(struct se_cmd *cmd)
 			if (!bio)
 				goto fail_put_bios;
 
-			atomic_inc(&ibr->pending);
+			refcount_inc(&ibr->pending);
 			bio_list_add(&list, bio);
 		}
 
@@ -706,7 +706,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 	cmd->priv = ibr;
 
 	if (!sgl_nents) {
-		atomic_set(&ibr->pending, 1);
+		refcount_set(&ibr->pending, 1);
 		iblock_complete_cmd(cmd);
 		return 0;
 	}
@@ -719,7 +719,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 	bio_list_init(&list);
 	bio_list_add(&list, bio);
 
-	atomic_set(&ibr->pending, 2);
+	refcount_set(&ibr->pending, 2);
 	bio_cnt = 1;
 
 	for_each_sg(sgl, sg, sgl_nents, i) {
@@ -740,7 +740,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 			if (!bio)
 				goto fail_put_bios;
 
-			atomic_inc(&ibr->pending);
+			refcount_inc(&ibr->pending);
 			bio_list_add(&list, bio);
 			bio_cnt++;
 		}
diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h
index 718d3fc..f2a5797 100644
--- a/drivers/target/target_core_iblock.h
+++ b/drivers/target/target_core_iblock.h
@@ -2,6 +2,7 @@
 #define TARGET_CORE_IBLOCK_H
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <target/target_core_base.h>
 
 #define IBLOCK_VERSION		"4.0"
@@ -10,7 +11,7 @@
 #define IBLOCK_LBA_SHIFT	9
 
 struct iblock_req {
-	atomic_t pending;
+	refcount_t pending;
 	atomic_t ib_bio_err_cnt;
 } ____cacheline_aligned;
 
diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c
index c121f16..5b5358f 100644
--- a/drivers/tty/serial/dz.c
+++ b/drivers/tty/serial/dz.c
@@ -49,7 +49,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 
@@ -78,8 +78,8 @@ struct dz_port {
 
 struct dz_mux {
 	struct dz_port		dport[DZ_NB_PORT];
-	atomic_t		map_guard;
-	atomic_t		irq_guard;
+	refcount_t		map_guard;
+	refcount_t		irq_guard;
 	int			initialised;
 };
 
@@ -403,18 +403,17 @@ static int dz_startup(struct uart_port *uport)
 	struct dz_port *dport = to_dport(uport);
 	struct dz_mux *mux = dport->mux;
 	unsigned long flags;
-	int irq_guard;
 	int ret;
 	u16 tmp;
 
-	irq_guard = atomic_add_return(1, &mux->irq_guard);
-	if (irq_guard != 1)
+	refcount_inc(&mux->irq_guard);
+	if (refcount_read(&mux->irq_guard) != 1)
 		return 0;
 
 	ret = request_irq(dport->port.irq, dz_interrupt,
 			  IRQF_SHARED, "dz", mux);
 	if (ret) {
-		atomic_add(-1, &mux->irq_guard);
+		refcount_dec(&mux->irq_guard);
 		printk(KERN_ERR "dz: Cannot get IRQ %d!\n", dport->port.irq);
 		return ret;
 	}
@@ -444,15 +443,13 @@ static void dz_shutdown(struct uart_port *uport)
 	struct dz_port *dport = to_dport(uport);
 	struct dz_mux *mux = dport->mux;
 	unsigned long flags;
-	int irq_guard;
 	u16 tmp;
 
 	spin_lock_irqsave(&dport->port.lock, flags);
 	dz_stop_tx(&dport->port);
 	spin_unlock_irqrestore(&dport->port.lock, flags);
 
-	irq_guard = atomic_add_return(-1, &mux->irq_guard);
-	if (!irq_guard) {
+	if (refcount_dec_and_test(&mux->irq_guard)) {
 		/* Disable interrupts.  */
 		tmp = dz_in(dport, DZ_CSR);
 		tmp &= ~(DZ_RIE | DZ_TIE);
@@ -663,13 +660,11 @@ static const char *dz_type(struct uart_port *uport)
 static void dz_release_port(struct uart_port *uport)
 {
 	struct dz_mux *mux = to_dport(uport)->mux;
-	int map_guard;
 
 	iounmap(uport->membase);
 	uport->membase = NULL;
 
-	map_guard = atomic_add_return(-1, &mux->map_guard);
-	if (!map_guard)
+	if (refcount_dec_and_test(&mux->map_guard))
 		release_mem_region(uport->mapbase, dec_kn_slot_size);
 }
 
@@ -688,14 +683,13 @@ static int dz_map_port(struct uart_port *uport)
 static int dz_request_port(struct uart_port *uport)
 {
 	struct dz_mux *mux = to_dport(uport)->mux;
-	int map_guard;
 	int ret;
 
-	map_guard = atomic_add_return(1, &mux->map_guard);
-	if (map_guard == 1) {
+	refcount_inc(&mux->map_guard);
+	if (refcount_read(&mux->map_guard) == 1) {
 		if (!request_mem_region(uport->mapbase, dec_kn_slot_size,
 					"dz")) {
-			atomic_add(-1, &mux->map_guard);
+			refcount_dec(&mux->map_guard);
 			printk(KERN_ERR
 			       "dz: Unable to reserve MMIO resource\n");
 			return -EBUSY;
@@ -703,8 +697,7 @@ static int dz_request_port(struct uart_port *uport)
 	}
 	ret = dz_map_port(uport);
 	if (ret) {
-		map_guard = atomic_add_return(-1, &mux->map_guard);
-		if (!map_guard)
+		if (refcount_dec_and_test(&mux->map_guard))
 			release_mem_region(uport->mapbase, dec_kn_slot_size);
 		return ret;
 	}
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c
index 771f361..041625c 100644
--- a/drivers/tty/serial/sb1250-duart.c
+++ b/drivers/tty/serial/sb1250-duart.c
@@ -41,7 +41,7 @@
 #include <linux/tty_flip.h>
 #include <linux/types.h>
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <asm/io.h>
 #include <asm/war.h>
 
@@ -103,7 +103,7 @@ struct sbd_port {
 struct sbd_duart {
 	struct sbd_port		sport[2];
 	unsigned long		mapctrl;
-	atomic_t		map_guard;
+	refcount_t		map_guard;
 };
 
 #define to_sport(uport) container_of(uport, struct sbd_port, port)
@@ -654,15 +654,13 @@ static void sbd_release_port(struct uart_port *uport)
 {
 	struct sbd_port *sport = to_sport(uport);
 	struct sbd_duart *duart = sport->duart;
-	int map_guard;
 
 	iounmap(sport->memctrl);
 	sport->memctrl = NULL;
 	iounmap(uport->membase);
 	uport->membase = NULL;
 
-	map_guard = atomic_add_return(-1, &duart->map_guard);
-	if (!map_guard)
+	if(refcount_dec_and_test(&duart->map_guard))
 		release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
 	release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
 }
@@ -698,7 +696,6 @@ static int sbd_request_port(struct uart_port *uport)
 {
 	const char *err = KERN_ERR "sbd: Unable to reserve MMIO resource\n";
 	struct sbd_duart *duart = to_sport(uport)->duart;
-	int map_guard;
 	int ret = 0;
 
 	if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
@@ -706,11 +703,11 @@ static int sbd_request_port(struct uart_port *uport)
 		printk(err);
 		return -EBUSY;
 	}
-	map_guard = atomic_add_return(1, &duart->map_guard);
-	if (map_guard == 1) {
+	refcount_inc(&duart->map_guard);
+	if (refcount_read(&duart->map_guard) == 1) {
 		if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
 					"sb1250-duart")) {
-			atomic_add(-1, &duart->map_guard);
+			refcount_dec(&duart->map_guard);
 			printk(err);
 			ret = -EBUSY;
 		}
@@ -718,8 +715,7 @@ static int sbd_request_port(struct uart_port *uport)
 	if (!ret) {
 		ret = sbd_map_port(uport);
 		if (ret) {
-			map_guard = atomic_add_return(-1, &duart->map_guard);
-			if (!map_guard)
+			if (refcount_dec_and_test(&duart->map_guard))
 				release_mem_region(duart->mapctrl,
 						   DUART_CHANREG_SPACING);
 		}
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 1eeb319..485d6b1 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1570,14 +1570,14 @@ static void ffs_data_get(struct ffs_data *ffs)
 {
 	ENTER();
 
-	atomic_inc(&ffs->ref);
+	refcount_inc(&ffs->ref);
 }
 
 static void ffs_data_opened(struct ffs_data *ffs)
 {
 	ENTER();
 
-	atomic_inc(&ffs->ref);
+	refcount_inc(&ffs->ref);
 	if (atomic_add_return(1, &ffs->opened) == 1 &&
 			ffs->state == FFS_DEACTIVATED) {
 		ffs->state = FFS_CLOSING;
@@ -1589,7 +1589,7 @@ static void ffs_data_put(struct ffs_data *ffs)
 {
 	ENTER();
 
-	if (unlikely(atomic_dec_and_test(&ffs->ref))) {
+	if (unlikely(refcount_dec_and_test(&ffs->ref))) {
 		pr_info("%s(): freeing\n", __func__);
 		ffs_data_clear(ffs);
 		BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
@@ -1634,7 +1634,7 @@ static struct ffs_data *ffs_data_new(void)
 
 	ENTER();
 
-	atomic_set(&ffs->ref, 1);
+	refcount_set(&ffs->ref, 1);
 	atomic_set(&ffs->opened, 0);
 	ffs->state = FFS_READ_DESCRIPTORS;
 	mutex_init(&ffs->mutex);
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index 6013985..7b690a2 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -20,6 +20,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
+#include <linux/refcount.h>
 
 #ifdef VERBOSE_DEBUG
 #ifndef pr_vdebug
@@ -177,7 +178,7 @@ struct ffs_data {
 	struct completion		ep0req_completion;	/* P: mutex */
 
 	/* reference counter */
-	atomic_t			ref;
+	refcount_t			ref;
 	/* how many files are opened (EP0 and others) */
 	atomic_t			opened;
 
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index e8f4102..9e46373 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -27,6 +27,7 @@
 #include <linux/mmu_context.h>
 #include <linux/aio.h>
 #include <linux/uio.h>
+#include <linux/refcount.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -115,7 +116,7 @@ enum ep0_state {
 
 struct dev_data {
 	spinlock_t			lock;
-	atomic_t			count;
+	refcount_t			count;
 	enum ep0_state			state;		/* P: lock */
 	struct usb_gadgetfs_event	event [N_EVENT];
 	unsigned			ev_next;
@@ -151,12 +152,12 @@ struct dev_data {
 
 static inline void get_dev (struct dev_data *data)
 {
-	atomic_inc (&data->count);
+	refcount_inc (&data->count);
 }
 
 static void put_dev (struct dev_data *data)
 {
-	if (likely (!atomic_dec_and_test (&data->count)))
+	if (likely (!refcount_dec_and_test (&data->count)))
 		return;
 	/* needs no more cleanup */
 	BUG_ON (waitqueue_active (&data->wait));
@@ -171,7 +172,7 @@ static struct dev_data *dev_new (void)
 	if (!dev)
 		return NULL;
 	dev->state = STATE_DEV_DISABLED;
-	atomic_set (&dev->count, 1);
+	refcount_set (&dev->count, 1);
 	spin_lock_init (&dev->lock);
 	INIT_LIST_HEAD (&dev->epfiles);
 	init_waitqueue_head (&dev->wait);
@@ -191,7 +192,7 @@ enum ep_state {
 struct ep_data {
 	struct mutex			lock;
 	enum ep_state			state;
-	atomic_t			count;
+	refcount_t			count;
 	struct dev_data			*dev;
 	/* must hold dev->lock before accessing ep or req */
 	struct usb_ep			*ep;
@@ -206,12 +207,12 @@ struct ep_data {
 
 static inline void get_ep (struct ep_data *data)
 {
-	atomic_inc (&data->count);
+	refcount_inc (&data->count);
 }
 
 static void put_ep (struct ep_data *data)
 {
-	if (likely (!atomic_dec_and_test (&data->count)))
+	if (likely (!refcount_dec_and_test (&data->count)))
 		return;
 	put_dev (data->dev);
 	/* needs no more cleanup */
@@ -1562,7 +1563,7 @@ static int activate_ep_files (struct dev_data *dev)
 		init_waitqueue_head (&data->wait);
 
 		strncpy (data->name, ep->name, sizeof (data->name) - 1);
-		atomic_set (&data->count, 1);
+		refcount_set (&data->count, 1);
 		data->dev = dev;
 		get_dev (dev);
 
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 2ef2b61..b183cb2 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -35,6 +35,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
+#include <linux/refcount.h>
 
 #include <xen/xen.h>
 #include <xen/grant_table.h>
@@ -85,7 +86,7 @@ struct grant_map {
 	int index;
 	int count;
 	int flags;
-	atomic_t users;
+	refcount_t users;
 	struct unmap_notify notify;
 	struct ioctl_gntdev_grant_ref *grants;
 	struct gnttab_map_grant_ref   *map_ops;
@@ -165,7 +166,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 
 	add->index = 0;
 	add->count = count;
-	atomic_set(&add->users, 1);
+	refcount_set(&add->users, 1);
 
 	return add;
 
@@ -211,7 +212,7 @@ static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map)
 	if (!map)
 		return;
 
-	if (!atomic_dec_and_test(&map->users))
+	if (!refcount_dec_and_test(&map->users))
 		return;
 
 	atomic_sub(map->count, &pages_mapped);
@@ -399,7 +400,7 @@ static void gntdev_vma_open(struct vm_area_struct *vma)
 	struct grant_map *map = vma->vm_private_data;
 
 	pr_debug("gntdev_vma_open %p\n", vma);
-	atomic_inc(&map->users);
+	refcount_inc(&map->users);
 }
 
 static void gntdev_vma_close(struct vm_area_struct *vma)
@@ -1003,7 +1004,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
 		goto unlock_out;
 	}
 
-	atomic_inc(&map->users);
+	refcount_inc(&map->users);
 
 	vma->vm_ops = &gntdev_vmops;
 
diff --git a/include/linux/connector.h b/include/linux/connector.h
index f8fe863..032102b 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -22,7 +22,7 @@
 #define __CONNECTOR_H
 
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include <linux/list.h>
 #include <linux/workqueue.h>
@@ -49,7 +49,7 @@ struct cn_callback_id {
 
 struct cn_callback_entry {
 	struct list_head callback_entry;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	struct cn_queue_dev *pdev;
 
 	struct cn_callback_id id;
diff --git a/include/media/videobuf2-memops.h b/include/media/videobuf2-memops.h
index 36565c7a..a6ed091 100644
--- a/include/media/videobuf2-memops.h
+++ b/include/media/videobuf2-memops.h
@@ -16,6 +16,7 @@
 
 #include <media/videobuf2-v4l2.h>
 #include <linux/mm.h>
+#include <linux/refcount.h>
 
 /**
  * struct vb2_vmarea_handler - common vma refcount tracking handler
@@ -25,7 +26,7 @@
  * @arg:	argument for @put callback
  */
 struct vb2_vmarea_handler {
-	atomic_t		*refcount;
+	refcount_t		*refcount;
 	void			(*put)(void *arg);
 	void			*arg;
 };
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 96dd0b3..53d2747 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -23,6 +23,7 @@
 #include <linux/timer.h>
 #include <linux/if.h>
 #include <linux/percpu.h>
+#include <linux/refcount.h>
 
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_fc.h>
@@ -321,7 +322,7 @@ struct fc_seq_els_data {
  */
 struct fc_fcp_pkt {
 	spinlock_t	  scsi_pkt_lock;
-	atomic_t	  ref_cnt;
+	refcount_t	  ref_cnt;
 
 	/* SCSI command and data transfer information */
 	u32		  data_len;
@@ -434,7 +435,7 @@ struct fc_seq {
  */
 struct fc_exch {
 	spinlock_t	    ex_lock;
-	atomic_t	    ex_refcnt;
+	refcount_t	    ex_refcnt;
 	enum fc_class	    class;
 	struct fc_exch_mgr  *em;
 	struct fc_exch_pool *pool;
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 4d1c46a..854ee17 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -29,6 +29,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/kfifo.h>
+#include <linux/refcount.h>
 #include <scsi/iscsi_proto.h>
 #include <scsi/iscsi_if.h>
 #include <scsi/scsi_transport_iscsi.h>
@@ -139,7 +140,7 @@ struct iscsi_task {
 
 	/* state set/tested under session->lock */
 	int			state;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct list_head	running;	/* running cmd list */
 	void			*dd_data;	/* driver/transport data */
 };
diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h
index df3e9ae..3c664ff 100644
--- a/include/trace/events/bcache.h
+++ b/include/trace/events/bcache.h
@@ -456,7 +456,7 @@ TRACE_EVENT(bcache_alloc_fail,
 		__entry->dev		= ca->bdev->bd_dev;
 		__entry->free		= fifo_used(&ca->free[reserve]);
 		__entry->free_inc	= fifo_used(&ca->free_inc);
-		__entry->blocked	= atomic_read(&ca->set->prio_blocked);
+		__entry->blocked	= refcount_read(&ca->set->prio_blocked);
 	),
 
 	TP_printk("alloc fail %d,%d free %u free_inc %u blocked %u",
-- 
2.7.4

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

* [kernel-hardening] [RFCv2 PATCH 18/18] drivers: infiniband convert from atomic_t to refcount_t
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (16 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 17/18] drivers: misc drivers " Elena Reshetova
@ 2017-01-18  9:11 ` Elena Reshetova
  2017-01-18 10:30 ` [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage Greg KH
  2017-01-18 21:52 ` [kernel-hardening] " Eric Biggers
  19 siblings, 0 replies; 46+ messages in thread
From: Elena Reshetova @ 2017-01-18  9:11 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova, Hans Liljestrand

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. Convert the cases found.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/infiniband/core/addr.c              |   8 +--
 drivers/infiniband/core/cm.c                |  26 +++----
 drivers/infiniband/core/cma.c               |  29 ++++----
 drivers/infiniband/core/cq.c                |   4 +-
 drivers/infiniband/core/iwcm.c              |  10 +--
 drivers/infiniband/core/iwcm.h              |   4 +-
 drivers/infiniband/core/iwpm_util.c         |   8 +--
 drivers/infiniband/core/iwpm_util.h         |   3 +-
 drivers/infiniband/core/mad.c               |  36 +++++-----
 drivers/infiniband/core/mad_priv.h          |   5 +-
 drivers/infiniband/core/mad_rmpp.c          |  11 +--
 drivers/infiniband/core/multicast.c         |  31 +++++----
 drivers/infiniband/core/uverbs.h            |   4 +-
 drivers/infiniband/core/uverbs_cmd.c        |  74 ++++++++++----------
 drivers/infiniband/core/uverbs_main.c       |  14 ++--
 drivers/infiniband/core/verbs.c             | 102 ++++++++++++++--------------
 drivers/infiniband/hw/cxgb3/iwch_ev.c       |   8 +--
 drivers/infiniband/hw/cxgb3/iwch_provider.c |  16 ++---
 drivers/infiniband/hw/cxgb3/iwch_provider.h |   5 +-
 drivers/infiniband/hw/cxgb3/iwch_qp.c       |   4 +-
 drivers/infiniband/hw/cxgb4/cq.c            |   6 +-
 drivers/infiniband/hw/cxgb4/ev.c            |   8 +--
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h      |   3 +-
 drivers/infiniband/hw/hfi1/file_ops.c       |   2 +-
 drivers/infiniband/hw/hfi1/qp.c             |   2 +-
 drivers/infiniband/hw/hfi1/user_sdma.c      |  13 ++--
 drivers/infiniband/hw/hns/hns_roce_cq.c     |   8 +--
 drivers/infiniband/hw/hns/hns_roce_device.h |   5 +-
 drivers/infiniband/hw/hns/hns_roce_qp.c     |  10 +--
 drivers/infiniband/hw/i40iw/i40iw.h         |   3 +-
 drivers/infiniband/hw/i40iw/i40iw_cm.c      |  12 ++--
 drivers/infiniband/hw/i40iw/i40iw_main.c    |   2 +-
 drivers/infiniband/hw/i40iw/i40iw_puda.h    |   4 +-
 drivers/infiniband/hw/i40iw/i40iw_utils.c   |  12 ++--
 drivers/infiniband/hw/i40iw/i40iw_verbs.c   |   2 +-
 drivers/infiniband/hw/i40iw/i40iw_verbs.h   |   4 +-
 drivers/infiniband/hw/mlx4/mcg.c            |  39 +++++------
 drivers/infiniband/hw/mlx5/cq.c             |   2 +-
 drivers/infiniband/hw/mlx5/main.c           |  20 +++---
 drivers/infiniband/hw/nes/nes.c             |   8 +--
 drivers/infiniband/hw/nes/nes_cm.c          |  28 ++++----
 drivers/infiniband/hw/nes/nes_cm.h          |   6 +-
 drivers/infiniband/hw/nes/nes_hw.c          |   8 +--
 drivers/infiniband/hw/nes/nes_hw.h          |   4 +-
 drivers/infiniband/hw/nes/nes_mgt.c         |   6 +-
 drivers/infiniband/hw/nes/nes_utils.c       |   4 +-
 drivers/infiniband/hw/nes/nes_verbs.c       |  44 ++++++------
 drivers/infiniband/hw/nes/nes_verbs.h       |   6 +-
 drivers/infiniband/hw/qib/qib_keys.c        |   4 +-
 drivers/infiniband/sw/rdmavt/mr.c           |   6 +-
 drivers/infiniband/sw/rdmavt/qp.c           |   4 +-
 drivers/infiniband/ulp/ipoib/ipoib.h        |   5 +-
 drivers/infiniband/ulp/ipoib/ipoib_main.c   |   8 +--
 include/linux/mlx5/driver.h                 |   5 +-
 include/rdma/ib_addr.h                      |   3 +-
 include/rdma/ib_verbs.h                     |  15 ++--
 include/rdma/rdmavt_mr.h                    |   6 +-
 include/rdma/rdmavt_qp.h                    |   6 +-
 58 files changed, 382 insertions(+), 353 deletions(-)

diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 0f58f46..10cf06d 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -213,14 +213,14 @@ static struct rdma_addr_client self;
 
 void rdma_addr_register_client(struct rdma_addr_client *client)
 {
-	atomic_set(&client->refcount, 1);
+	refcount_set(&client->refcount, 1);
 	init_completion(&client->comp);
 }
 EXPORT_SYMBOL(rdma_addr_register_client);
 
 static inline void put_client(struct rdma_addr_client *client)
 {
-	if (atomic_dec_and_test(&client->refcount))
+	if (refcount_dec_and_test(&client->refcount))
 		complete(&client->comp);
 }
 
@@ -633,7 +633,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
 	req->callback = callback;
 	req->context = context;
 	req->client = client;
-	atomic_inc(&client->refcount);
+	refcount_inc(&client->refcount);
 	req->seq = (u32)atomic_inc_return(&ib_nl_addr_request_seq);
 
 	req->status = addr_resolve(src_in, dst_in, addr, true, req->seq);
@@ -648,7 +648,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
 		break;
 	default:
 		ret = req->status;
-		atomic_dec(&client->refcount);
+		refcount_dec(&client->refcount);
 		goto err;
 	}
 	return ret;
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index cf1edfa..cc9c3af 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -48,6 +48,7 @@
 #include <linux/workqueue.h>
 #include <linux/kdev_t.h>
 #include <linux/etherdevice.h>
+#include <linux/refcount.h>
 
 #include <rdma/ib_cache.h>
 #include <rdma/ib_cm.h>
@@ -262,7 +263,7 @@ struct cm_id_private {
 	struct rb_node sidr_id_node;
 	spinlock_t lock;	/* Do not acquire inside cm.lock */
 	struct completion comp;
-	atomic_t refcount;
+	refcount_t refcount;
 	/* Number of clients sharing this ib_cm_id. Only valid for listeners.
 	 * Protected by the cm.lock spinlock. */
 	int listen_sharecount;
@@ -307,7 +308,7 @@ static void cm_work_handler(struct work_struct *work);
 
 static inline void cm_deref_id(struct cm_id_private *cm_id_priv)
 {
-	if (atomic_dec_and_test(&cm_id_priv->refcount))
+	if (refcount_dec_and_test(&cm_id_priv->refcount))
 		complete(&cm_id_priv->comp);
 }
 
@@ -364,7 +365,7 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
 	m->ah = ah;
 	m->retries = cm_id_priv->max_cm_retries;
 
-	atomic_inc(&cm_id_priv->refcount);
+	refcount_inc(&cm_id_priv->refcount);
 	m->context[0] = cm_id_priv;
 	*msg = m;
 
@@ -522,7 +523,7 @@ static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
 			      (__force int) (local_id ^ cm.random_id_operand));
 	if (cm_id_priv) {
 		if (cm_id_priv->id.remote_id == remote_id)
-			atomic_inc(&cm_id_priv->refcount);
+			refcount_inc(&cm_id_priv->refcount);
 		else
 			cm_id_priv = NULL;
 	}
@@ -779,7 +780,7 @@ struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
 	INIT_LIST_HEAD(&cm_id_priv->prim_list);
 	INIT_LIST_HEAD(&cm_id_priv->altr_list);
 	atomic_set(&cm_id_priv->work_count, -1);
-	atomic_set(&cm_id_priv->refcount, 1);
+	refcount_set(&cm_id_priv->refcount, 1);
 	return &cm_id_priv->id;
 
 error:
@@ -1123,7 +1124,7 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device,
 			spin_unlock_irqrestore(&cm.lock, flags);
 			return ERR_PTR(-EINVAL);
 		}
-		atomic_inc(&cm_id_priv->refcount);
+		refcount_inc(&cm_id_priv->refcount);
 		++cm_id_priv->listen_sharecount;
 		spin_unlock_irqrestore(&cm.lock, flags);
 
@@ -1678,8 +1679,8 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
 			     NULL, 0);
 		goto out;
 	}
-	atomic_inc(&listen_cm_id_priv->refcount);
-	atomic_inc(&cm_id_priv->refcount);
+	refcount_inc(&listen_cm_id_priv->refcount);
+	refcount_inc(&cm_id_priv->refcount);
 	cm_id_priv->id.state = IB_CM_REQ_RCVD;
 	atomic_inc(&cm_id_priv->work_count);
 	spin_unlock_irq(&cm.lock);
@@ -1822,7 +1823,8 @@ static int cm_req_handler(struct cm_work *work)
 	return 0;
 
 rejected:
-	atomic_dec(&cm_id_priv->refcount);
+	/* FIXME: make sure we're expecting non-zero! */
+	refcount_dec(&cm_id_priv->refcount);
 	cm_deref_id(listen_cm_id_priv);
 destroy:
 	ib_destroy_cm_id(cm_id);
@@ -2565,7 +2567,7 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
 				       cm.random_id_operand));
 		if (cm_id_priv) {
 			if (cm_id_priv->id.remote_id == remote_id)
-				atomic_inc(&cm_id_priv->refcount);
+				refcount_inc(&cm_id_priv->refcount);
 			else
 				cm_id_priv = NULL;
 		}
@@ -3262,8 +3264,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
 		cm_reject_sidr_req(cm_id_priv, IB_SIDR_UNSUPPORTED);
 		goto out; /* No match. */
 	}
-	atomic_inc(&cur_cm_id_priv->refcount);
-	atomic_inc(&cm_id_priv->refcount);
+	refcount_inc(&cur_cm_id_priv->refcount);
+	refcount_inc(&cm_id_priv->refcount);
 	spin_unlock_irq(&cm.lock);
 
 	cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index e7dcfac..4672265 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -43,6 +43,7 @@
 #include <linux/inetdevice.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/refcount.h>
 #include <net/route.h>
 
 #include <net/net_namespace.h>
@@ -195,7 +196,7 @@ struct cma_device {
 	struct list_head	list;
 	struct ib_device	*device;
 	struct completion	comp;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct list_head	id_list;
 	enum ib_gid_type	*default_gid_type;
 };
@@ -243,7 +244,7 @@ enum {
 
 void cma_ref_dev(struct cma_device *cma_dev)
 {
-	atomic_inc(&cma_dev->refcount);
+	refcount_inc(&cma_dev->refcount);
 }
 
 struct cma_device *cma_enum_devices_by_ibdev(cma_device_filter	filter,
@@ -324,7 +325,7 @@ struct rdma_id_private {
 	struct mutex		qp_mutex;
 
 	struct completion	comp;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct mutex		handler_mutex;
 
 	int			backlog;
@@ -498,7 +499,7 @@ static void cma_attach_to_dev(struct rdma_id_private *id_priv,
 
 void cma_deref_dev(struct cma_device *cma_dev)
 {
-	if (atomic_dec_and_test(&cma_dev->refcount))
+	if (refcount_dec_and_test(&cma_dev->refcount))
 		complete(&cma_dev->comp);
 }
 
@@ -757,7 +758,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
 
 static void cma_deref_id(struct rdma_id_private *id_priv)
 {
-	if (atomic_dec_and_test(&id_priv->refcount))
+	if (refcount_dec_and_test(&id_priv->refcount))
 		complete(&id_priv->comp);
 }
 
@@ -781,7 +782,7 @@ struct rdma_cm_id *rdma_create_id(struct net *net,
 	spin_lock_init(&id_priv->lock);
 	mutex_init(&id_priv->qp_mutex);
 	init_completion(&id_priv->comp);
-	atomic_set(&id_priv->refcount, 1);
+	refcount_set(&id_priv->refcount, 1);
 	mutex_init(&id_priv->handler_mutex);
 	INIT_LIST_HEAD(&id_priv->listen_list);
 	INIT_LIST_HEAD(&id_priv->mc_list);
@@ -1966,7 +1967,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 	 * Protect against the user destroying conn_id from another thread
 	 * until we're done accessing it.
 	 */
-	atomic_inc(&conn_id->refcount);
+	refcount_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (ret)
 		goto err3;
@@ -2142,7 +2143,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
 	 * Protect against the user destroying conn_id from another thread
 	 * until we're done accessing it.
 	 */
-	atomic_inc(&conn_id->refcount);
+	refcount_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (ret) {
 		/* User wants to destroy the CM ID */
@@ -2239,7 +2240,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
 
 	_cma_attach_to_dev(dev_id_priv, cma_dev);
 	list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
-	atomic_inc(&id_priv->refcount);
+	refcount_inc(&id_priv->refcount);
 	dev_id_priv->internal_id = 1;
 	dev_id_priv->afonly = id_priv->afonly;
 
@@ -2611,7 +2612,7 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
 	if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_RESOLVED, RDMA_CM_ROUTE_QUERY))
 		return -EINVAL;
 
-	atomic_inc(&id_priv->refcount);
+	refcount_inc(&id_priv->refcount);
 	if (rdma_cap_ib_sa(id->device, id->port_num))
 		ret = cma_resolve_ib_route(id_priv, timeout_ms);
 	else if (rdma_protocol_roce(id->device, id->port_num))
@@ -2844,7 +2845,7 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
 	if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY))
 		return -EINVAL;
 
-	atomic_inc(&id_priv->refcount);
+	refcount_inc(&id_priv->refcount);
 	memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
 	if (cma_any_addr(dst_addr)) {
 		ret = cma_resolve_loopback(id_priv);
@@ -4175,7 +4176,7 @@ static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id
 		INIT_WORK(&work->work, cma_ndev_work_handler);
 		work->id = id_priv;
 		work->event.event = RDMA_CM_EVENT_ADDR_CHANGE;
-		atomic_inc(&id_priv->refcount);
+		refcount_inc(&id_priv->refcount);
 		queue_work(cma_wq, &work->work);
 	}
 
@@ -4240,7 +4241,7 @@ static void cma_add_one(struct ib_device *device)
 	}
 
 	init_completion(&cma_dev->comp);
-	atomic_set(&cma_dev->refcount, 1);
+	refcount_set(&cma_dev->refcount, 1);
 	INIT_LIST_HEAD(&cma_dev->id_list);
 	ib_set_client_data(device, &cma_client, cma_dev);
 
@@ -4289,7 +4290,7 @@ static void cma_process_remove(struct cma_device *cma_dev)
 
 		list_del(&id_priv->listen_list);
 		list_del_init(&id_priv->list);
-		atomic_inc(&id_priv->refcount);
+		refcount_inc(&id_priv->refcount);
 		mutex_unlock(&lock);
 
 		ret = id_priv->internal_id ? 1 : cma_remove_id_dev(id_priv);
diff --git a/drivers/infiniband/core/cq.c b/drivers/infiniband/core/cq.c
index a754fc7..22a48ae 100644
--- a/drivers/infiniband/core/cq.c
+++ b/drivers/infiniband/core/cq.c
@@ -142,7 +142,7 @@ struct ib_cq *ib_alloc_cq(struct ib_device *dev, void *private,
 	cq->event_handler = NULL;
 	cq->cq_context = private;
 	cq->poll_ctx = poll_ctx;
-	atomic_set(&cq->usecnt, 0);
+	refcount_set(&cq->usecnt, 0);
 
 	cq->wc = kmalloc_array(IB_POLL_BATCH, sizeof(*cq->wc), GFP_KERNEL);
 	if (!cq->wc)
@@ -186,7 +186,7 @@ void ib_free_cq(struct ib_cq *cq)
 {
 	int ret;
 
-	if (WARN_ON_ONCE(atomic_read(&cq->usecnt)))
+	if (WARN_ON_ONCE(refcount_read(&cq->usecnt)))
 		return;
 
 	switch (cq->poll_ctx) {
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 31661b5..5c49a7a 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -208,8 +208,8 @@ static void free_cm_id(struct iwcm_id_private *cm_id_priv)
  */
 static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
 {
-	BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
-	if (atomic_dec_and_test(&cm_id_priv->refcount)) {
+	BUG_ON(refcount_read(&cm_id_priv->refcount)==0);
+	if (refcount_dec_and_test(&cm_id_priv->refcount)) {
 		BUG_ON(!list_empty(&cm_id_priv->work_list));
 		free_cm_id(cm_id_priv);
 		return 1;
@@ -222,7 +222,7 @@ static void add_ref(struct iw_cm_id *cm_id)
 {
 	struct iwcm_id_private *cm_id_priv;
 	cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-	atomic_inc(&cm_id_priv->refcount);
+	refcount_inc(&cm_id_priv->refcount);
 }
 
 static void rem_ref(struct iw_cm_id *cm_id)
@@ -254,7 +254,7 @@ struct iw_cm_id *iw_create_cm_id(struct ib_device *device,
 	cm_id_priv->id.add_ref = add_ref;
 	cm_id_priv->id.rem_ref = rem_ref;
 	spin_lock_init(&cm_id_priv->lock);
-	atomic_set(&cm_id_priv->refcount, 1);
+	refcount_set(&cm_id_priv->refcount, 1);
 	init_waitqueue_head(&cm_id_priv->connect_wait);
 	init_completion(&cm_id_priv->destroy_comp);
 	INIT_LIST_HEAD(&cm_id_priv->work_list);
@@ -1081,7 +1081,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id,
 		}
 	}
 
-	atomic_inc(&cm_id_priv->refcount);
+	refcount_inc(&cm_id_priv->refcount);
 	if (list_empty(&cm_id_priv->work_list)) {
 		list_add_tail(&work->list, &cm_id_priv->work_list);
 		queue_work(iwcm_wq, &work->work);
diff --git a/drivers/infiniband/core/iwcm.h b/drivers/infiniband/core/iwcm.h
index 82c2cd1..12fe7da 100644
--- a/drivers/infiniband/core/iwcm.h
+++ b/drivers/infiniband/core/iwcm.h
@@ -33,6 +33,8 @@
 #ifndef IWCM_H
 #define IWCM_H
 
+#include <linux/refcount.h>
+
 enum iw_cm_state {
 	IW_CM_STATE_IDLE,             /* unbound, inactive */
 	IW_CM_STATE_LISTEN,           /* listen waiting for connect */
@@ -52,7 +54,7 @@ struct iwcm_id_private {
 	wait_queue_head_t connect_wait;
 	struct list_head work_list;
 	spinlock_t lock;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct list_head work_free_list;
 };
 
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index 3ef51a9..4961909 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -57,7 +57,7 @@ int iwpm_init(u8 nl_client)
 	if (iwpm_valid_client(nl_client))
 		return -EINVAL;
 	mutex_lock(&iwpm_admin_lock);
-	if (atomic_read(&iwpm_admin.refcount) == 0) {
+	if (refcount_read(&iwpm_admin.refcount) == 0) {
 		iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE *
 					sizeof(struct hlist_head), GFP_KERNEL);
 		if (!iwpm_hash_bucket) {
@@ -72,7 +72,7 @@ int iwpm_init(u8 nl_client)
 			goto init_exit;
 		}
 	}
-	atomic_inc(&iwpm_admin.refcount);
+	refcount_inc(&iwpm_admin.refcount);
 init_exit:
 	mutex_unlock(&iwpm_admin_lock);
 	if (!ret) {
@@ -94,12 +94,12 @@ int iwpm_exit(u8 nl_client)
 	if (!iwpm_valid_client(nl_client))
 		return -EINVAL;
 	mutex_lock(&iwpm_admin_lock);
-	if (atomic_read(&iwpm_admin.refcount) == 0) {
+	if (refcount_read(&iwpm_admin.refcount) == 0) {
 		mutex_unlock(&iwpm_admin_lock);
 		pr_err("%s Incorrect usage - negative refcount\n", __func__);
 		return -EINVAL;
 	}
-	if (atomic_dec_and_test(&iwpm_admin.refcount)) {
+	if (refcount_dec_and_test(&iwpm_admin.refcount)) {
 		free_hash_bucket();
 		free_reminfo_bucket();
 		pr_debug("%s: Resources are destroyed\n", __func__);
diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h
index af1fc14..d7b4ae9 100644
--- a/drivers/infiniband/core/iwpm_util.h
+++ b/drivers/infiniband/core/iwpm_util.h
@@ -45,6 +45,7 @@
 #include <linux/mutex.h>
 #include <linux/jhash.h>
 #include <linux/kref.h>
+#include <linux/refcount.h>
 #include <net/netlink.h>
 #include <linux/errno.h>
 #include <rdma/iw_portmap.h>
@@ -89,7 +90,7 @@ struct iwpm_remote_info {
 };
 
 struct iwpm_admin_data {
-	atomic_t refcount;
+	refcount_t refcount;
 	atomic_t nlmsg_seq;
 	int      client_list[RDMA_NL_NUM_CLIENTS];
 	u32      reg_list[RDMA_NL_NUM_CLIENTS];
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index a009f71..7c34b8e 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -364,7 +364,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
 	INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends);
 	INIT_LIST_HEAD(&mad_agent_priv->local_list);
 	INIT_WORK(&mad_agent_priv->local_work, local_completions);
-	atomic_set(&mad_agent_priv->refcount, 1);
+	refcount_set(&mad_agent_priv->refcount, 1);
 	init_completion(&mad_agent_priv->comp);
 
 	spin_lock_irqsave(&port_priv->reg_lock, flags);
@@ -531,7 +531,7 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
 		goto error2;
 	}
 
-	atomic_set(&mad_snoop_priv->refcount, 1);
+	refcount_set(&mad_snoop_priv->refcount, 1);
 	return &mad_snoop_priv->agent;
 
 error2:
@@ -543,13 +543,13 @@ EXPORT_SYMBOL(ib_register_mad_snoop);
 
 static inline void deref_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
 {
-	if (atomic_dec_and_test(&mad_agent_priv->refcount))
+	if (refcount_dec_and_test(&mad_agent_priv->refcount))
 		complete(&mad_agent_priv->comp);
 }
 
 static inline void deref_snoop_agent(struct ib_mad_snoop_private *mad_snoop_priv)
 {
-	if (atomic_dec_and_test(&mad_snoop_priv->refcount))
+	if (refcount_dec_and_test(&mad_snoop_priv->refcount))
 		complete(&mad_snoop_priv->comp);
 }
 
@@ -653,7 +653,7 @@ static void snoop_send(struct ib_mad_qp_info *qp_info,
 		    !(mad_snoop_priv->mad_snoop_flags & mad_snoop_flags))
 			continue;
 
-		atomic_inc(&mad_snoop_priv->refcount);
+		refcount_inc(&mad_snoop_priv->refcount);
 		spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 		mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,
 						    send_buf, mad_send_wc);
@@ -678,7 +678,7 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info,
 		    !(mad_snoop_priv->mad_snoop_flags & mad_snoop_flags))
 			continue;
 
-		atomic_inc(&mad_snoop_priv->refcount);
+		refcount_inc(&mad_snoop_priv->refcount);
 		spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 		mad_snoop_priv->agent.recv_handler(&mad_snoop_priv->agent, NULL,
 						   mad_recv_wc);
@@ -854,7 +854,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
 			 * Reference MAD agent until receive
 			 * side of local completion handled
 			 */
-			atomic_inc(&mad_agent_priv->refcount);
+			refcount_inc(&mad_agent_priv->refcount);
 		} else
 			kfree(mad_priv);
 		break;
@@ -894,7 +894,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
 		local->return_wc_byte_len = mad_size;
 	}
 	/* Reference MAD agent until send side of local completion handled */
-	atomic_inc(&mad_agent_priv->refcount);
+	refcount_inc(&mad_agent_priv->refcount);
 	/* Queue local completion to local list */
 	spin_lock_irqsave(&mad_agent_priv->lock, flags);
 	list_add_tail(&local->completion_list, &mad_agent_priv->local_list);
@@ -1052,7 +1052,7 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
 	}
 
 	mad_send_wr->send_buf.mad_agent = mad_agent;
-	atomic_inc(&mad_agent_priv->refcount);
+	refcount_inc(&mad_agent_priv->refcount);
 	return &mad_send_wr->send_buf;
 }
 EXPORT_SYMBOL(ib_create_send_mad);
@@ -1263,7 +1263,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
 		mad_send_wr->status = IB_WC_SUCCESS;
 
 		/* Reference MAD agent until send completes */
-		atomic_inc(&mad_agent_priv->refcount);
+		refcount_inc(&mad_agent_priv->refcount);
 		spin_lock_irqsave(&mad_agent_priv->lock, flags);
 		list_add_tail(&mad_send_wr->agent_list,
 			      &mad_agent_priv->send_list);
@@ -1280,7 +1280,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
 			spin_lock_irqsave(&mad_agent_priv->lock, flags);
 			list_del(&mad_send_wr->agent_list);
 			spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
-			atomic_dec(&mad_agent_priv->refcount);
+			refcount_dec(&mad_agent_priv->refcount);
 			goto error;
 		}
 	}
@@ -1759,7 +1759,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
 
 	if (mad_agent) {
 		if (mad_agent->agent.recv_handler)
-			atomic_inc(&mad_agent->refcount);
+			refcount_inc(&mad_agent->refcount);
 		else {
 			dev_notice(&port_priv->device->dev,
 				   "No receive handler for client %p on port %d\n",
@@ -1968,7 +1968,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 				mad_agent_priv->agent.recv_handler(
 						&mad_agent_priv->agent, NULL,
 						mad_recv_wc);
-				atomic_dec(&mad_agent_priv->refcount);
+				refcount_dec(&mad_agent_priv->refcount);
 			} else {
 				/* not user rmpp, revert to normal behavior and
 				 * drop the mad */
@@ -1985,7 +1985,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 					&mad_agent_priv->agent,
 					&mad_send_wr->send_buf,
 					mad_recv_wc);
-			atomic_dec(&mad_agent_priv->refcount);
+			refcount_dec(&mad_agent_priv->refcount);
 
 			mad_send_wc.status = IB_WC_SUCCESS;
 			mad_send_wc.vendor_err = 0;
@@ -2571,7 +2571,7 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
 		list_del(&mad_send_wr->agent_list);
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   &mad_send_wc);
-		atomic_dec(&mad_agent_priv->refcount);
+		refcount_dec(&mad_agent_priv->refcount);
 	}
 }
 
@@ -2709,7 +2709,7 @@ static void local_completions(struct work_struct *work)
 						&local->mad_send_wr->send_buf,
 						&local->mad_priv->header.recv_wc);
 			spin_lock_irqsave(&recv_mad_agent->lock, flags);
-			atomic_dec(&recv_mad_agent->refcount);
+			refcount_dec(&recv_mad_agent->refcount);
 			spin_unlock_irqrestore(&recv_mad_agent->lock, flags);
 		}
 
@@ -2726,7 +2726,7 @@ static void local_completions(struct work_struct *work)
 						   &mad_send_wc);
 
 		spin_lock_irqsave(&mad_agent_priv->lock, flags);
-		atomic_dec(&mad_agent_priv->refcount);
+		refcount_dec(&mad_agent_priv->refcount);
 		if (free_mad)
 			kfree(local->mad_priv);
 		kfree(local);
@@ -2812,7 +2812,7 @@ static void timeout_sends(struct work_struct *work)
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   &mad_send_wc);
 
-		atomic_dec(&mad_agent_priv->refcount);
+		refcount_dec(&mad_agent_priv->refcount);
 		spin_lock_irqsave(&mad_agent_priv->lock, flags);
 	}
 	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 28669f6..f4e75ab 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -38,6 +38,7 @@
 
 #include <linux/completion.h>
 #include <linux/err.h>
+#include <linux/refcount.h>
 #include <linux/workqueue.h>
 #include <rdma/ib_mad.h>
 #include <rdma/ib_smi.h>
@@ -104,7 +105,7 @@ struct ib_mad_agent_private {
 	struct work_struct local_work;
 	struct list_head rmpp_list;
 
-	atomic_t refcount;
+	refcount_t refcount;
 	struct completion comp;
 };
 
@@ -113,7 +114,7 @@ struct ib_mad_snoop_private {
 	struct ib_mad_qp_info *qp_info;
 	int snoop_index;
 	int mad_snoop_flags;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct completion comp;
 };
 
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index 382941b..db96133 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -33,6 +33,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 #include "mad_priv.h"
 #include "mad_rmpp.h"
@@ -52,7 +53,7 @@ struct mad_rmpp_recv {
 	struct completion comp;
 	enum rmpp_state state;
 	spinlock_t lock;
-	atomic_t refcount;
+	refcount_t refcount;
 
 	struct ib_ah *ah;
 	struct ib_mad_recv_wc *rmpp_wc;
@@ -73,7 +74,7 @@ struct mad_rmpp_recv {
 
 static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
 {
-	if (atomic_dec_and_test(&rmpp_recv->refcount))
+	if (refcount_dec_and_test(&rmpp_recv->refcount))
 		complete(&rmpp_recv->comp);
 }
 
@@ -304,7 +305,7 @@ create_rmpp_recv(struct ib_mad_agent_private *agent,
 	INIT_DELAYED_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler);
 	spin_lock_init(&rmpp_recv->lock);
 	rmpp_recv->state = RMPP_STATE_ACTIVE;
-	atomic_set(&rmpp_recv->refcount, 1);
+	refcount_set(&rmpp_recv->refcount, 1);
 
 	rmpp_recv->rmpp_wc = mad_recv_wc;
 	rmpp_recv->cur_seg_buf = &mad_recv_wc->recv_buf;
@@ -356,7 +357,7 @@ acquire_rmpp_recv(struct ib_mad_agent_private *agent,
 	spin_lock_irqsave(&agent->lock, flags);
 	rmpp_recv = find_rmpp_recv(agent, mad_recv_wc);
 	if (rmpp_recv)
-		atomic_inc(&rmpp_recv->refcount);
+		refcount_inc(&rmpp_recv->refcount);
 	spin_unlock_irqrestore(&agent->lock, flags);
 	return rmpp_recv;
 }
@@ -552,7 +553,7 @@ start_rmpp(struct ib_mad_agent_private *agent,
 		destroy_rmpp_recv(rmpp_recv);
 		return continue_rmpp(agent, mad_recv_wc);
 	}
-	atomic_inc(&rmpp_recv->refcount);
+	refcount_inc(&rmpp_recv->refcount);
 
 	if (get_last_flag(&mad_recv_wc->recv_buf)) {
 		rmpp_recv->state = RMPP_STATE_COMPLETE;
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index 322cb67..9096ace 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/random.h>
+#include <linux/refcount.h>
 
 #include <rdma/ib_cache.h>
 #include "sa.h"
@@ -61,7 +62,7 @@ struct mcast_port {
 	struct mcast_device	*dev;
 	spinlock_t		lock;
 	struct rb_root		table;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	comp;
 	u8			port_num;
 };
@@ -103,7 +104,7 @@ struct mcast_group {
 	struct list_head	active_list;
 	struct mcast_member	*last_join;
 	int			members[NUM_JOIN_MEMBERSHIP_TYPES];
-	atomic_t		refcount;
+	refcount_t		refcount;
 	enum mcast_group_state	state;
 	struct ib_sa_query	*query;
 	u16			pkey_index;
@@ -117,7 +118,7 @@ struct mcast_member {
 	struct mcast_group	*group;
 	struct list_head	list;
 	enum mcast_state	state;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	comp;
 };
 
@@ -178,7 +179,7 @@ static struct mcast_group *mcast_insert(struct mcast_port *port,
 
 static void deref_port(struct mcast_port *port)
 {
-	if (atomic_dec_and_test(&port->refcount))
+	if (refcount_dec_and_test(&port->refcount))
 		complete(&port->comp);
 }
 
@@ -188,7 +189,7 @@ static void release_group(struct mcast_group *group)
 	unsigned long flags;
 
 	spin_lock_irqsave(&port->lock, flags);
-	if (atomic_dec_and_test(&group->refcount)) {
+	if (refcount_dec_and_test(&group->refcount)) {
 		rb_erase(&group->node, &port->table);
 		spin_unlock_irqrestore(&port->lock, flags);
 		kfree(group);
@@ -199,7 +200,7 @@ static void release_group(struct mcast_group *group)
 
 static void deref_member(struct mcast_member *member)
 {
-	if (atomic_dec_and_test(&member->refcount))
+	if (refcount_dec_and_test(&member->refcount))
 		complete(&member->comp);
 }
 
@@ -212,7 +213,7 @@ static void queue_join(struct mcast_member *member)
 	list_add_tail(&member->list, &group->pending_list);
 	if (group->state == MCAST_IDLE) {
 		group->state = MCAST_BUSY;
-		atomic_inc(&group->refcount);
+		refcount_inc(&group->refcount);
 		queue_work(mcast_wq, &group->work);
 	}
 	spin_unlock_irqrestore(&group->lock, flags);
@@ -401,7 +402,7 @@ static void process_group_error(struct mcast_group *group)
 	while (!list_empty(&group->active_list)) {
 		member = list_entry(group->active_list.next,
 				    struct mcast_member, list);
-		atomic_inc(&member->refcount);
+		refcount_inc(&member->refcount);
 		list_del_init(&member->list);
 		adjust_membership(group, member->multicast.rec.join_state, -1);
 		member->state = MCAST_ERROR;
@@ -445,7 +446,7 @@ static void mcast_work_handler(struct work_struct *work)
 				    struct mcast_member, list);
 		multicast = &member->multicast;
 		join_state = multicast->rec.join_state;
-		atomic_inc(&member->refcount);
+		refcount_inc(&member->refcount);
 
 		if (join_state == (group->rec.join_state & join_state)) {
 			status = cmp_rec(&group->rec, &multicast->rec,
@@ -497,7 +498,7 @@ static void process_join_error(struct mcast_group *group, int status)
 	member = list_entry(group->pending_list.next,
 			    struct mcast_member, list);
 	if (group->last_join == member) {
-		atomic_inc(&member->refcount);
+		refcount_inc(&member->refcount);
 		list_del_init(&member->list);
 		spin_unlock_irq(&group->lock);
 		ret = member->multicast.callback(status, &member->multicast);
@@ -589,9 +590,9 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
 		kfree(group);
 		group = cur_group;
 	} else
-		atomic_inc(&port->refcount);
+		refcount_inc(&port->refcount);
 found:
-	atomic_inc(&group->refcount);
+	refcount_inc(&group->refcount);
 	spin_unlock_irqrestore(&port->lock, flags);
 	return group;
 }
@@ -632,7 +633,7 @@ ib_sa_join_multicast(struct ib_sa_client *client,
 	member->multicast.callback = callback;
 	member->multicast.context = context;
 	init_completion(&member->comp);
-	atomic_set(&member->refcount, 1);
+	refcount_set(&member->refcount, 1);
 	member->state = MCAST_JOINING;
 
 	member->group = acquire_group(&dev->port[port_num - dev->start_port],
@@ -772,7 +773,7 @@ static void mcast_groups_event(struct mcast_port *port,
 		group = rb_entry(node, struct mcast_group, node);
 		spin_lock(&group->lock);
 		if (group->state == MCAST_IDLE) {
-			atomic_inc(&group->refcount);
+			refcount_inc(&group->refcount);
 			queue_work(mcast_wq, &group->work);
 		}
 		if (group->state != MCAST_GROUP_ERROR)
@@ -833,7 +834,7 @@ static void mcast_add_one(struct ib_device *device)
 		spin_lock_init(&port->lock);
 		port->table = RB_ROOT;
 		init_completion(&port->comp);
-		atomic_set(&port->refcount, 1);
+		refcount_set(&port->refcount, 1);
 		++count;
 	}
 
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 455034a..19dc476 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -85,7 +85,7 @@
  */
 
 struct ib_uverbs_device {
-	atomic_t				refcount;
+	refcount_t				refcount;
 	int					num_comp_vectors;
 	struct completion			comp;
 	struct device			       *dev;
@@ -149,7 +149,7 @@ struct ib_uevent_object {
 
 struct ib_uxrcd_object {
 	struct ib_uobject	uobject;
-	atomic_t		refcnt;
+	refcount_t		refcnt;
 };
 
 struct ib_usrq_object {
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 7007822..f088fb4 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -572,7 +572,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
 	pd->device  = ib_dev;
 	pd->uobject = uobj;
 	pd->__internal_mr = NULL;
-	atomic_set(&pd->usecnt, 0);
+	refcount_set(&pd->usecnt, 0);
 
 	uobj->object = pd;
 	ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj);
@@ -627,7 +627,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
 		return -EINVAL;
 	pd = uobj->object;
 
-	if (atomic_read(&pd->usecnt)) {
+	if (refcount_read(&pd->usecnt)) {
 		ret = -EBUSY;
 		goto err_put;
 	}
@@ -808,13 +808,13 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
 
 		xrcd->inode   = inode;
 		xrcd->device  = ib_dev;
-		atomic_set(&xrcd->usecnt, 0);
+		refcount_set(&xrcd->usecnt, 0);
 		mutex_init(&xrcd->tgt_qp_mutex);
 		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
 		new_xrcd = 1;
 	}
 
-	atomic_set(&obj->refcnt, 0);
+	refcount_set(&obj->refcnt, 0);
 	obj->uobject.object = xrcd;
 	ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
 	if (ret)
@@ -830,7 +830,7 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
 			if (ret)
 				goto err_insert_xrcd;
 		}
-		atomic_inc(&xrcd->usecnt);
+		refcount_inc(&xrcd->usecnt);
 	}
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -856,7 +856,7 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
 	if (inode) {
 		if (new_xrcd)
 			xrcd_table_delete(file->device, inode);
-		atomic_dec(&xrcd->usecnt);
+		refcount_dec(&xrcd->usecnt);
 	}
 
 err_insert_xrcd:
@@ -903,13 +903,13 @@ ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
 	xrcd  = uobj->object;
 	inode = xrcd->inode;
 	obj   = container_of(uobj, struct ib_uxrcd_object, uobject);
-	if (atomic_read(&obj->refcnt)) {
+	if (refcount_read(&obj->refcnt)) {
 		put_uobj_write(uobj);
 		ret = -EBUSY;
 		goto out;
 	}
 
-	if (!inode || atomic_dec_and_test(&xrcd->usecnt)) {
+	if (!inode || refcount_dec_and_test(&xrcd->usecnt)) {
 		ret = ib_dealloc_xrcd(uobj->object);
 		if (!ret)
 			uobj->live = 0;
@@ -917,7 +917,7 @@ ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
 
 	live = uobj->live;
 	if (inode && ret)
-		atomic_inc(&xrcd->usecnt);
+		refcount_inc(&xrcd->usecnt);
 
 	put_uobj_write(uobj);
 
@@ -946,7 +946,7 @@ void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
 	struct inode *inode;
 
 	inode = xrcd->inode;
-	if (inode && !atomic_dec_and_test(&xrcd->usecnt))
+	if (inode && !refcount_dec_and_test(&xrcd->usecnt))
 		return;
 
 	ib_dealloc_xrcd(xrcd);
@@ -1017,7 +1017,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
 	mr->device  = pd->device;
 	mr->pd      = pd;
 	mr->uobject = uobj;
-	atomic_inc(&pd->usecnt);
+	refcount_inc(&pd->usecnt);
 
 	uobj->object = mr;
 	ret = idr_add_uobj(&ib_uverbs_mr_idr, uobj);
@@ -1121,9 +1121,9 @@ ssize_t ib_uverbs_rereg_mr(struct ib_uverbs_file *file,
 					cmd.access_flags, pd, &udata);
 	if (!ret) {
 		if (cmd.flags & IB_MR_REREG_PD) {
-			atomic_inc(&pd->usecnt);
+			refcount_inc(&pd->usecnt);
 			mr->pd = pd;
-			atomic_dec(&old_pd->usecnt);
+			refcount_dec(&old_pd->usecnt);
 		}
 	} else {
 		goto put_uobj_pd;
@@ -1235,7 +1235,7 @@ ssize_t ib_uverbs_alloc_mw(struct ib_uverbs_file *file,
 	mw->device  = pd->device;
 	mw->pd      = pd;
 	mw->uobject = uobj;
-	atomic_inc(&pd->usecnt);
+	refcount_inc(&pd->usecnt);
 
 	uobj->object = mw;
 	ret = idr_add_uobj(&ib_uverbs_mw_idr, uobj);
@@ -1417,7 +1417,7 @@ static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file,
 	cq->comp_handler  = ib_uverbs_comp_handler;
 	cq->event_handler = ib_uverbs_cq_event_handler;
 	cq->cq_context    = ev_file;
-	atomic_set(&cq->usecnt, 0);
+	refcount_set(&cq->usecnt, 0);
 
 	obj->uobject.object = cq;
 	ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject);
@@ -1925,16 +1925,16 @@ static int create_qp(struct ib_uverbs_file *file,
 		qp->event_handler = attr.event_handler;
 		qp->qp_context	  = attr.qp_context;
 		qp->qp_type	  = attr.qp_type;
-		atomic_set(&qp->usecnt, 0);
-		atomic_inc(&pd->usecnt);
+		refcount_set(&qp->usecnt, 0);
+		refcount_inc(&pd->usecnt);
 		if (attr.send_cq)
-			atomic_inc(&attr.send_cq->usecnt);
+			refcount_inc(&attr.send_cq->usecnt);
 		if (attr.recv_cq)
-			atomic_inc(&attr.recv_cq->usecnt);
+			refcount_inc(&attr.recv_cq->usecnt);
 		if (attr.srq)
-			atomic_inc(&attr.srq->usecnt);
+			refcount_inc(&attr.srq->usecnt);
 		if (ind_tbl)
-			atomic_inc(&ind_tbl->usecnt);
+			refcount_inc(&ind_tbl->usecnt);
 	}
 	qp->uobject = &obj->uevent.uobject;
 
@@ -1962,7 +1962,7 @@ static int create_qp(struct ib_uverbs_file *file,
 	if (xrcd) {
 		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
 					  uobject);
-		atomic_inc(&obj->uxrcd->refcnt);
+		refcount_inc(&obj->uxrcd->refcnt);
 		put_xrcd_read(xrcd_uobj);
 	}
 
@@ -2188,7 +2188,7 @@ ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
 	}
 
 	obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
-	atomic_inc(&obj->uxrcd->refcnt);
+	refcount_inc(&obj->uxrcd->refcnt);
 	put_xrcd_read(xrcd_uobj);
 
 	mutex_lock(&file->mutex);
@@ -2519,7 +2519,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
 		return ret;
 
 	if (obj->uxrcd)
-		atomic_dec(&obj->uxrcd->refcnt);
+		refcount_dec(&obj->uxrcd->refcnt);
 
 	idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
 
@@ -2978,7 +2978,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
 
 	ah->device  = pd->device;
 	ah->pd      = pd;
-	atomic_inc(&pd->usecnt);
+	refcount_inc(&pd->usecnt);
 	ah->uobject  = uobj;
 	uobj->object = ah;
 
@@ -3340,9 +3340,9 @@ int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file,
 	wq->pd = pd;
 	wq->device = pd->device;
 	wq->wq_context = wq_init_attr.wq_context;
-	atomic_set(&wq->usecnt, 0);
-	atomic_inc(&pd->usecnt);
-	atomic_inc(&cq->usecnt);
+	refcount_set(&wq->usecnt, 0);
+	refcount_inc(&pd->usecnt);
+	refcount_inc(&cq->usecnt);
 	wq->uobject = &obj->uevent.uobject;
 	obj->uevent.uobject.object = wq;
 	err = idr_add_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject);
@@ -3599,10 +3599,10 @@ int ib_uverbs_ex_create_rwq_ind_table(struct ib_uverbs_file *file,
 	rwq_ind_tbl->uobject = uobj;
 	uobj->object = rwq_ind_tbl;
 	rwq_ind_tbl->device = ib_dev;
-	atomic_set(&rwq_ind_tbl->usecnt, 0);
+	refcount_set(&rwq_ind_tbl->usecnt, 0);
 
 	for (i = 0; i < num_wq_handles; i++)
-		atomic_inc(&wqs[i]->usecnt);
+		refcount_inc(&wqs[i]->usecnt);
 
 	err = idr_add_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
 	if (err)
@@ -3941,7 +3941,7 @@ static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
 		}
 
 		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
-		atomic_inc(&obj->uxrcd->refcnt);
+		refcount_inc(&obj->uxrcd->refcnt);
 
 		attr.ext.xrc.cq  = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
 		if (!attr.ext.xrc.cq) {
@@ -3982,12 +3982,12 @@ static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
 	if (cmd->srq_type == IB_SRQT_XRC) {
 		srq->ext.xrc.cq   = attr.ext.xrc.cq;
 		srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
-		atomic_inc(&attr.ext.xrc.cq->usecnt);
-		atomic_inc(&attr.ext.xrc.xrcd->usecnt);
+		refcount_inc(&attr.ext.xrc.cq->usecnt);
+		refcount_inc(&attr.ext.xrc.xrcd->usecnt);
 	}
 
-	atomic_inc(&pd->usecnt);
-	atomic_set(&srq->usecnt, 0);
+	refcount_inc(&pd->usecnt);
+	refcount_set(&srq->usecnt, 0);
 
 	obj->uevent.uobject.object = srq;
 	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
@@ -4038,7 +4038,7 @@ static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
 
 err_put_xrcd:
 	if (cmd->srq_type == IB_SRQT_XRC) {
-		atomic_dec(&obj->uxrcd->refcnt);
+		refcount_dec(&obj->uxrcd->refcnt);
 		put_uobj_read(xrcd_uobj);
 	}
 
@@ -4218,7 +4218,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
 
 	if (srq_type == IB_SRQT_XRC) {
 		us = container_of(obj, struct ib_usrq_object, uevent);
-		atomic_dec(&us->uxrcd->refcnt);
+		refcount_dec(&us->uxrcd->refcnt);
 	}
 
 	idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index b3f95d4..1863eab 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -150,7 +150,7 @@ int uverbs_dealloc_mw(struct ib_mw *mw)
 
 	ret = mw->device->dealloc_mw(mw);
 	if (!ret)
-		atomic_dec(&pd->usecnt);
+		refcount_dec(&pd->usecnt);
 	return ret;
 }
 
@@ -366,7 +366,7 @@ static void ib_uverbs_release_file(struct kref *ref)
 		module_put(ib_dev->owner);
 	srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
 
-	if (atomic_dec_and_test(&file->device->refcount))
+	if (refcount_dec_and_test(&file->device->refcount))
 		ib_uverbs_comp_dev(file->device);
 
 	kfree(file);
@@ -932,7 +932,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
 	int srcu_key;
 
 	dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
-	if (!atomic_inc_not_zero(&dev->refcount))
+	if (!refcount_inc_not_zero(&dev->refcount))
 		return -ENXIO;
 
 	srcu_key = srcu_read_lock(&dev->disassociate_srcu);
@@ -986,7 +986,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
 err:
 	mutex_unlock(&dev->lists_mutex);
 	srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
-	if (atomic_dec_and_test(&dev->refcount))
+	if (refcount_dec_and_test(&dev->refcount))
 		ib_uverbs_comp_dev(dev);
 
 	return ret;
@@ -1135,7 +1135,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
 		return;
 	}
 
-	atomic_set(&uverbs_dev->refcount, 1);
+	refcount_set(&uverbs_dev->refcount, 1);
 	init_completion(&uverbs_dev->comp);
 	uverbs_dev->xrcd_tree = RB_ROOT;
 	mutex_init(&uverbs_dev->xrcd_tree_mutex);
@@ -1200,7 +1200,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
 		clear_bit(devnum, overflow_map);
 
 err:
-	if (atomic_dec_and_test(&uverbs_dev->refcount))
+	if (refcount_dec_and_test(&uverbs_dev->refcount))
 		ib_uverbs_comp_dev(uverbs_dev);
 	wait_for_completion(&uverbs_dev->comp);
 	kobject_put(&uverbs_dev->kobj);
@@ -1311,7 +1311,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
 		wait_clients = 0;
 	}
 
-	if (atomic_dec_and_test(&uverbs_dev->refcount))
+	if (refcount_dec_and_test(&uverbs_dev->refcount))
 		ib_uverbs_comp_dev(uverbs_dev);
 	if (wait_clients)
 		wait_for_completion(&uverbs_dev->comp);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 71580cc..11e0cf0 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -240,7 +240,7 @@ struct ib_pd *__ib_alloc_pd(struct ib_device *device, unsigned int flags,
 	pd->device = device;
 	pd->uobject = NULL;
 	pd->__internal_mr = NULL;
-	atomic_set(&pd->usecnt, 0);
+	refcount_set(&pd->usecnt, 0);
 	pd->flags = flags;
 
 	if (device->attrs.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)
@@ -300,7 +300,7 @@ void ib_dealloc_pd(struct ib_pd *pd)
 
 	/* uverbs manipulates usecnt with proper locking, while the kabi
 	   requires the caller to guarantee we can't race here. */
-	WARN_ON(atomic_read(&pd->usecnt));
+	WARN_ON(refcount_read(&pd->usecnt));
 
 	/* Making delalloc_pd a void return is a WIP, no driver should return
 	   an error here. */
@@ -321,7 +321,7 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
 		ah->device  = pd->device;
 		ah->pd      = pd;
 		ah->uobject = NULL;
-		atomic_inc(&pd->usecnt);
+		refcount_inc(&pd->usecnt);
 	}
 
 	return ah;
@@ -595,7 +595,7 @@ int ib_destroy_ah(struct ib_ah *ah)
 	pd = ah->pd;
 	ret = ah->device->destroy_ah(ah);
 	if (!ret)
-		atomic_dec(&pd->usecnt);
+		refcount_dec(&pd->usecnt);
 
 	return ret;
 }
@@ -623,11 +623,11 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd,
 		if (srq->srq_type == IB_SRQT_XRC) {
 			srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
 			srq->ext.xrc.cq   = srq_init_attr->ext.xrc.cq;
-			atomic_inc(&srq->ext.xrc.xrcd->usecnt);
-			atomic_inc(&srq->ext.xrc.cq->usecnt);
+			refcount_inc(&srq->ext.xrc.xrcd->usecnt);
+			refcount_inc(&srq->ext.xrc.cq->usecnt);
 		}
-		atomic_inc(&pd->usecnt);
-		atomic_set(&srq->usecnt, 0);
+		refcount_inc(&pd->usecnt);
+		refcount_set(&srq->usecnt, 0);
 	}
 
 	return srq;
@@ -660,7 +660,7 @@ int ib_destroy_srq(struct ib_srq *srq)
 	struct ib_cq *uninitialized_var(cq);
 	int ret;
 
-	if (atomic_read(&srq->usecnt))
+	if (refcount_read(&srq->usecnt))
 		return -EBUSY;
 
 	pd = srq->pd;
@@ -672,10 +672,10 @@ int ib_destroy_srq(struct ib_srq *srq)
 
 	ret = srq->device->destroy_srq(srq);
 	if (!ret) {
-		atomic_dec(&pd->usecnt);
+		refcount_dec(&pd->usecnt);
 		if (srq_type == IB_SRQT_XRC) {
-			atomic_dec(&xrcd->usecnt);
-			atomic_dec(&cq->usecnt);
+			refcount_dec(&xrcd->usecnt);
+			refcount_dec(&cq->usecnt);
 		}
 	}
 
@@ -716,7 +716,7 @@ static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
 		return ERR_PTR(-ENOMEM);
 
 	qp->real_qp = real_qp;
-	atomic_inc(&real_qp->usecnt);
+	refcount_inc(&real_qp->usecnt);
 	qp->device = real_qp->device;
 	qp->event_handler = event_handler;
 	qp->qp_context = qp_context;
@@ -763,7 +763,7 @@ static struct ib_qp *ib_create_xrc_qp(struct ib_qp *qp,
 	qp->send_cq = qp->recv_cq = NULL;
 	qp->srq = NULL;
 	qp->xrcd = qp_init_attr->xrcd;
-	atomic_inc(&qp_init_attr->xrcd->usecnt);
+	refcount_inc(&qp_init_attr->xrcd->usecnt);
 	INIT_LIST_HEAD(&qp->open_list);
 
 	qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
@@ -807,7 +807,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
 	qp->qp_type    = qp_init_attr->qp_type;
 	qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl;
 
-	atomic_set(&qp->usecnt, 0);
+	refcount_set(&qp->usecnt, 0);
 	qp->mrs_used = 0;
 	spin_lock_init(&qp->mr_lock);
 	INIT_LIST_HEAD(&qp->rdma_mrs);
@@ -824,21 +824,21 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
 	} else {
 		qp->recv_cq = qp_init_attr->recv_cq;
 		if (qp_init_attr->recv_cq)
-			atomic_inc(&qp_init_attr->recv_cq->usecnt);
+			refcount_inc(&qp_init_attr->recv_cq->usecnt);
 		qp->srq = qp_init_attr->srq;
 		if (qp->srq)
-			atomic_inc(&qp_init_attr->srq->usecnt);
+			refcount_inc(&qp_init_attr->srq->usecnt);
 	}
 
 	qp->pd	    = pd;
 	qp->send_cq = qp_init_attr->send_cq;
 	qp->xrcd    = NULL;
 
-	atomic_inc(&pd->usecnt);
+	refcount_inc(&pd->usecnt);
 	if (qp_init_attr->send_cq)
-		atomic_inc(&qp_init_attr->send_cq->usecnt);
+		refcount_inc(&qp_init_attr->send_cq->usecnt);
 	if (qp_init_attr->rwq_ind_tbl)
-		atomic_inc(&qp->rwq_ind_tbl->usecnt);
+		refcount_inc(&qp->rwq_ind_tbl->usecnt);
 
 	if (qp_init_attr->cap.max_rdma_ctxs) {
 		ret = rdma_rw_init_mrs(qp, qp_init_attr);
@@ -1289,7 +1289,7 @@ int ib_close_qp(struct ib_qp *qp)
 	list_del(&qp->open_list);
 	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
 
-	atomic_dec(&real_qp->usecnt);
+	refcount_dec(&real_qp->usecnt);
 	kfree(qp);
 
 	return 0;
@@ -1307,7 +1307,7 @@ static int __ib_destroy_shared_qp(struct ib_qp *qp)
 
 	mutex_lock(&xrcd->tgt_qp_mutex);
 	ib_close_qp(qp);
-	if (atomic_read(&real_qp->usecnt) == 0)
+	if (refcount_read(&real_qp->usecnt) == 0)
 		list_del(&real_qp->xrcd_list);
 	else
 		real_qp = NULL;
@@ -1316,7 +1316,7 @@ static int __ib_destroy_shared_qp(struct ib_qp *qp)
 	if (real_qp) {
 		ret = ib_destroy_qp(real_qp);
 		if (!ret)
-			atomic_dec(&xrcd->usecnt);
+			refcount_dec(&xrcd->usecnt);
 		else
 			__ib_insert_xrcd_qp(xrcd, real_qp);
 	}
@@ -1334,7 +1334,7 @@ int ib_destroy_qp(struct ib_qp *qp)
 
 	WARN_ON_ONCE(qp->mrs_used > 0);
 
-	if (atomic_read(&qp->usecnt))
+	if (refcount_read(&qp->usecnt))
 		return -EBUSY;
 
 	if (qp->real_qp != qp)
@@ -1352,15 +1352,15 @@ int ib_destroy_qp(struct ib_qp *qp)
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
 		if (pd)
-			atomic_dec(&pd->usecnt);
+			refcount_dec(&pd->usecnt);
 		if (scq)
-			atomic_dec(&scq->usecnt);
+			refcount_dec(&scq->usecnt);
 		if (rcq)
-			atomic_dec(&rcq->usecnt);
+			refcount_dec(&rcq->usecnt);
 		if (srq)
-			atomic_dec(&srq->usecnt);
+			refcount_dec(&srq->usecnt);
 		if (ind_tbl)
-			atomic_dec(&ind_tbl->usecnt);
+			refcount_dec(&ind_tbl->usecnt);
 	}
 
 	return ret;
@@ -1385,7 +1385,7 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
 		cq->comp_handler  = comp_handler;
 		cq->event_handler = event_handler;
 		cq->cq_context    = cq_context;
-		atomic_set(&cq->usecnt, 0);
+		refcount_set(&cq->usecnt, 0);
 	}
 
 	return cq;
@@ -1401,7 +1401,7 @@ EXPORT_SYMBOL(ib_modify_cq);
 
 int ib_destroy_cq(struct ib_cq *cq)
 {
-	if (atomic_read(&cq->usecnt))
+	if (refcount_read(&cq->usecnt))
 		return -EBUSY;
 
 	return cq->device->destroy_cq(cq);
@@ -1424,7 +1424,7 @@ int ib_dereg_mr(struct ib_mr *mr)
 
 	ret = mr->device->dereg_mr(mr);
 	if (!ret)
-		atomic_dec(&pd->usecnt);
+		refcount_dec(&pd->usecnt);
 
 	return ret;
 }
@@ -1456,7 +1456,7 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *pd,
 		mr->device  = pd->device;
 		mr->pd      = pd;
 		mr->uobject = NULL;
-		atomic_inc(&pd->usecnt);
+		refcount_inc(&pd->usecnt);
 		mr->need_inval = false;
 	}
 
@@ -1479,7 +1479,7 @@ struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd,
 	if (!IS_ERR(fmr)) {
 		fmr->device = pd->device;
 		fmr->pd     = pd;
-		atomic_inc(&pd->usecnt);
+		refcount_inc(&pd->usecnt);
 	}
 
 	return fmr;
@@ -1506,7 +1506,7 @@ int ib_dealloc_fmr(struct ib_fmr *fmr)
 	pd = fmr->pd;
 	ret = fmr->device->dealloc_fmr(fmr);
 	if (!ret)
-		atomic_dec(&pd->usecnt);
+		refcount_dec(&pd->usecnt);
 
 	return ret;
 }
@@ -1525,7 +1525,7 @@ int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 
 	ret = qp->device->attach_mcast(qp, gid, lid);
 	if (!ret)
-		atomic_inc(&qp->usecnt);
+		refcount_inc(&qp->usecnt);
 	return ret;
 }
 EXPORT_SYMBOL(ib_attach_mcast);
@@ -1541,7 +1541,7 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 
 	ret = qp->device->detach_mcast(qp, gid, lid);
 	if (!ret)
-		atomic_dec(&qp->usecnt);
+		refcount_dec(&qp->usecnt);
 	return ret;
 }
 EXPORT_SYMBOL(ib_detach_mcast);
@@ -1557,7 +1557,7 @@ struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device)
 	if (!IS_ERR(xrcd)) {
 		xrcd->device = device;
 		xrcd->inode = NULL;
-		atomic_set(&xrcd->usecnt, 0);
+		refcount_set(&xrcd->usecnt, 0);
 		mutex_init(&xrcd->tgt_qp_mutex);
 		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
 	}
@@ -1571,7 +1571,7 @@ int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
 	struct ib_qp *qp;
 	int ret;
 
-	if (atomic_read(&xrcd->usecnt))
+	if (refcount_read(&xrcd->usecnt))
 		return -EBUSY;
 
 	while (!list_empty(&xrcd->tgt_qp_list)) {
@@ -1616,9 +1616,9 @@ struct ib_wq *ib_create_wq(struct ib_pd *pd,
 		wq->device = pd->device;
 		wq->pd = pd;
 		wq->uobject = NULL;
-		atomic_inc(&pd->usecnt);
-		atomic_inc(&wq_attr->cq->usecnt);
-		atomic_set(&wq->usecnt, 0);
+		refcount_inc(&pd->usecnt);
+		refcount_inc(&wq_attr->cq->usecnt);
+		refcount_set(&wq->usecnt, 0);
 	}
 	return wq;
 }
@@ -1634,13 +1634,13 @@ int ib_destroy_wq(struct ib_wq *wq)
 	struct ib_cq *cq = wq->cq;
 	struct ib_pd *pd = wq->pd;
 
-	if (atomic_read(&wq->usecnt))
+	if (refcount_read(&wq->usecnt))
 		return -EBUSY;
 
 	err = wq->device->destroy_wq(wq);
 	if (!err) {
-		atomic_dec(&pd->usecnt);
-		atomic_dec(&cq->usecnt);
+		refcount_dec(&pd->usecnt);
+		refcount_dec(&cq->usecnt);
 	}
 	return err;
 }
@@ -1697,10 +1697,10 @@ struct ib_rwq_ind_table *ib_create_rwq_ind_table(struct ib_device *device,
 	rwq_ind_table->log_ind_tbl_size = init_attr->log_ind_tbl_size;
 	rwq_ind_table->device = device;
 	rwq_ind_table->uobject = NULL;
-	atomic_set(&rwq_ind_table->usecnt, 0);
+	refcount_set(&rwq_ind_table->usecnt, 0);
 
 	for (i = 0; i < table_size; i++)
-		atomic_inc(&rwq_ind_table->ind_tbl[i]->usecnt);
+		refcount_inc(&rwq_ind_table->ind_tbl[i]->usecnt);
 
 	return rwq_ind_table;
 }
@@ -1716,13 +1716,13 @@ int ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *rwq_ind_table)
 	u32 table_size = (1 << rwq_ind_table->log_ind_tbl_size);
 	struct ib_wq **ind_tbl = rwq_ind_table->ind_tbl;
 
-	if (atomic_read(&rwq_ind_table->usecnt))
+	if (refcount_read(&rwq_ind_table->usecnt))
 		return -EBUSY;
 
 	err = rwq_ind_table->device->destroy_rwq_ind_table(rwq_ind_table);
 	if (!err) {
 		for (i = 0; i < table_size; i++)
-			atomic_dec(&ind_tbl[i]->usecnt);
+			refcount_dec(&ind_tbl[i]->usecnt);
 	}
 
 	return err;
@@ -1739,7 +1739,7 @@ struct ib_flow *ib_create_flow(struct ib_qp *qp,
 
 	flow_id = qp->device->create_flow(qp, flow_attr, domain);
 	if (!IS_ERR(flow_id)) {
-		atomic_inc(&qp->usecnt);
+		refcount_inc(&qp->usecnt);
 		flow_id->qp = qp;
 	}
 	return flow_id;
@@ -1753,7 +1753,7 @@ int ib_destroy_flow(struct ib_flow *flow_id)
 
 	err = qp->device->destroy_flow(flow_id);
 	if (!err)
-		atomic_dec(&qp->usecnt);
+		refcount_dec(&qp->usecnt);
 	return err;
 }
 EXPORT_SYMBOL(ib_destroy_flow);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
index abcc9e7..3196a36 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -74,7 +74,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
 	       CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
 	       CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
 
-	atomic_inc(&qhp->refcnt);
+	refcount_inc(&qhp->refcnt);
 	spin_unlock(&rnicp->lock);
 
 	if (qhp->attr.state == IWCH_QP_STATE_RTS) {
@@ -99,7 +99,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 	spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 
-	if (atomic_dec_and_test(&qhp->refcnt))
+	if (refcount_dec_and_test(&qhp->refcnt))
 		wake_up(&qhp->wait);
 }
 
@@ -127,7 +127,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
 		goto out;
 	}
 	iwch_qp_add_ref(&qhp->ibqp);
-	atomic_inc(&chp->refcnt);
+	refcount_inc(&chp->refcnt);
 	spin_unlock(&rnicp->lock);
 
 	/*
@@ -224,7 +224,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
 		break;
 	}
 done:
-	if (atomic_dec_and_test(&chp->refcnt))
+	if (refcount_dec_and_test(&chp->refcnt))
 	        wake_up(&chp->wait);
 	iwch_qp_rem_ref(&qhp->ibqp);
 out:
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 9d5fe18..041963a 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -135,8 +135,8 @@ static int iwch_destroy_cq(struct ib_cq *ib_cq)
 	chp = to_iwch_cq(ib_cq);
 
 	remove_handle(chp->rhp, &chp->rhp->cqidr, chp->cq.cqid);
-	atomic_dec(&chp->refcnt);
-	wait_event(chp->wait, !atomic_read(&chp->refcnt));
+	refcount_dec(&chp->refcnt);
+	wait_event(chp->wait, !refcount_read(&chp->refcnt));
 
 	cxio_destroy_cq(&chp->rhp->rdev, &chp->cq);
 	kfree(chp);
@@ -201,7 +201,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev,
 	chp->ibcq.cqe = 1 << chp->cq.size_log2;
 	spin_lock_init(&chp->lock);
 	spin_lock_init(&chp->comp_handler_lock);
-	atomic_set(&chp->refcnt, 1);
+	refcount_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
 		cxio_destroy_cq(&chp->rhp->rdev, &chp->cq);
@@ -810,8 +810,8 @@ static int iwch_destroy_qp(struct ib_qp *ib_qp)
 
 	remove_handle(rhp, &rhp->qpidr, qhp->wq.qpid);
 
-	atomic_dec(&qhp->refcnt);
-	wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
+	refcount_dec(&qhp->refcnt);
+	wait_event(qhp->wait, !refcount_read(&qhp->refcnt));
 
 	ucontext = ib_qp->uobject ? to_iwch_ucontext(ib_qp->uobject->context)
 				  : NULL;
@@ -921,7 +921,7 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
 
 	spin_lock_init(&qhp->lock);
 	init_waitqueue_head(&qhp->wait);
-	atomic_set(&qhp->refcnt, 1);
+	refcount_set(&qhp->refcnt, 1);
 
 	if (insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.qpid)) {
 		cxio_destroy_qp(&rhp->rdev, &qhp->wq,
@@ -1024,13 +1024,13 @@ static int iwch_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 void iwch_qp_add_ref(struct ib_qp *qp)
 {
 	PDBG("%s ib_qp %p\n", __func__, qp);
-	atomic_inc(&(to_iwch_qp(qp)->refcnt));
+	refcount_inc(&(to_iwch_qp(qp)->refcnt));
 }
 
 void iwch_qp_rem_ref(struct ib_qp *qp)
 {
 	PDBG("%s ib_qp %p\n", __func__, qp);
-	if (atomic_dec_and_test(&(to_iwch_qp(qp)->refcnt)))
+	if (refcount_dec_and_test(&(to_iwch_qp(qp)->refcnt)))
 	        wake_up(&(to_iwch_qp(qp)->wait));
 }
 
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index 252c464..f70ba41 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -34,6 +34,7 @@
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <linux/refcount.h>
 #include <rdma/ib_verbs.h>
 #include <asm/types.h>
 #include "t3cdev.h"
@@ -106,7 +107,7 @@ struct iwch_cq {
 	struct t3_cq cq;
 	spinlock_t lock;
 	spinlock_t comp_handler_lock;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	wait_queue_head_t wait;
 	u32 __user *user_rptr_addr;
 };
@@ -165,7 +166,7 @@ struct iwch_qp {
 	struct iwch_qp_attributes attr;
 	struct t3_wq wq;
 	spinlock_t lock;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	wait_queue_head_t wait;
 	enum IWCH_QP_FLAGS flags;
 	struct timer_list timer;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index a9194db..17f94a0 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -731,7 +731,7 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
 
 	PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
 	/* take a ref on the qhp since we must release the lock */
-	atomic_inc(&qhp->refcnt);
+	refcount_inc(&qhp->refcnt);
 	spin_unlock(&qhp->lock);
 
 	/* locking hierarchy: cq lock first, then qp lock. */
@@ -763,7 +763,7 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
 	}
 
 	/* deref */
-	if (atomic_dec_and_test(&qhp->refcnt))
+	if (refcount_dec_and_test(&qhp->refcnt))
 	        wake_up(&qhp->wait);
 
 	spin_lock(&qhp->lock);
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 19c6477..cab3df3 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -859,8 +859,8 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq)
 	chp = to_c4iw_cq(ib_cq);
 
 	remove_handle(chp->rhp, &chp->rhp->cqidr, chp->cq.cqid);
-	atomic_dec(&chp->refcnt);
-	wait_event(chp->wait, !atomic_read(&chp->refcnt));
+	refcount_dec(&chp->refcnt);
+	wait_event(chp->wait, !refcount_read(&chp->refcnt));
 
 	ucontext = ib_cq->uobject ? to_c4iw_ucontext(ib_cq->uobject->context)
 				  : NULL;
@@ -954,7 +954,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
 	chp->ibcq.cqe = entries - 2;
 	spin_lock_init(&chp->lock);
 	spin_lock_init(&chp->comp_handler_lock);
-	atomic_set(&chp->refcnt, 1);
+	refcount_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
 	if (ret)
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index bdfac2c..e95609d 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -151,7 +151,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
 	}
 
 	c4iw_qp_add_ref(&qhp->ibqp);
-	atomic_inc(&chp->refcnt);
+	refcount_inc(&chp->refcnt);
 	spin_unlock_irq(&dev->lock);
 
 	/* Bad incoming write */
@@ -213,7 +213,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
 		break;
 	}
 done:
-	if (atomic_dec_and_test(&chp->refcnt))
+	if (refcount_dec_and_test(&chp->refcnt))
 		wake_up(&chp->wait);
 	c4iw_qp_rem_ref(&qhp->ibqp);
 out:
@@ -228,13 +228,13 @@ int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
 	spin_lock_irqsave(&dev->lock, flag);
 	chp = get_chp(dev, qid);
 	if (chp) {
-		atomic_inc(&chp->refcnt);
+		refcount_inc(&chp->refcnt);
 		spin_unlock_irqrestore(&dev->lock, flag);
 		t4_clear_cq_armed(&chp->cq);
 		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
-		if (atomic_dec_and_test(&chp->refcnt))
+		if (refcount_dec_and_test(&chp->refcnt))
 			wake_up(&chp->wait);
 	} else {
 		PDBG("%s unknown cqid 0x%x\n", __func__, qid);
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 4dc1415..a236a90 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -45,6 +45,7 @@
 #include <linux/kref.h>
 #include <linux/timer.h>
 #include <linux/io.h>
+#include <linux/refcount.h>
 
 #include <asm/byteorder.h>
 
@@ -419,7 +420,7 @@ struct c4iw_cq {
 	struct t4_cq cq;
 	spinlock_t lock;
 	spinlock_t comp_handler_lock;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	wait_queue_head_t wait;
 };
 
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index bd786b7..ef05549 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -185,7 +185,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
 	if (fd) {
 		fd->rec_cpu_num = -1; /* no cpu affinity by default */
 		fd->mm = current->mm;
-		atomic_inc(&fd->mm->mm_count);
+		refcount_inc(&fd->mm->mm_count);
 		fp->private_data = fd;
 	} else {
 		fp->private_data = NULL;
diff --git a/drivers/infiniband/hw/hfi1/qp.c b/drivers/infiniband/hw/hfi1/qp.c
index d752d67..b8bc0e6 100644
--- a/drivers/infiniband/hw/hfi1/qp.c
+++ b/drivers/infiniband/hw/hfi1/qp.c
@@ -748,7 +748,7 @@ void qp_iter_print(struct seq_file *s, struct qp_iter *iter)
 		   iter->n,
 		   qp_idle(qp) ? "I" : "B",
 		   qp->ibqp.qp_num,
-		   atomic_read(&qp->refcount),
+		   refcount_read(&qp->refcount),
 		   qp_type_str[qp->ibqp.qp_type],
 		   qp->state,
 		   wqe ? wqe->wr.opcode : 0,
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c
index 7d22f8e..fa5e5c9 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.c
+++ b/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -60,6 +60,7 @@
 #include <linux/mmu_context.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#include <linux/refcount.h>
 
 #include "hfi.h"
 #include "sdma.h"
@@ -190,7 +191,7 @@ struct user_sdma_iovec {
 struct sdma_mmu_node {
 	struct mmu_rb_node rb;
 	struct hfi1_user_sdma_pkt_q *pq;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct page **pages;
 	unsigned npages;
 };
@@ -1178,7 +1179,7 @@ static int pin_vector_pages(struct user_sdma_request *req,
 
 		node->rb.addr = (unsigned long)iovec->iov.iov_base;
 		node->pq = pq;
-		atomic_set(&node->refcount, 0);
+		refcount_set(&node->refcount, 0);
 	}
 
 	npages = num_user_pages(&iovec->iov);
@@ -1602,7 +1603,7 @@ static void user_sdma_free_request(struct user_sdma_request *req, bool unpin)
 				hfi1_mmu_rb_remove(req->pq->handler,
 						   &node->rb);
 			else
-				atomic_dec(&node->refcount);
+				refcount_dec(&node->refcount);
 		}
 	}
 	kfree(req->tids);
@@ -1634,7 +1635,7 @@ static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode)
 	struct sdma_mmu_node *node =
 		container_of(mnode, struct sdma_mmu_node, rb);
 
-	atomic_inc(&node->refcount);
+	refcount_inc(&node->refcount);
 	return 0;
 }
 
@@ -1651,7 +1652,7 @@ static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode,
 	struct evict_data *evict_data = evict_arg;
 
 	/* is this node still being used? */
-	if (atomic_read(&node->refcount))
+	if (refcount_read(&node->refcount))
 		return 0; /* keep this node */
 
 	/* this node will be evicted, add its pages to our count */
@@ -1681,7 +1682,7 @@ static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode)
 	struct sdma_mmu_node *node =
 		container_of(mnode, struct sdma_mmu_node, rb);
 
-	if (!atomic_read(&node->refcount))
+	if (!refcount_read(&node->refcount))
 		return 1;
 	return 0;
 }
diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c
index 589496c..3605adb 100644
--- a/drivers/infiniband/hw/hns/hns_roce_cq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_cq.c
@@ -152,7 +152,7 @@ static int hns_roce_cq_alloc(struct hns_roce_dev *hr_dev, int nent,
 	hr_cq->cons_index = 0;
 	hr_cq->uar = hr_uar;
 
-	atomic_set(&hr_cq->refcount, 1);
+	refcount_set(&hr_cq->refcount, 1);
 	init_completion(&hr_cq->free);
 
 	return 0;
@@ -194,7 +194,7 @@ void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
 	synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq);
 
 	/* wait for all interrupt processed */
-	if (atomic_dec_and_test(&hr_cq->refcount))
+	if (refcount_dec_and_test(&hr_cq->refcount))
 		complete(&hr_cq->free);
 	wait_for_completion(&hr_cq->free);
 
@@ -436,7 +436,7 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
 	cq = radix_tree_lookup(&cq_table->tree,
 			       cqn & (hr_dev->caps.num_cqs - 1));
 	if (cq)
-		atomic_inc(&cq->refcount);
+		refcount_inc(&cq->refcount);
 
 	if (!cq) {
 		dev_warn(dev, "Async event for bogus CQ %08x\n", cqn);
@@ -445,7 +445,7 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
 
 	cq->event(cq, (enum hns_roce_event)event_type);
 
-	if (atomic_dec_and_test(&cq->refcount))
+	if (refcount_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 }
 
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 1a6cb5d..23aebb6 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -33,6 +33,7 @@
 #ifndef _HNS_ROCE_DEVICE_H
 #define _HNS_ROCE_DEVICE_H
 
+#include <linux/refcount.h>
 #include <rdma/ib_verbs.h>
 
 #define DRV_NAME "hns_roce"
@@ -310,7 +311,7 @@ struct hns_roce_cq {
 	u16				*tptr_addr;
 	unsigned long			cqn;
 	u32				vector;
-	atomic_t			refcount;
+	refcount_t			refcount;
 	struct completion		free;
 };
 
@@ -427,7 +428,7 @@ struct hns_roce_qp {
 					 enum hns_roce_event);
 	unsigned long		qpn;
 
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 };
 
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
index f036f32..83bcf40 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -51,7 +51,7 @@ void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
 
 	qp = __hns_roce_qp_lookup(hr_dev, qpn);
 	if (qp)
-		atomic_inc(&qp->refcount);
+		refcount_inc(&qp->refcount);
 
 	spin_unlock(&qp_table->lock);
 
@@ -62,7 +62,7 @@ void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
 
 	qp->event(qp, (enum hns_roce_event)event_type);
 
-	if (atomic_dec_and_test(&qp->refcount))
+	if (refcount_dec_and_test(&qp->refcount))
 		complete(&qp->free);
 }
 
@@ -157,7 +157,7 @@ static int hns_roce_gsi_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
 		goto err_put_irrl;
 	}
 
-	atomic_set(&hr_qp->refcount, 1);
+	refcount_set(&hr_qp->refcount, 1);
 	init_completion(&hr_qp->free);
 
 	return 0;
@@ -202,7 +202,7 @@ static int hns_roce_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
 		goto err_put_irrl;
 	}
 
-	atomic_set(&hr_qp->refcount, 1);
+	refcount_set(&hr_qp->refcount, 1);
 	init_completion(&hr_qp->free);
 
 	return 0;
@@ -232,7 +232,7 @@ void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
 {
 	struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
 
-	if (atomic_dec_and_test(&hr_qp->refcount))
+	if (refcount_dec_and_test(&hr_qp->refcount))
 		complete(&hr_qp->free);
 	wait_for_completion(&hr_qp->free);
 
diff --git a/drivers/infiniband/hw/i40iw/i40iw.h b/drivers/infiniband/hw/i40iw/i40iw.h
index da2eb5a..0be1b50 100644
--- a/drivers/infiniband/hw/i40iw/i40iw.h
+++ b/drivers/infiniband/hw/i40iw/i40iw.h
@@ -45,6 +45,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/crc32c.h>
+#include <linux/refcount.h>
 #include <rdma/ib_smi.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_pack.h>
@@ -140,7 +141,7 @@ struct i40iw_cqp_request {
 	struct cqp_commands_info info;
 	wait_queue_head_t waitq;
 	struct list_head list;
-	atomic_t refcount;
+	refcount_t refcount;
 	void (*callback_fcn)(struct i40iw_cqp_request*, u32);
 	void *param;
 	struct i40iw_cqp_compl_info compl_info;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c
index 95a0586..6839ee6 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -76,7 +76,7 @@ void i40iw_free_sqbuf(struct i40iw_sc_vsi *vsi, void *bufp)
 	struct i40iw_puda_buf *buf = (struct i40iw_puda_buf *)bufp;
 	struct i40iw_puda_rsrc *ilq = vsi->ilq;
 
-	if (!atomic_dec_return(&buf->refcount))
+	if (refcount_dec_and_test(&buf->refcount))
 		i40iw_puda_ret_bufpool(ilq, buf);
 }
 
@@ -532,7 +532,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct i40iw_cm_node *cm_node,
 	if (pdata && pdata->addr)
 		memcpy(buf, pdata->addr, pdata->size);
 
-	atomic_set(&sqbuf->refcount, 1);
+	refcount_set(&sqbuf->refcount, 1);
 
 	return sqbuf;
 }
@@ -1097,7 +1097,7 @@ int i40iw_schedule_cm_timer(struct i40iw_cm_node *cm_node,
 		spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
 		new_send->timetosend = jiffies + I40IW_RETRY_TIMEOUT;
 
-		atomic_inc(&sqbuf->refcount);
+		refcount_inc(&sqbuf->refcount);
 		i40iw_puda_send_buf(vsi->ilq, sqbuf);
 		if (!send_retrans) {
 			i40iw_cleanup_retrans_entry(cm_node);
@@ -1273,7 +1273,7 @@ static void i40iw_cm_timer_tick(unsigned long pass)
 
 		vsi = &cm_node->iwdev->vsi;
 		dev = cm_node->dev;
-		atomic_inc(&send_entry->sqbuf->refcount);
+		refcount_inc(&send_entry->sqbuf->refcount);
 		i40iw_puda_send_buf(vsi->ilq, send_entry->sqbuf);
 		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
 		if (send_entry->send_retrans) {
@@ -1868,7 +1868,7 @@ static int i40iw_dec_refcnt_listen(struct i40iw_cm_core *cm_core,
 		}
 	}
 
-	if (!atomic_dec_return(&listener->ref_count)) {
+	if (atomic_dec_and_test(&listener->ref_count)) {
 		spin_lock_irqsave(&cm_core->listen_list_lock, flags);
 		list_del(&listener->list);
 		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
@@ -2236,7 +2236,7 @@ static void i40iw_rem_ref_cm_node(struct i40iw_cm_node *cm_node)
 	unsigned long flags;
 
 	spin_lock_irqsave(&cm_node->cm_core->ht_lock, flags);
-	if (atomic_dec_return(&cm_node->ref_count)) {
+	if (!atomic_dec_and_test(&cm_node->ref_count)) {
 		spin_unlock_irqrestore(&cm_node->cm_core->ht_lock, flags);
 		return;
 	}
diff --git a/drivers/infiniband/hw/i40iw/i40iw_main.c b/drivers/infiniband/hw/i40iw/i40iw_main.c
index 2728af3..53549b4 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_main.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_main.c
@@ -1113,7 +1113,7 @@ static enum i40iw_status_code i40iw_alloc_local_mac_ipaddr_entry(struct i40iw_de
 	}
 
 	/* increment refcount, because we need the cqp request ret value */
-	atomic_inc(&cqp_request->refcount);
+	refcount_inc(&cqp_request->refcount);
 
 	cqp_info = &cqp_request->info;
 	cqp_info->cqp_cmd = OP_ALLOC_LOCAL_MAC_IPADDR_ENTRY;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_puda.h b/drivers/infiniband/hw/i40iw/i40iw_puda.h
index dba05ce..0f8f06a 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_puda.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_puda.h
@@ -35,6 +35,8 @@
 #ifndef I40IW_PUDA_H
 #define I40IW_PUDA_H
 
+#include <linux/refcount.h>
+
 #define I40IW_IEQ_MPA_FRAMING 6
 
 struct i40iw_sc_dev;
@@ -90,7 +92,7 @@ struct i40iw_puda_buf {
 	u8 tcphlen;		/* tcp length in bytes */
 	u8 maclen;		/* mac length in bytes */
 	u32 totallen;		/* machlen+iphlen+tcphlen+datalen */
-	atomic_t refcount;
+	refcount_t refcount;
 	u8 hdrlen;
 	bool ipv4;
 	u32 seqnum;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c
index 0f5d43d..7155f17 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_utils.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c
@@ -314,10 +314,10 @@ struct i40iw_cqp_request *i40iw_get_cqp_request(struct i40iw_cqp *cqp, bool wait
 	}
 
 	if (wait) {
-		atomic_set(&cqp_request->refcount, 2);
+		refcount_set(&cqp_request->refcount, 2);
 		cqp_request->waiting = true;
 	} else {
-		atomic_set(&cqp_request->refcount, 1);
+		refcount_set(&cqp_request->refcount, 1);
 	}
 	return cqp_request;
 }
@@ -352,7 +352,7 @@ void i40iw_free_cqp_request(struct i40iw_cqp *cqp, struct i40iw_cqp_request *cqp
 void i40iw_put_cqp_request(struct i40iw_cqp *cqp,
 			   struct i40iw_cqp_request *cqp_request)
 {
-	if (atomic_dec_and_test(&cqp_request->refcount))
+	if (refcount_dec_and_test(&cqp_request->refcount))
 		i40iw_free_cqp_request(cqp, cqp_request);
 }
 
@@ -497,7 +497,7 @@ void i40iw_add_ref(struct ib_qp *ibqp)
 {
 	struct i40iw_qp *iwqp = (struct i40iw_qp *)ibqp;
 
-	atomic_inc(&iwqp->refcount);
+	refcount_inc(&iwqp->refcount);
 }
 
 /**
@@ -517,7 +517,7 @@ void i40iw_rem_ref(struct ib_qp *ibqp)
 	iwqp = to_iwqp(ibqp);
 	iwdev = iwqp->iwdev;
 	spin_lock_irqsave(&iwdev->qptable_lock, flags);
-	if (!atomic_dec_and_test(&iwqp->refcount)) {
+	if (!refcount_dec_and_test(&iwqp->refcount)) {
 		spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
 		return;
 	}
@@ -931,7 +931,7 @@ static void i40iw_cqp_manage_hmc_fcn_callback(struct i40iw_cqp_request *cqp_requ
 
 	if (hmcfcninfo && hmcfcninfo->callback_fcn) {
 		i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_HMC, "%s1\n", __func__);
-		atomic_inc(&cqp_request->refcount);
+		refcount_inc(&cqp_request->refcount);
 		work = &iwdev->virtchnl_w[hmcfcninfo->iw_vf_idx];
 		work->cqp_request = cqp_request;
 		INIT_WORK(&work->work, i40iw_cqp_manage_hmc_fcn_worker);
diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
index 29e97df..fd1073a 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
@@ -264,7 +264,7 @@ static void i40iw_alloc_push_page(struct i40iw_device *iwdev, struct i40iw_sc_qp
 	if (!cqp_request)
 		return;
 
-	atomic_inc(&cqp_request->refcount);
+	refcount_inc(&cqp_request->refcount);
 
 	cqp_info = &cqp_request->info;
 	cqp_info->cqp_cmd = OP_MANAGE_PUSH_PAGE;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.h b/drivers/infiniband/hw/i40iw/i40iw_verbs.h
index 07c3fec..14f70c3 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_verbs.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.h
@@ -35,6 +35,8 @@
 #ifndef I40IW_VERBS_H
 #define I40IW_VERBS_H
 
+#include <linux/refcount.h>
+
 struct i40iw_ucontext {
 	struct ib_ucontext ibucontext;
 	struct i40iw_device *iwdev;
@@ -140,7 +142,7 @@ struct i40iw_qp {
 	struct i40iw_qp_host_ctx_info ctx_info;
 	struct i40iwarp_offload_info iwarp_info;
 	void *allocated_buffer;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct iw_cm_id *cm_id;
 	void *cm_node;
 	struct ib_mr *lsmm_mr;
diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c
index e010fe4..82c866d 100644
--- a/drivers/infiniband/hw/mlx4/mcg.c
+++ b/drivers/infiniband/hw/mlx4/mcg.c
@@ -38,6 +38,7 @@
 #include <linux/mlx4/cmd.h>
 #include <linux/rbtree.h>
 #include <linux/delay.h>
+#include <linux/refcount.h>
 
 #include "mlx4_ib.h"
 
@@ -121,7 +122,7 @@ struct mcast_group {
 	   2. Each invocation of the worker thread
 	   3. Membership of the port at the SA
 	*/
-	atomic_t		refcount;
+	refcount_t		refcount;
 
 	/* delayed work to clean pending SM request */
 	struct delayed_work	timeout_work;
@@ -138,9 +139,9 @@ struct mcast_req {
 };
 
 
-#define safe_atomic_dec(ref) \
+#define safe_refcount_dec(ref) \
 	do {\
-		if (atomic_dec_and_test(ref)) \
+		if (refcount_dec_and_test(ref)) \
 			mcg_warn_group(group, "did not expect to reach zero\n"); \
 	} while (0)
 
@@ -441,11 +442,11 @@ static int release_group(struct mcast_group *group, int from_timeout_handler)
 
 	mutex_lock(&ctx->mcg_table_lock);
 	mutex_lock(&group->lock);
-	if (atomic_dec_and_test(&group->refcount)) {
+	if (refcount_dec_and_test(&group->refcount)) {
 		if (!from_timeout_handler) {
 			if (group->state != MCAST_IDLE &&
 			    !cancel_delayed_work(&group->timeout_work)) {
-				atomic_inc(&group->refcount);
+				refcount_inc(&group->refcount);
 				mutex_unlock(&group->lock);
 				mutex_unlock(&ctx->mcg_table_lock);
 				return 0;
@@ -574,9 +575,9 @@ static void mlx4_ib_mcg_timeout_handler(struct work_struct *work)
 	} else
 		mcg_warn_group(group, "invalid state %s\n", get_state_string(group->state));
 	group->state = MCAST_IDLE;
-	atomic_inc(&group->refcount);
+	refcount_inc(&group->refcount);
 	if (!queue_work(group->demux->mcg_wq, &group->work))
-		safe_atomic_dec(&group->refcount);
+		safe_refcount_dec(&group->refcount);
 
 	mutex_unlock(&group->lock);
 }
@@ -775,7 +776,7 @@ static struct mcast_group *search_relocate_mgid0_group(struct mlx4_ib_demux_ctx
 					return NULL;
 				}
 
-				atomic_inc(&group->refcount);
+				refcount_inc(&group->refcount);
 				add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
 				mutex_unlock(&group->lock);
 				mutex_unlock(&ctx->mcg_table_lock);
@@ -863,7 +864,7 @@ static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx,
 	add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
 
 found:
-	atomic_inc(&group->refcount);
+	refcount_inc(&group->refcount);
 	return group;
 }
 
@@ -871,13 +872,13 @@ static void queue_req(struct mcast_req *req)
 {
 	struct mcast_group *group = req->group;
 
-	atomic_inc(&group->refcount); /* for the request */
-	atomic_inc(&group->refcount); /* for scheduling the work */
+	refcount_inc(&group->refcount); /* for the request */
+	refcount_inc(&group->refcount); /* for scheduling the work */
 	list_add_tail(&req->group_list, &group->pending_list);
 	list_add_tail(&req->func_list, &group->func[req->func].pending);
 	/* calls mlx4_ib_mcg_work_handler */
 	if (!queue_work(group->demux->mcg_wq, &group->work))
-		safe_atomic_dec(&group->refcount);
+		safe_refcount_dec(&group->refcount);
 }
 
 int mlx4_ib_mcg_demux_handler(struct ib_device *ibdev, int port, int slave,
@@ -911,9 +912,9 @@ int mlx4_ib_mcg_demux_handler(struct ib_device *ibdev, int port, int slave,
 		group->prev_state = group->state;
 		group->state = MCAST_RESP_READY;
 		/* calls mlx4_ib_mcg_work_handler */
-		atomic_inc(&group->refcount);
+		refcount_inc(&group->refcount);
 		if (!queue_work(ctx->mcg_wq, &group->work))
-			safe_atomic_dec(&group->refcount);
+			safe_refcount_dec(&group->refcount);
 		mutex_unlock(&group->lock);
 		release_group(group, 0);
 		return 1; /* consumed */
@@ -1014,7 +1015,7 @@ static ssize_t sysfs_show_group(struct device *dev,
 	len += sprintf(buf + len, "%1d [%02d,%02d,%02d] %4d %4s %5s     ",
 			group->rec.scope_join_state & 0xf,
 			group->members[2], group->members[1], group->members[0],
-			atomic_read(&group->refcount),
+			refcount_read(&group->refcount),
 			pending_str,
 			state_str);
 	for (f = 0; f < MAX_VFS; ++f)
@@ -1101,8 +1102,8 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
 	mutex_lock(&ctx->mcg_table_lock);
 	while ((p = rb_first(&ctx->mcg_table)) != NULL) {
 		group = rb_entry(p, struct mcast_group, node);
-		if (atomic_read(&group->refcount))
-			mcg_warn_group(group, "group refcount %d!!! (pointer %p)\n", atomic_read(&group->refcount), group);
+		if (refcount_read(&group->refcount))
+			mcg_warn_group(group, "group refcount %d!!! (pointer %p)\n", refcount_read(&group->refcount), group);
 
 		force_clean_group(group);
 	}
@@ -1182,7 +1183,7 @@ static void clear_pending_reqs(struct mcast_group *group, int vf)
 			list_del(&req->group_list);
 			list_del(&req->func_list);
 			kfree(req);
-			atomic_dec(&group->refcount);
+			refcount_dec(&group->refcount);
 		}
 	}
 
@@ -1230,7 +1231,7 @@ void clean_vf_mcast(struct mlx4_ib_demux_ctx *ctx, int slave)
 	for (p = rb_first(&ctx->mcg_table); p; p = rb_next(p)) {
 		group = rb_entry(p, struct mcast_group, node);
 		mutex_lock(&group->lock);
-		if (atomic_read(&group->refcount)) {
+		if (refcount_read(&group->refcount)) {
 			/* clear pending requests of this VF */
 			clear_pending_reqs(group, slave);
 			push_deleteing_req(group, slave);
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c
index b3ef47c..5c45cea 100644
--- a/drivers/infiniband/hw/mlx5/cq.c
+++ b/drivers/infiniband/hw/mlx5/cq.c
@@ -188,7 +188,7 @@ static void handle_responder(struct ib_wc *wc, struct mlx5_cqe64 *cqe,
 			wqe_ctr = be16_to_cpu(cqe->wqe_counter);
 			wc->wr_id = srq->wrid[wqe_ctr];
 			mlx5_ib_free_srq_wqe(srq, wqe_ctr);
-			if (msrq && atomic_dec_and_test(&msrq->refcount))
+			if (msrq && refcount_dec_and_test(&msrq->refcount))
 				complete(&msrq->free);
 		}
 	} else {
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index d566f67..c938dda 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -2645,7 +2645,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
 	}
 	devr->p0->device  = &dev->ib_dev;
 	devr->p0->uobject = NULL;
-	atomic_set(&devr->p0->usecnt, 0);
+	refcount_set(&devr->p0->usecnt, 0);
 
 	devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, &cq_attr, NULL, NULL);
 	if (IS_ERR(devr->c0)) {
@@ -2657,7 +2657,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
 	devr->c0->comp_handler  = NULL;
 	devr->c0->event_handler = NULL;
 	devr->c0->cq_context    = NULL;
-	atomic_set(&devr->c0->usecnt, 0);
+	refcount_set(&devr->c0->usecnt, 0);
 
 	devr->x0 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL, NULL);
 	if (IS_ERR(devr->x0)) {
@@ -2666,7 +2666,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
 	}
 	devr->x0->device = &dev->ib_dev;
 	devr->x0->inode = NULL;
-	atomic_set(&devr->x0->usecnt, 0);
+	refcount_set(&devr->x0->usecnt, 0);
 	mutex_init(&devr->x0->tgt_qp_mutex);
 	INIT_LIST_HEAD(&devr->x0->tgt_qp_list);
 
@@ -2677,7 +2677,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
 	}
 	devr->x1->device = &dev->ib_dev;
 	devr->x1->inode = NULL;
-	atomic_set(&devr->x1->usecnt, 0);
+	refcount_set(&devr->x1->usecnt, 0);
 	mutex_init(&devr->x1->tgt_qp_mutex);
 	INIT_LIST_HEAD(&devr->x1->tgt_qp_list);
 
@@ -2701,10 +2701,10 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
 	devr->s0->srq_type      = IB_SRQT_XRC;
 	devr->s0->ext.xrc.xrcd	= devr->x0;
 	devr->s0->ext.xrc.cq	= devr->c0;
-	atomic_inc(&devr->s0->ext.xrc.xrcd->usecnt);
-	atomic_inc(&devr->s0->ext.xrc.cq->usecnt);
-	atomic_inc(&devr->p0->usecnt);
-	atomic_set(&devr->s0->usecnt, 0);
+	refcount_inc(&devr->s0->ext.xrc.xrcd->usecnt);
+	refcount_inc(&devr->s0->ext.xrc.cq->usecnt);
+	refcount_inc(&devr->p0->usecnt);
+	refcount_set(&devr->s0->usecnt, 0);
 
 	memset(&attr, 0, sizeof(attr));
 	attr.attr.max_sge = 1;
@@ -2722,8 +2722,8 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
 	devr->s1->srq_context   = NULL;
 	devr->s1->srq_type      = IB_SRQT_BASIC;
 	devr->s1->ext.xrc.cq	= devr->c0;
-	atomic_inc(&devr->p0->usecnt);
-	atomic_set(&devr->s0->usecnt, 0);
+	refcount_inc(&devr->p0->usecnt);
+	refcount_set(&devr->s0->usecnt, 0);
 
 	for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) {
 		INIT_WORK(&devr->ports[port].pkey_change_work,
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 5b96010..ebeeac9 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -257,8 +257,8 @@ void nes_add_ref(struct ib_qp *ibqp)
 
 	nesqp = to_nesqp(ibqp);
 	nes_debug(NES_DBG_QP, "Bumping refcount for QP%u.  Pre-inc value = %u\n",
-			ibqp->qp_num, atomic_read(&nesqp->refcount));
-	atomic_inc(&nesqp->refcount);
+			ibqp->qp_num, refcount_read(&nesqp->refcount));
+	refcount_inc(&nesqp->refcount);
 }
 
 static void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
@@ -306,13 +306,13 @@ void nes_rem_ref(struct ib_qp *ibqp)
 
 	nesqp = to_nesqp(ibqp);
 
-	if (atomic_read(&nesqp->refcount) == 0) {
+	if (refcount_read(&nesqp->refcount) == 0) {
 		printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n",
 				__func__, ibqp->qp_num, nesqp->last_aeq);
 		BUG();
 	}
 
-	if (atomic_dec_and_test(&nesqp->refcount)) {
+	if (refcount_dec_and_test(&nesqp->refcount)) {
 		if (nesqp->pau_mode)
 			nes_destroy_pau_qp(nesdev, nesqp);
 
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 53eb47b..906d3c0 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -814,7 +814,7 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
 				  "refcount = %d: HIT A "
 				  "NES_TIMER_TYPE_CLOSE with something "
 				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				  atomic_read(&nesqp->refcount));
+				  refcount_read(&nesqp->refcount));
 			nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
 			nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
 			nesqp->ibqp_state = IB_QPS_ERR;
@@ -826,7 +826,7 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
 				  "refcount = %d: HIT A "
 				  "NES_TIMER_TYPE_CLOSE with nothing "
 				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				  atomic_read(&nesqp->refcount));
+				  refcount_read(&nesqp->refcount));
 		}
 	} else if (rem_node) {
 		/* TIME_WAIT state */
@@ -1186,7 +1186,7 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
 		     listen_addr == 0x00000000) &&
 		    (listen_port == dst_port) &&
 		    (listener_state & listen_node->listener_state)) {
-			atomic_inc(&listen_node->ref_count);
+			refcount_inc(&listen_node->ref_count);
 			spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 			return listen_node;
 		}
@@ -1240,7 +1240,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 
 	nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, "
 		  "refcnt=%d\n", listener, free_hanging_nodes,
-		  atomic_read(&listener->ref_count));
+		  refcount_read(&listener->ref_count));
 	/* free non-accelerated child nodes for this listener */
 	INIT_LIST_HEAD(&reset_list);
 	if (free_hanging_nodes) {
@@ -1309,7 +1309,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 	}
 
 	spin_lock_irqsave(&cm_core->listen_list_lock, flags);
-	if (!atomic_dec_return(&listener->ref_count)) {
+	if (refcount_dec_and_test(&listener->ref_count)) {
 		list_del(&listener->list);
 
 		/* decrement our listen node count */
@@ -1496,7 +1496,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
 	spin_lock_init(&cm_node->retrans_list_lock);
 
 	cm_node->loopbackpartner = NULL;
-	atomic_set(&cm_node->ref_count, 1);
+	refcount_set(&cm_node->ref_count, 1);
 	/* associate our parent CM core */
 	cm_node->cm_core = cm_core;
 	cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;
@@ -1548,7 +1548,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
  */
 static int add_ref_cm_node(struct nes_cm_node *cm_node)
 {
-	atomic_inc(&cm_node->ref_count);
+	refcount_inc(&cm_node->ref_count);
 	return 0;
 }
 
@@ -1566,7 +1566,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
 		return -EINVAL;
 
 	spin_lock_irqsave(&cm_node->cm_core->ht_lock, flags);
-	if (atomic_dec_return(&cm_node->ref_count)) {
+	if (!refcount_dec_and_test(&cm_node->ref_count)) {
 		spin_unlock_irqrestore(&cm_node->cm_core->ht_lock, flags);
 		return 0;
 	}
@@ -1668,7 +1668,7 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node)
 {
 	nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
 		  "refcnt=%d\n", cm_node, cm_node->state,
-		  atomic_read(&cm_node->ref_count));
+		  refcount_read(&cm_node->ref_count));
 	switch (cm_node->state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_SYN_SENT:
@@ -1726,7 +1726,7 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 	atomic_inc(&cm_resets_recvd);
 	nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u."
 			" refcnt=%d\n", cm_node, cm_node->state,
-			atomic_read(&cm_node->ref_count));
+			refcount_read(&cm_node->ref_count));
 	cleanup_retrans_entry(cm_node);
 	switch (cm_node->state) {
 	case NES_CM_STATE_SYN_SENT:
@@ -2274,7 +2274,7 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
 
 	if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {
 		/* find automatically incs ref count ??? */
-		atomic_dec(&listener->ref_count);
+		refcount_dec(&listener->ref_count);
 		nes_debug(NES_DBG_CM, "Not creating listener since it already exists\n");
 		return NULL;
 	}
@@ -2289,7 +2289,7 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
 		listener->loc_port = cm_info->loc_port;
 		listener->reused_node = 0;
 
-		atomic_set(&listener->ref_count, 1);
+		refcount_set(&listener->ref_count, 1);
 	}
 	/* pasive case */
 	/* find already inc'ed the ref count */
@@ -2624,7 +2624,7 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
 				nes_debug(NES_DBG_CM, "Unable to allocate "
 					  "node\n");
 				cm_packets_dropped++;
-				atomic_dec(&listener->ref_count);
+				refcount_dec(&listener->ref_count);
 				dev_kfree_skb_any(skb);
 				break;
 			}
@@ -2976,7 +2976,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
 				  "cm_id = %p, refcount = %u.\n",
 				  nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
 				  nesqp->hwqp.sq_tail, cm_id,
-				  atomic_read(&nesqp->refcount));
+				  refcount_read(&nesqp->refcount));
 
 			ret = cm_id->event_handler(cm_id, &cm_event);
 			if (ret)
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index d827d03..4a5812e 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -34,6 +34,8 @@
 #ifndef NES_CM_H
 #define NES_CM_H
 
+#include <linux/refcount.h>
+
 #define QUEUE_EVENTS
 
 #define NES_MANAGE_APBVT_DEL 0
@@ -297,7 +299,7 @@ struct nes_cm_listener {
 	u16                        loc_port;
 	struct iw_cm_id            *cm_id;
 	enum nes_cm_conn_type      conn_type;
-	atomic_t                   ref_count;
+	refcount_t                   ref_count;
 	struct nes_vnic            *nesvnic;
 	atomic_t                   pend_accepts_cnt;
 	int                        backlog;
@@ -318,7 +320,7 @@ struct nes_cm_node {
 	struct nes_cm_tcp_context tcp_cntxt;
 	struct nes_cm_core        *cm_core;
 	struct sk_buff_head       resend_list;
-	atomic_t                  ref_count;
+	refcount_t                  ref_count;
 	struct net_device         *netdev;
 
 	struct nes_cm_node        *loopbackpartner;
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 19acd13..e6c04cc 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -3563,7 +3563,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 				nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
 						" need ae to finish up, original_last_aeq = 0x%04X."
 						" last_aeq = 0x%04X, scheduling timer. TCP state = %d\n",
-						nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
+						nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount),
 						async_event_id, nesqp->last_aeq, tcp_state);
 			}
 			break;
@@ -3756,7 +3756,7 @@ int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
 
 	nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n");
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	if (add_port == NES_MANAGE_APBVT_ADD)
@@ -3826,7 +3826,7 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
 	nes_debug(NES_DBG_NETDEV, "Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n",
 			nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
 
-	atomic_set(&cqp_request->refcount, 1);
+	refcount_set(&cqp_request->refcount, 1);
 	nes_post_cqp_request(nesdev, cqp_request);
 }
 
@@ -3850,7 +3850,7 @@ void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
 	}
 	if (wait_completion) {
 		cqp_request->waiting = 1;
-		atomic_set(&cqp_request->refcount, 2);
+		refcount_set(&cqp_request->refcount, 2);
 	} else {
 		cqp_request->waiting = 0;
 	}
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 1b66ef1..0579488 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -33,6 +33,8 @@
 #ifndef __NES_HW_H
 #define __NES_HW_H
 
+#include <linux/refcount.h>
+
 #define NES_PHY_TYPE_CX4       1
 #define NES_PHY_TYPE_1G        2
 #define NES_PHY_TYPE_ARGUS     4
@@ -880,7 +882,7 @@ struct nes_cqp_request {
 	wait_queue_head_t     waitq;
 	struct nes_hw_cqp_wqe cqp_wqe;
 	struct list_head      list;
-	atomic_t              refcount;
+	refcount_t              refcount;
 	void (*cqp_callback)(struct nes_device *nesdev, struct nes_cqp_request *cqp_request);
 	u16                   major_code;
 	u16                   minor_code;
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
index 33624f1..2051ac4 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.c
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -471,7 +471,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
 		cqp_request->callback = 1;
 		cqp_request->cqp_callback = nes_download_callback;
 
-		atomic_set(&cqp_request->refcount, 1);
+		refcount_set(&cqp_request->refcount, 1);
 		nes_post_cqp_request(nesdev, cqp_request);
 		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
 	}
@@ -695,7 +695,7 @@ static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request
 		new_request->cqp_callback_pointer = qh_chg;
 		new_request->callback = 1;
 		new_request->cqp_callback = nes_chg_qh_handler;
-		atomic_set(&new_request->refcount, 1);
+		refcount_set(&new_request->refcount, 1);
 		nes_post_cqp_request(nesdev, new_request);
 		break;
 
@@ -751,7 +751,7 @@ static int nes_change_quad_hash(struct nes_device *nesdev,
 	cqp_request->cqp_callback_pointer = qh_chg;
 	cqp_request->callback = 1;
 	cqp_request->cqp_callback = nes_chg_qh_handler;
-	atomic_set(&cqp_request->refcount, 1);
+	refcount_set(&cqp_request->refcount, 1);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	return ret;
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index 37331e2..60ad51c 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -617,7 +617,7 @@ void nes_free_cqp_request(struct nes_device *nesdev,
 void nes_put_cqp_request(struct nes_device *nesdev,
 			 struct nes_cqp_request *cqp_request)
 {
-	if (atomic_dec_and_test(&cqp_request->refcount))
+	if (refcount_dec_and_test(&cqp_request->refcount))
 		nes_free_cqp_request(nesdev, cqp_request);
 }
 
@@ -656,7 +656,7 @@ void nes_post_cqp_request(struct nes_device *nesdev,
 			opcode & NES_CQP_OPCODE_MASK,
 			le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
 			nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
-			cqp_request->waiting, atomic_read(&cqp_request->refcount));
+			cqp_request->waiting, refcount_read(&cqp_request->refcount));
 
 		barrier();
 
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index aff9fb1..4ee9dc8 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -124,7 +124,7 @@ static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd, enum ib_mw_type type,
 	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff));
 	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -181,7 +181,7 @@ static int nes_dealloc_mw(struct ib_mw *ibmw)
 	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, NES_CQP_DEALLOCATE_STAG);
 	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ibmw->rkey);
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -274,7 +274,7 @@ static int alloc_fast_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
 	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE);
 	barrier();
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -592,7 +592,7 @@ static struct ib_ucontext *nes_alloc_ucontext(struct ib_device *ibdev,
 
 	INIT_LIST_HEAD(&nes_ucontext->cq_reg_mem_list);
 	INIT_LIST_HEAD(&nes_ucontext->qp_reg_mem_list);
-	atomic_set(&nes_ucontext->usecnt, 1);
+	refcount_set(&nes_ucontext->usecnt, 1);
 	return &nes_ucontext->ibucontext;
 }
 
@@ -606,7 +606,7 @@ static int nes_dealloc_ucontext(struct ib_ucontext *context)
 	/* struct nes_device *nesdev = nesvnic->nesdev; */
 	struct nes_ucontext *nes_ucontext = to_nesucontext(context);
 
-	if (!atomic_dec_and_test(&nes_ucontext->usecnt))
+	if (!refcount_dec_and_test(&nes_ucontext->usecnt))
 	  return 0;
 	kfree(nes_ucontext);
 	return 0;
@@ -1263,7 +1263,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
 			u64temp = (u64)nesqp->nesqp_context_pbase;
 			set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
 
-			atomic_set(&cqp_request->refcount, 2);
+			refcount_set(&cqp_request->refcount, 2);
 			nes_post_cqp_request(nesdev, cqp_request);
 
 			/* Wait for CQP */
@@ -1398,7 +1398,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
 
 		nes_debug(NES_DBG_QP, "Generating a CM Timeout Event for "
 				"QP%u. cm_id = %p, refcount = %u. \n",
-				nesqp->hwqp.qp_id, cm_id, atomic_read(&nesqp->refcount));
+				nesqp->hwqp.qp_id, cm_id, refcount_read(&nesqp->refcount));
 
 		cm_id->rem_ref(cm_id);
 		ret = cm_id->event_handler(cm_id, &cm_event);
@@ -1647,7 +1647,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev,
 	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
 			cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -1751,7 +1751,7 @@ static int nes_destroy_cq(struct ib_cq *ib_cq)
 	if (!nescq->mcrqf)
 		nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number);
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -1963,7 +1963,7 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
 	}
 	barrier();
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -2531,7 +2531,7 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
 			NES_CQP_STAG_DEALLOC_PBLS | NES_CQP_STAG_MR);
 	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ib_mr->rkey);
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -2679,7 +2679,7 @@ int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp,
 	u16 major_code;
 
 	nes_debug(NES_DBG_MOD_QP, "QP%u, refcount=%d\n",
-			nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
+			nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount));
 
 	cqp_request = nes_get_cqp_request(nesdev);
 	if (cqp_request == NULL) {
@@ -2708,7 +2708,7 @@ int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp,
 		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_NEW_MSS_IDX, termlen);
 	}
 
-	atomic_set(&cqp_request->refcount, 2);
+	refcount_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
@@ -2764,7 +2764,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	nes_debug(NES_DBG_MOD_QP, "QP%u: QP State=%u, cur QP State=%u,"
 			" iwarp_state=0x%X, refcount=%d\n",
 			nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state,
-			nesqp->iwarp_state, atomic_read(&nesqp->refcount));
+			nesqp->iwarp_state, refcount_read(&nesqp->refcount));
 
 	spin_lock_irqsave(&nesqp->lock, qplockflags);
 
@@ -2956,14 +2956,14 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	if ((issue_modify_qp) && (nesqp->ibqp_state > IB_QPS_RTS)) {
 		nes_debug(NES_DBG_MOD_QP, "QP%u Issued ModifyQP refcount (%d),"
 				" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
-				nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
+				nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount),
 				original_last_aeq, nesqp->last_aeq);
 		if (!ret || original_last_aeq != NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
 			if (dont_wait) {
 				if (nesqp->cm_id && nesqp->hw_tcp_state != 0) {
 					nes_debug(NES_DBG_MOD_QP, "QP%u Queuing fake disconnect for QP refcount (%d),"
 							" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
-							nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
+							nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount),
 							original_last_aeq, nesqp->last_aeq);
 					/* this one is for the cm_disconnect thread */
 					spin_lock_irqsave(&nesqp->lock, qplockflags);
@@ -2973,7 +2973,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 					nes_cm_disconn(nesqp);
 				} else {
 					nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n",
-							nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
+							nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount));
 				}
 			} else {
 				spin_lock_irqsave(&nesqp->lock, qplockflags);
@@ -2984,7 +2984,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 						nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
 								" need ae to finish up, original_last_aeq = 0x%04X."
 								" last_aeq = 0x%04X, scheduling timer.\n",
-								nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
+								nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount),
 								original_last_aeq, nesqp->last_aeq);
 						schedule_nes_timer(nesqp->cm_node, (struct sk_buff *) nesqp, NES_TIMER_TYPE_CLOSE, 1, 0);
 					}
@@ -2994,27 +2994,27 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 					nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
 							" need ae to finish up, original_last_aeq = 0x%04X."
 							" last_aeq = 0x%04X.\n",
-							nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
+							nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount),
 							original_last_aeq, nesqp->last_aeq);
 				}
 			}
 		} else {
 			nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"
 					" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
-					nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
+					nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount),
 					original_last_aeq, nesqp->last_aeq);
 		}
 	} else {
 		nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"
 				" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
-				nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
+				nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount),
 				original_last_aeq, nesqp->last_aeq);
 	}
 
 	err = 0;
 
 	nes_debug(NES_DBG_MOD_QP, "QP%u Leaving, refcount=%d\n",
-			nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
+			nesqp->hwqp.qp_id, refcount_read(&nesqp->refcount));
 
 	return err;
 }
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index e02a566..570095b 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -35,6 +35,8 @@
 #ifndef NES_VERBS_H
 #define NES_VERBS_H
 
+#include <linux/refcount.h>
+
 struct nes_device;
 
 #define NES_MAX_USER_DB_REGIONS  4096
@@ -59,7 +61,7 @@ struct nes_ucontext {
 	struct list_head   cq_reg_mem_list;
 	struct list_head   qp_reg_mem_list;
 	u32                mcrqf;
-	atomic_t	   usecnt;
+	refcount_t	   usecnt;
 };
 
 struct nes_pd {
@@ -154,7 +156,7 @@ struct nes_qp {
 	u32                   hte_index;
 	u32                   last_aeq;
 	u32                   qp_mem_size;
-	atomic_t              refcount;
+	refcount_t              refcount;
 	atomic_t              close_timer_started;
 	u32                   mmap_sq_db_index;
 	u32                   mmap_rq_db_index;
diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c
index 2c3c935..3c65ce6 100644
--- a/drivers/infiniband/hw/qib/qib_keys.c
+++ b/drivers/infiniband/hw/qib/qib_keys.c
@@ -172,7 +172,7 @@ int qib_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge,
 		mr = rcu_dereference(dev->dma_mr);
 		if (!mr)
 			goto bail;
-		if (unlikely(!atomic_inc_not_zero(&mr->refcount)))
+		if (unlikely(!refcount_inc_not_zero(&mr->refcount)))
 			goto bail;
 		rcu_read_unlock();
 
@@ -194,7 +194,7 @@ int qib_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge,
 	if (unlikely(vaddr < mr->iova || off + len > mr->length ||
 		     (mr->access_flags & acc) == 0))
 		goto bail;
-	if (unlikely(!atomic_inc_not_zero(&mr->refcount)))
+	if (unlikely(!refcount_inc_not_zero(&mr->refcount)))
 		goto bail;
 	rcu_read_unlock();
 
diff --git a/drivers/infiniband/sw/rdmavt/mr.c b/drivers/infiniband/sw/rdmavt/mr.c
index 52fd152..5ffb63a 100644
--- a/drivers/infiniband/sw/rdmavt/mr.c
+++ b/drivers/infiniband/sw/rdmavt/mr.c
@@ -141,7 +141,7 @@ static int rvt_init_mregion(struct rvt_mregion *mr, struct ib_pd *pd,
 	}
 	init_completion(&mr->comp);
 	/* count returning the ptr to user */
-	atomic_set(&mr->refcount, 1);
+	refcount_set(&mr->refcount, 1);
 	atomic_set(&mr->lkey_invalid, 0);
 	mr->pd = pd;
 	mr->max_segs = count;
@@ -446,7 +446,7 @@ int rvt_dereg_mr(struct ib_mr *ibmr)
 	if (!timeout) {
 		rvt_pr_err(rdi,
 			   "rvt_dereg_mr timeout mr %p pd %p refcount %u\n",
-			   mr, mr->mr.pd, atomic_read(&mr->mr.refcount));
+			   mr, mr->mr.pd, refcount_read(&mr->mr.refcount));
 		rvt_get_mr(&mr->mr);
 		ret = -EBUSY;
 		goto out;
@@ -678,7 +678,7 @@ int rvt_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
 	u32 ps;
 	struct rvt_dev_info *rdi = ib_to_rvt(ibfmr->device);
 
-	i = atomic_read(&fmr->mr.refcount);
+	i = refcount_read(&fmr->mr.refcount);
 	if (i > 2)
 		return -EBUSY;
 
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
index 2a13ac6..d009389 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -600,7 +600,7 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
 
 		/* take qp out the hash and wait for it to be unused */
 		rvt_remove_qp(rdi, qp);
-		wait_event(qp->wait, !atomic_read(&qp->refcount));
+		wait_event(qp->wait, !refcount_read(&qp->refcount));
 
 		/* grab the lock b/c it was locked at call time */
 		spin_lock_irq(&qp->r_lock);
@@ -777,7 +777,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		spin_lock_init(&qp->s_hlock);
 		spin_lock_init(&qp->s_lock);
 		spin_lock_init(&qp->r_rq.lock);
-		atomic_set(&qp->refcount, 0);
+		refcount_set(&qp->refcount, 0);
 		atomic_set(&qp->local_ops_pending, 0);
 		init_waitqueue_head(&qp->wait);
 		init_timer(&qp->s_timer);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index da12717..b302167 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -42,6 +42,7 @@
 #include <linux/kref.h>
 #include <linux/if_infiniband.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 
 #include <net/neighbour.h>
 #include <net/sch_generic.h>
@@ -444,7 +445,7 @@ struct ipoib_neigh {
 	struct list_head    list;
 	struct ipoib_neigh __rcu *hnext;
 	struct rcu_head     rcu;
-	atomic_t	    refcnt;
+	refcount_t	    refcnt;
 	unsigned long       alive;
 };
 
@@ -454,7 +455,7 @@ struct ipoib_neigh {
 void ipoib_neigh_dtor(struct ipoib_neigh *neigh);
 static inline void ipoib_neigh_put(struct ipoib_neigh *neigh)
 {
-	if (atomic_dec_and_test(&neigh->refcnt))
+	if (refcount_dec_and_test(&neigh->refcnt))
 		ipoib_neigh_dtor(neigh);
 }
 struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 3ce0765..2568f5b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1226,7 +1226,7 @@ struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr)
 	     neigh = rcu_dereference_bh(neigh->hnext)) {
 		if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {
 			/* found, take one ref on behalf of the caller */
-			if (!atomic_inc_not_zero(&neigh->refcnt)) {
+			if (!refcount_inc_not_zero(&neigh->refcnt)) {
 				/* deleted */
 				neigh = NULL;
 				goto out_unlock;
@@ -1328,7 +1328,7 @@ static struct ipoib_neigh *ipoib_neigh_ctor(u8 *daddr,
 	INIT_LIST_HEAD(&neigh->list);
 	ipoib_cm_set(neigh, NULL);
 	/* one ref on behalf of the caller */
-	atomic_set(&neigh->refcnt, 1);
+	refcount_set(&neigh->refcnt, 1);
 
 	return neigh;
 }
@@ -1360,7 +1360,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
 					       lockdep_is_held(&priv->lock))) {
 		if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {
 			/* found, take one ref on behalf of the caller */
-			if (!atomic_inc_not_zero(&neigh->refcnt)) {
+			if (!refcount_inc_not_zero(&neigh->refcnt)) {
 				/* deleted */
 				neigh = NULL;
 				break;
@@ -1375,7 +1375,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
 		goto out_unlock;
 
 	/* one ref on behalf of the hash table */
-	atomic_inc(&neigh->refcnt);
+	refcount_inc(&neigh->refcnt);
 	neigh->alive = jiffies;
 	/* put in hash */
 	rcu_assign_pointer(neigh->hnext,
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 0ae5536..446a353 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -43,6 +43,7 @@
 #include <linux/radix-tree.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
+#include <linux/refcount.h>
 
 #include <linux/mlx5/device.h>
 #include <linux/mlx5/doorbell.h>
@@ -387,7 +388,7 @@ enum mlx5_res_type {
 
 struct mlx5_core_rsc_common {
 	enum mlx5_res_type	res;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 };
 
@@ -400,7 +401,7 @@ struct mlx5_core_srq {
 	int		wqe_shift;
 	void (*event)	(struct mlx5_core_srq *, enum mlx5_event);
 
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 };
 
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
index 1beab55..14e8628 100644
--- a/include/rdma/ib_addr.h
+++ b/include/rdma/ib_addr.h
@@ -41,6 +41,7 @@
 #include <linux/inetdevice.h>
 #include <linux/socket.h>
 #include <linux/if_vlan.h>
+#include <linux/refcount.h>
 #include <net/ipv6.h>
 #include <net/if_inet6.h>
 #include <net/ip.h>
@@ -50,7 +51,7 @@
 #include <net/net_namespace.h>
 
 struct rdma_addr_client {
-	atomic_t refcount;
+	refcount_t refcount;
 	struct completion comp;
 };
 
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 958a24d..5eae1a0 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -58,6 +58,7 @@
 
 #include <linux/if_link.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/mmu_notifier.h>
 #include <linux/uaccess.h>
 
@@ -1389,7 +1390,7 @@ struct ib_pd {
 	u32			flags;
 	struct ib_device       *device;
 	struct ib_uobject      *uobject;
-	atomic_t          	usecnt; /* count all resources */
+	refcount_t          	usecnt; /* count all resources */
 
 	u32			unsafe_global_rkey;
 
@@ -1401,7 +1402,7 @@ struct ib_pd {
 
 struct ib_xrcd {
 	struct ib_device       *device;
-	atomic_t		usecnt; /* count all exposed resources */
+	refcount_t		usecnt; /* count all exposed resources */
 	struct inode	       *inode;
 
 	struct mutex		tgt_qp_mutex;
@@ -1429,7 +1430,7 @@ struct ib_cq {
 	void                  (*event_handler)(struct ib_event *, void *);
 	void                   *cq_context;
 	int               	cqe;
-	atomic_t          	usecnt; /* count number of work queues */
+	refcount_t          	usecnt; /* count number of work queues */
 	enum ib_poll_context	poll_ctx;
 	struct ib_wc		*wc;
 	union {
@@ -1445,7 +1446,7 @@ struct ib_srq {
 	void		      (*event_handler)(struct ib_event *, void *);
 	void		       *srq_context;
 	enum ib_srq_type	srq_type;
-	atomic_t		usecnt;
+	refcount_t		usecnt;
 
 	union {
 		struct {
@@ -1476,7 +1477,7 @@ struct ib_wq {
 	u32		wq_num;
 	enum ib_wq_state       state;
 	enum ib_wq_type	wq_type;
-	atomic_t		usecnt;
+	refcount_t		usecnt;
 };
 
 struct ib_wq_init_attr {
@@ -1501,7 +1502,7 @@ struct ib_wq_attr {
 struct ib_rwq_ind_table {
 	struct ib_device	*device;
 	struct ib_uobject      *uobject;
-	atomic_t		usecnt;
+	refcount_t		usecnt;
 	u32		ind_tbl_num;
 	u32		log_ind_tbl_size;
 	struct ib_wq	**ind_tbl;
@@ -1531,7 +1532,7 @@ struct ib_qp {
 	struct list_head	xrcd_list;
 
 	/* count times opened, mcast attaches, flow attaches */
-	atomic_t		usecnt;
+	refcount_t		usecnt;
 	struct list_head	open_list;
 	struct ib_qp           *real_qp;
 	struct ib_uobject      *uobject;
diff --git a/include/rdma/rdmavt_mr.h b/include/rdma/rdmavt_mr.h
index de59de2..f6aa67b 100644
--- a/include/rdma/rdmavt_mr.h
+++ b/include/rdma/rdmavt_mr.h
@@ -83,7 +83,7 @@ struct rvt_mregion {
 	u8  lkey_published;     /* in global table */
 	atomic_t lkey_invalid;	/* true if current lkey is invalid */
 	struct completion comp; /* complete when refcount goes to zero */
-	atomic_t refcount;
+	refcount_t refcount;
 	struct rvt_segarray *map[0];    /* the segments */
 };
 
@@ -123,13 +123,13 @@ struct rvt_sge_state {
 
 static inline void rvt_put_mr(struct rvt_mregion *mr)
 {
-	if (unlikely(atomic_dec_and_test(&mr->refcount)))
+	if (unlikely(refcount_dec_and_test(&mr->refcount)))
 		complete(&mr->comp);
 }
 
 static inline void rvt_get_mr(struct rvt_mregion *mr)
 {
-	atomic_inc(&mr->refcount);
+	refcount_inc(&mr->refcount);
 }
 
 static inline void rvt_put_ss(struct rvt_sge_state *ss)
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h
index f3dbd15..1c0b021f 100644
--- a/include/rdma/rdmavt_qp.h
+++ b/include/rdma/rdmavt_qp.h
@@ -304,7 +304,7 @@ struct rvt_qp {
 	u8 s_draining;
 
 	/* start of read/write fields */
-	atomic_t refcount ____cacheline_aligned_in_smp;
+	refcount_t refcount ____cacheline_aligned_in_smp;
 	wait_queue_head_t wait;
 
 	struct rvt_ack_entry *s_ack_queue;
@@ -472,7 +472,7 @@ static inline struct rvt_rwqe *rvt_get_rwqe_ptr(struct rvt_rq *rq, unsigned n)
  */
 static inline void rvt_get_qp(struct rvt_qp *qp)
 {
-	atomic_inc(&qp->refcount);
+	refcount_inc(&qp->refcount);
 }
 
 /**
@@ -481,7 +481,7 @@ static inline void rvt_get_qp(struct rvt_qp *qp)
  */
 static inline void rvt_put_qp(struct rvt_qp *qp)
 {
-	if (qp && atomic_dec_and_test(&qp->refcount))
+	if (qp && refcount_dec_and_test(&qp->refcount))
 		wake_up(&qp->wait);
 }
 
-- 
2.7.4

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

* [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (17 preceding siblings ...)
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 18/18] drivers: infiniband " Elena Reshetova
@ 2017-01-18 10:30 ` Greg KH
  2017-01-18 20:06   ` Kees Cook
  2017-01-23  7:52   ` [kernel-hardening] " Reshetova, Elena
  2017-01-18 21:52 ` [kernel-hardening] " Eric Biggers
  19 siblings, 2 replies; 46+ messages in thread
From: Greg KH @ 2017-01-18 10:30 UTC (permalink / raw)
  To: Elena Reshetova
  Cc: kernel-hardening, keescook, arnd, tglx, mingo, h.peter.anvin,
	peterz, will.deacon, dwindsor

On Wed, Jan 18, 2017 at 11:11:29AM +0200, Elena Reshetova wrote:
> Changes since v1:
>  - kref INIT fixes are moved to a proper separate commit
>  - Peter's commits are now properly integrated into series 
>  - various small fixes are incorporated based on testing
>    results and feedback
> 
> This patch series is build on top of Peter's Zijlstra patches
> that provide refcount_t type and API definition.
> The rest of patches convert various places of kernel subsystems
> where atomic_t was used for reference counting to new refcount_t type and API.
> By doing this, we make sure that underflows and overflows
> cannot occur in these places and therefore no use-after-free situation
> can be created and misused by an attacker.

Your first 7 patches are fine, and most of them are already in the tip
tree and getting use in linux-next now.  I'd recommend submitting the
remaining one(s?) that are not there yet to be included, that will get
refcount_t into 4.11-rc1.

Then comes the real work :)

You will need to break up the remaining patches into "one-per-type" and
start submitting them to the various submaintainers for inclusion.  You
can do that once 4.11-rc1 is out.  That's going to be a lot of different
patches, and your patch-maintaince skills are going to be tested here...

With those submissions, lots of them will start to trickly into
linux-next and start to show up in 4.12-rc1.  You'll then need to
refresh your patchset, drop the ones that were accepted, and do it all
over again.  If some maintainers are just ignoring you, you'll have to
go through some other tree for them (I can take the driver ones through
my driver tree.)

It's going to be work, but is totally doable.  I recommend setting up a
separate git or quilt tree that can get included into linux-next and
kbuild for testing and refreshing as the patches start to flow upstream.

Kernel development isn't always a lot of coding, it's primarily dealing
with stuff like this, welcome to the club :)

hope this helps,

greg k-h

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

* [kernel-hardening] Re: [RFCv2 PATCH 09/18] net: convert from atomic_t to refcount_t
  2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 09/18] net: " Elena Reshetova
@ 2017-01-18 18:39   ` David Windsor
  2017-01-19  1:11     ` Kees Cook
  0 siblings, 1 reply; 46+ messages in thread
From: David Windsor @ 2017-01-18 18:39 UTC (permalink / raw)
  To: Elena Reshetova
  Cc: kernel-hardening, Kees Cook, Arnd Bergmann, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Peter Zijlstra, Will Deacon,
	Greg KH, Hans Liljestrand

The relevant part of the patch has been cut off, but it appears that
you've fixed some of the issues we identified earlier as corner cases
as to reference counting in net/.  In particular, inetpeer.c has its
own garbage collection system in place which frees shared objects when
their reference count became -1 (rather than 0).  The proposed
solution was to do a global +1 on this refcounting scheme, then
replace unsupported atomic_*() functions with appropriate refcount_*()
calls.

When submitting this to netdev, it may make sense to separate out
these changes: first, do a global +1 (while still using atomic_t),
then convert to refcount_t.  I'm already working on this now, but I
didn't know if you wanted to follow this approach or not.

Thanks,
David

On Wed, Jan 18, 2017 at 4:11 AM, Elena Reshetova
<elena.reshetova@intel.com> wrote:
> refcount_t type and corresponding API should be
> used instead of atomic_t when the variable is used as
> a reference counter. Convert the cases found.
>
> Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
> Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  crypto/algif_aead.c                                |  2 +-
>  drivers/atm/fore200e.c                             | 13 +++------
>  drivers/atm/he.c                                   |  2 +-
>  drivers/atm/idt77252.c                             |  4 +--
>  drivers/infiniband/hw/nes/nes_cm.c                 |  4 +--
>  drivers/isdn/mISDN/socket.c                        |  2 +-
>  drivers/net/rionet.c                               |  2 +-
>  drivers/net/vxlan.c                                | 10 +++----
>  drivers/net/wireless/intel/ipw2x00/libipw_rx.c     |  8 ++---
>  drivers/net/wireless/intel/ipw2x00/libipw_tx.c     |  4 +--
>  .../net/wireless/intersil/hostap/hostap_80211_rx.c |  8 ++---
>  .../net/wireless/intersil/hostap/hostap_80211_tx.c |  4 +--
>  drivers/s390/net/ctcm_main.c                       | 26 ++++++++---------
>  drivers/s390/net/netiucv.c                         | 10 +++----
>  drivers/s390/net/qeth_core_main.c                  |  4 +--
>  drivers/scsi/cxgbi/libcxgbi.h                      |  2 +-
>  drivers/staging/rtl8192e/rtllib_rx.c               |  8 ++---
>  drivers/staging/rtl8192e/rtllib_tx.c               |  4 +--
>  .../staging/rtl8192u/ieee80211/ieee80211_crypt.c   |  2 +-
>  .../staging/rtl8192u/ieee80211/ieee80211_crypt.h   |  3 +-
>  drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c  |  8 ++---
>  drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c  |  4 +--
>  include/linux/atmdev.h                             |  9 +++---
>  include/linux/ceph/libceph.h                       |  3 +-
>  include/linux/ceph/osd_client.h                    |  3 +-
>  include/linux/ceph/pagelist.h                      |  6 ++--
>  include/linux/filter.h                             |  3 +-
>  include/linux/igmp.h                               |  3 +-
>  include/linux/inetdevice.h                         | 11 +++----
>  include/linux/netpoll.h                            |  3 +-
>  include/linux/skbuff.h                             | 23 ++++++++-------
>  include/linux/sunrpc/auth.h                        |  8 ++---
>  include/linux/sunrpc/auth_gss.h                    |  3 +-
>  include/net/addrconf.h                             | 14 ++++-----
>  include/net/af_unix.h                              |  3 +-
>  include/net/arp.h                                  |  2 +-
>  include/net/ax25.h                                 | 20 ++++++-------
>  include/net/bluetooth/hci_core.h                   | 10 +++----
>  include/net/bluetooth/rfcomm.h                     |  8 +++--
>  include/net/calipso.h                              |  4 +--
>  include/net/cipso_ipv4.h                           |  3 +-
>  include/net/dn_fib.h                               |  5 ++--
>  include/net/fib_rules.h                            |  7 +++--
>  include/net/if_inet6.h                             |  9 +++---
>  include/net/inet_frag.h                            |  4 +--
>  include/net/inet_hashtables.h                      |  4 +--
>  include/net/inetpeer.h                             |  4 +--
>  include/net/ip_fib.h                               |  7 +++--
>  include/net/ip_vs.h                                | 24 ++++++++-------
>  include/net/ipv6.h                                 |  7 +++--
>  include/net/ipx.h                                  | 13 +++++----
>  include/net/lapb.h                                 |  3 +-
>  include/net/lib80211.h                             |  2 +-
>  include/net/llc.h                                  |  6 ++--
>  include/net/lwtunnel.h                             |  7 +++--
>  include/net/ndisc.h                                |  2 +-
>  include/net/neighbour.h                            | 15 +++++-----
>  include/net/net_namespace.h                        |  3 +-
>  include/net/netfilter/br_netfilter.h               |  2 +-
>  include/net/netfilter/nf_conntrack_expect.h        |  4 ++-
>  include/net/netfilter/nf_conntrack_timeout.h       |  3 +-
>  include/net/netlabel.h                             |  8 ++---
>  include/net/netrom.h                               | 13 +++++----
>  include/net/request_sock.h                         |  9 +++---
>  include/net/sch_generic.h                          |  3 +-
>  include/net/sctp/auth.h                            |  5 ++--
>  include/net/sctp/structs.h                         |  8 ++---
>  include/net/sock.h                                 | 25 ++++++++--------
>  include/net/vxlan.h                                |  2 +-
>  include/net/x25.h                                  | 15 +++++-----
>  include/net/xfrm.h                                 | 21 ++++++-------
>  net/atm/br2684.c                                   |  2 +-
>  net/atm/clip.c                                     |  8 ++---
>  net/atm/common.c                                   | 10 +++----
>  net/atm/lec.c                                      | 11 +++----
>  net/atm/lec_arpc.h                                 |  2 +-
>  net/atm/mpc.c                                      |  4 +--
>  net/atm/mpoa_caches.c                              | 26 ++++++++---------
>  net/atm/mpoa_caches.h                              |  5 ++--
>  net/atm/pppoatm.c                                  |  2 +-
>  net/atm/proc.c                                     |  4 +--
>  net/atm/raw.c                                      |  2 +-
>  net/atm/resources.c                                |  2 +-
>  net/atm/signaling.c                                |  2 +-
>  net/ax25/af_ax25.c                                 |  2 +-
>  net/ax25/ax25_route.c                              |  2 +-
>  net/ax25/ax25_uid.c                                |  2 +-
>  net/bluetooth/a2mp.c                               |  4 +--
>  net/bluetooth/af_bluetooth.c                       |  2 +-
>  net/bluetooth/hci_conn.c                           |  4 +--
>  net/bluetooth/rfcomm/core.c                        |  4 +--
>  net/bluetooth/rfcomm/sock.c                        |  2 +-
>  net/bridge/br_netfilter_hooks.c                    |  4 +--
>  net/bridge/br_private.h                            |  3 +-
>  net/bridge/br_vlan.c                               |  8 ++---
>  net/caif/caif_socket.c                             |  2 +-
>  net/ceph/osd_client.c                              | 16 +++++-----
>  net/ceph/pagelist.c                                |  2 +-
>  net/ceph/snapshot.c                                |  6 ++--
>  net/core/datagram.c                                | 10 +++----
>  net/core/dev.c                                     | 10 +++----
>  net/core/dst.c                                     |  7 +----
>  net/core/fib_rules.c                               |  4 +--
>  net/core/filter.c                                  |  6 ++--
>  net/core/neighbour.c                               | 22 +++++++-------
>  net/core/net-sysfs.c                               |  2 +-
>  net/core/net_namespace.c                           |  4 +--
>  net/core/netpoll.c                                 | 10 +++----
>  net/core/pktgen.c                                  | 16 +++++-----
>  net/core/rtnetlink.c                               |  2 +-
>  net/core/skbuff.c                                  | 34 +++++++++++-----------
>  net/core/sock.c                                    | 30 +++++++++----------
>  net/dccp/ipv6.c                                    |  2 +-
>  net/decnet/dn_fib.c                                |  6 ++--
>  net/decnet/dn_neigh.c                              |  2 +-
>  net/ipv4/af_inet.c                                 |  2 +-
>  net/ipv4/cipso_ipv4.c                              | 16 +++++-----
>  net/ipv4/devinet.c                                 |  2 +-
>  net/ipv4/fib_semantics.c                           |  2 +-
>  net/ipv4/fib_trie.c                                |  2 +-
>  net/ipv4/igmp.c                                    | 10 +++----
>  net/ipv4/inet_connection_sock.c                    |  2 +-
>  net/ipv4/inet_fragment.c                           | 14 ++++-----
>  net/ipv4/inet_hashtables.c                         |  4 +--
>  net/ipv4/inet_timewait_sock.c                      |  8 ++---
>  net/ipv4/inetpeer.c                                | 18 ++++++------
>  net/ipv4/ip_fragment.c                             |  2 +-
>  net/ipv4/ip_output.c                               |  6 ++--
>  net/ipv4/netfilter/ipt_CLUSTERIP.c                 | 19 ++++++------
>  net/ipv4/ping.c                                    |  4 +--
>  net/ipv4/raw.c                                     |  2 +-
>  net/ipv4/syncookies.c                              |  2 +-
>  net/ipv4/tcp.c                                     |  4 +--
>  net/ipv4/tcp_fastopen.c                            |  2 +-
>  net/ipv4/tcp_ipv4.c                                |  4 +--
>  net/ipv4/tcp_offload.c                             |  2 +-
>  net/ipv4/tcp_output.c                              | 13 ++++-----
>  net/ipv4/udp.c                                     |  6 ++--
>  net/ipv4/udp_diag.c                                |  4 +--
>  net/ipv6/addrconf.c                                |  4 +--
>  net/ipv6/addrlabel.c                               |  9 +++---
>  net/ipv6/anycast.c                                 |  6 ++--
>  net/ipv6/calipso.c                                 | 16 +++++-----
>  net/ipv6/datagram.c                                |  2 +-
>  net/ipv6/exthdrs.c                                 |  4 +--
>  net/ipv6/inet6_hashtables.c                        |  4 +--
>  net/ipv6/ip6_output.c                              |  4 +--
>  net/ipv6/ipv6_sockglue.c                           |  2 +-
>  net/ipv6/mcast.c                                   | 18 ++++++------
>  net/ipv6/syncookies.c                              |  2 +-
>  net/ipv6/tcp_ipv6.c                                |  6 ++--
>  net/ipv6/udp.c                                     |  2 +-
>  net/ipv6/xfrm6_input.c                             |  2 +-
>  net/ipv6/xfrm6_tunnel.c                            |  8 ++---
>  net/ipx/af_ipx.c                                   |  6 ++--
>  net/ipx/ipx_proc.c                                 |  2 +-
>  net/ipx/ipx_route.c                                |  2 +-
>  net/kcm/kcmproc.c                                  |  2 +-
>  net/key/af_key.c                                   | 10 +++----
>  net/l2tp/l2tp_core.c                               | 12 ++++----
>  net/l2tp/l2tp_core.h                               | 13 +++++----
>  net/l2tp/l2tp_debugfs.c                            |  6 ++--
>  net/l2tp/l2tp_ppp.c                                |  2 +-
>  net/lapb/lapb_iface.c                              |  6 ++--
>  net/llc/llc_conn.c                                 |  8 ++---
>  net/llc/llc_core.c                                 |  2 +-
>  net/llc/llc_sap.c                                  |  2 +-
>  net/netfilter/ipset/ip_set_hash_gen.h              | 19 ++++++------
>  net/netfilter/ipvs/ip_vs_conn.c                    | 24 +++++++--------
>  net/netfilter/ipvs/ip_vs_core.c                    |  4 +--
>  net/netfilter/ipvs/ip_vs_ctl.c                     | 24 +++++++--------
>  net/netfilter/ipvs/ip_vs_dh.c                      |  2 +-
>  net/netfilter/ipvs/ip_vs_fo.c                      |  2 +-
>  net/netfilter/ipvs/ip_vs_lblc.c                    |  4 +--
>  net/netfilter/ipvs/ip_vs_lblcr.c                   |  8 ++---
>  net/netfilter/ipvs/ip_vs_lc.c                      |  2 +-
>  net/netfilter/ipvs/ip_vs_nq.c                      |  4 +--
>  net/netfilter/ipvs/ip_vs_ovf.c                     |  2 +-
>  net/netfilter/ipvs/ip_vs_pe_sip.c                  |  2 +-
>  net/netfilter/ipvs/ip_vs_proto_sctp.c              |  2 +-
>  net/netfilter/ipvs/ip_vs_proto_tcp.c               |  2 +-
>  net/netfilter/ipvs/ip_vs_rr.c                      |  4 +--
>  net/netfilter/ipvs/ip_vs_sed.c                     |  4 +--
>  net/netfilter/ipvs/ip_vs_sh.c                      |  2 +-
>  net/netfilter/ipvs/ip_vs_wlc.c                     |  4 +--
>  net/netfilter/ipvs/ip_vs_wrr.c                     |  4 +--
>  net/netfilter/nf_conntrack_core.c                  | 26 ++++++++---------
>  net/netfilter/nf_conntrack_expect.c                | 12 ++++----
>  net/netfilter/nf_conntrack_netlink.c               | 10 +++----
>  net/netfilter/nf_conntrack_standalone.c            |  4 +--
>  net/netfilter/nfnetlink_acct.c                     | 16 +++++-----
>  net/netfilter/nfnetlink_cttimeout.c                | 12 ++++----
>  net/netfilter/nfnetlink_log.c                      | 14 +++++----
>  net/netfilter/nft_ct.c                             |  2 +-
>  net/netfilter/xt_CT.c                              |  2 +-
>  net/netfilter/xt_TPROXY.c                          |  4 +--
>  net/netlink/af_netlink.c                           | 14 ++++-----
>  net/netrom/nr_route.c                              |  6 ++--
>  net/packet/af_packet.c                             | 14 ++++-----
>  net/packet/internal.h                              |  4 ++-
>  net/phonet/socket.c                                |  4 +--
>  net/rds/ib.c                                       | 12 ++++----
>  net/rds/ib.h                                       |  2 +-
>  net/rds/ib_rdma.c                                  |  4 +--
>  net/rds/message.c                                  | 12 ++++----
>  net/rds/rdma.c                                     | 10 +++----
>  net/rds/rds.h                                      |  9 +++---
>  net/rds/recv.c                                     | 12 ++++----
>  net/rds/tcp_send.c                                 |  2 +-
>  net/rxrpc/af_rxrpc.c                               |  6 ++--
>  net/rxrpc/skbuff.c                                 | 12 ++++----
>  net/sched/em_meta.c                                |  2 +-
>  net/sched/sch_api.c                                |  8 ++---
>  net/sched/sch_atm.c                                |  2 +-
>  net/sched/sch_generic.c                            |  8 ++---
>  net/sctp/associola.c                               |  6 ++--
>  net/sctp/auth.c                                    |  4 +--
>  net/sctp/chunk.c                                   |  6 ++--
>  net/sctp/endpointola.c                             |  6 ++--
>  net/sctp/output.c                                  |  2 +-
>  net/sctp/outqueue.c                                |  2 +-
>  net/sctp/proc.c                                    |  2 +-
>  net/sctp/sm_make_chunk.c                           |  6 ++--
>  net/sctp/socket.c                                  |  6 ++--
>  net/sctp/transport.c                               |  8 ++---
>  net/sunrpc/auth.c                                  | 12 ++++----
>  net/sunrpc/auth_gss/auth_gss.c                     | 29 +++++++++---------
>  net/tipc/socket.c                                  |  2 +-
>  net/unix/af_unix.c                                 | 16 +++++-----
>  net/wireless/lib80211.c                            |  2 +-
>  net/x25/x25_link.c                                 |  2 +-
>  net/x25/x25_route.c                                |  2 +-
>  net/xfrm/xfrm_input.c                              |  4 +--
>  net/xfrm/xfrm_policy.c                             |  4 +--
>  net/xfrm/xfrm_state.c                              |  4 +--
>  235 files changed, 833 insertions(+), 791 deletions(-)
>
> diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
> index f849311..cd37cc0 100644
> --- a/crypto/algif_aead.c
> +++ b/crypto/algif_aead.c
> @@ -749,7 +749,7 @@ static void aead_sock_destruct(struct sock *sk)
>         unsigned int ivlen = crypto_aead_ivsize(
>                                 crypto_aead_reqtfm(&ctx->aead_req));
>
> -       WARN_ON(atomic_read(&sk->sk_refcnt) != 0);
> +       WARN_ON(refcount_read(&sk->sk_refcnt) != 0);
>         aead_put_sgl(sk);
>         sock_kzfree_s(sk, ctx->iv, ivlen);
>         sock_kfree_s(sk, ctx, ctx->len);
> diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
> index 637c3e6..cd39f6f 100644
> --- a/drivers/atm/fore200e.c
> +++ b/drivers/atm/fore200e.c
> @@ -924,12 +924,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
>                 else {
>                     dev_kfree_skb_any(entry->skb);
>                 }
> -#if 1
> -               /* race fixed by the above incarnation mechanism, but... */
> -               if (atomic_read(&sk_atm(vcc)->sk_wmem_alloc) < 0) {
> -                   atomic_set(&sk_atm(vcc)->sk_wmem_alloc, 0);
> -               }
> -#endif
> +
>                 /* check error condition */
>                 if (*entry->status & STATUS_ERROR)
>                     atomic_inc(&vcc->stats->tx_err);
> @@ -1130,12 +1125,12 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
>         return -ENOMEM;
>      }
>
> -    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
> +    ASSERT(refcount_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
>
>      vcc->push(vcc, skb);
>      atomic_inc(&vcc->stats->rx);
>
> -    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
> +    ASSERT(refcount_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
>
>      return 0;
>  }
> @@ -1572,7 +1567,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
>      unsigned long           flags;
>
>      ASSERT(vcc);
> -    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
> +    ASSERT(refcount_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
>      ASSERT(fore200e);
>      ASSERT(fore200e_vcc);
>
> diff --git a/drivers/atm/he.c b/drivers/atm/he.c
> index 3617659..fc1bbdb 100644
> --- a/drivers/atm/he.c
> +++ b/drivers/atm/he.c
> @@ -2395,7 +2395,7 @@ he_close(struct atm_vcc *vcc)
>                  * TBRQ, the host issues the close command to the adapter.
>                  */
>
> -               while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) &&
> +               while (((tx_inuse = refcount_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) &&
>                        (retry < MAX_RETRY)) {
>                         msleep(sleep);
>                         if (sleep < 250)
> diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
> index 471ddfd..fffdc49 100644
> --- a/drivers/atm/idt77252.c
> +++ b/drivers/atm/idt77252.c
> @@ -724,7 +724,7 @@ push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
>                 struct sock *sk = sk_atm(vcc);
>
>                 vc->estimator->cells += (skb->len + 47) / 48;
> -               if (atomic_read(&sk->sk_wmem_alloc) >
> +               if (refcount_read(&sk->sk_wmem_alloc) >
>                     (sk->sk_sndbuf >> 1)) {
>                         u32 cps = vc->estimator->maxcps;
>
> @@ -2012,7 +2012,7 @@ idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)
>                 atomic_inc(&vcc->stats->tx_err);
>                 return -ENOMEM;
>         }
> -       atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
>
>         memcpy(skb_put(skb, 52), cell, 52);
>
> diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
> index 8e70347..53eb47b 100644
> --- a/drivers/infiniband/hw/nes/nes_cm.c
> +++ b/drivers/infiniband/hw/nes/nes_cm.c
> @@ -743,7 +743,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
>
>         if (type == NES_TIMER_TYPE_SEND) {
>                 new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
> -               atomic_inc(&new_send->skb->users);
> +               refcount_inc(&new_send->skb->users);
>                 spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
>                 cm_node->send_entry = new_send;
>                 add_ref_cm_node(cm_node);
> @@ -925,7 +925,7 @@ static void nes_cm_timer_tick(unsigned long pass)
>                                                   flags);
>                                 break;
>                         }
> -                       atomic_inc(&send_entry->skb->users);
> +                       refcount_inc(&send_entry->skb->users);
>                         cm_packets_retrans++;
>                         nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
>                                   "for node %p, jiffies = %lu, time to send = "
> diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
> index 99e5f97..c5603d1 100644
> --- a/drivers/isdn/mISDN/socket.c
> +++ b/drivers/isdn/mISDN/socket.c
> @@ -155,7 +155,7 @@ mISDN_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>         copied = skb->len + MISDN_HEADER_LEN;
>         if (len < copied) {
>                 if (flags & MSG_PEEK)
> -                       atomic_dec(&skb->users);
> +                       refcount_dec(&skb->users);
>                 else
>                         skb_queue_head(&sk->sk_receive_queue, skb);
>                 return -ENOSPC;
> diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
> index 300bb14..e9f101c 100644
> --- a/drivers/net/rionet.c
> +++ b/drivers/net/rionet.c
> @@ -201,7 +201,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
>                                 rionet_queue_tx_msg(skb, ndev,
>                                         nets[rnet->mport->id].active[i]);
>                                 if (count)
> -                                       atomic_inc(&skb->users);
> +                                       refcount_inc(&skb->users);
>                                 count++;
>                         }
>         } else if (RIONET_MAC_MATCH(eth->h_dest)) {
> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> index bb70dd5..50d9ad8 100644
> --- a/drivers/net/vxlan.c
> +++ b/drivers/net/vxlan.c
> @@ -958,11 +958,11 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
>         /* The vxlan_sock is only used by dev, leaving group has
>          * no effect on other vxlan devices.
>          */
> -       if (family == AF_INET && sock4 && atomic_read(&sock4->refcnt) == 1)
> +       if (family == AF_INET && sock4 && refcount_read(&sock4->refcnt) == 1)
>                 return false;
>  #if IS_ENABLED(CONFIG_IPV6)
>         sock6 = rtnl_dereference(dev->vn6_sock);
> -       if (family == AF_INET6 && sock6 && atomic_read(&sock6->refcnt) == 1)
> +       if (family == AF_INET6 && sock6 && refcount_read(&sock6->refcnt) == 1)
>                 return false;
>  #endif
>
> @@ -999,7 +999,7 @@ static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
>
>         if (!vs)
>                 return false;
> -       if (!atomic_dec_and_test(&vs->refcnt))
> +       if (!refcount_dec_and_test(&vs->refcnt))
>                 return false;
>
>         vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id);
> @@ -2699,7 +2699,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
>         }
>
>         vs->sock = sock;
> -       atomic_set(&vs->refcnt, 1);
> +       refcount_set(&vs->refcnt, 1);
>         vs->flags = (flags & VXLAN_F_RCV_FLAGS);
>
>         spin_lock(&vn->sock_lock);
> @@ -2733,7 +2733,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
>                 spin_lock(&vn->sock_lock);
>                 vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
>                                      vxlan->cfg.dst_port, vxlan->flags);
> -               if (vs && !atomic_add_unless(&vs->refcnt, 1, 0)) {
> +               if (vs && !refcount_inc_not_zero(&vs->refcnt)) {
>                         spin_unlock(&vn->sock_lock);
>                         return -EBUSY;
>                 }
> diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
> index 6df19f0..61a5b19 100644
> --- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
> +++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
> @@ -281,9 +281,9 @@ libipw_rx_frame_decrypt(struct libipw_device *ieee, struct sk_buff *skb,
>         hdr = (struct libipw_hdr_3addr *)skb->data;
>         hdrlen = libipw_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 LIBIPW_DEBUG_DROP("decryption failed (SA=%pM) res=%d\n",
>                                      hdr->addr2, res);
> @@ -313,9 +313,9 @@ libipw_rx_frame_decrypt_msdu(struct libipw_device *ieee,
>         hdr = (struct libipw_hdr_3addr *)skb->data;
>         hdrlen = libipw_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
>                        " (SA=%pM keyidx=%d)\n", ieee->dev->name, hdr->addr2,
> diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
> index 048f1e3..c616089 100644
> --- a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
> +++ b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
> @@ -161,12 +161,12 @@ static int libipw_encrypt_fragment(struct libipw_device *ieee,
>
>         /* To encrypt, frame format is:
>          * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = 0;
>         if (crypt->ops && crypt->ops->encrypt_mpdu)
>                 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
>
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
>                        ieee->dev->name, frag->len);
> diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
> index 34dbddb..9c5cadf 100644
> --- a/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
> +++ b/drivers/net/wireless/intersil/hostap/hostap_80211_rx.c
> @@ -669,9 +669,9 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
>                 return -1;
>         }
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 printk(KERN_DEBUG "%s: decryption failed (SA=%pM) res=%d\n",
>                        local->dev->name, hdr->addr2, res);
> @@ -697,9 +697,9 @@ hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
>         hdr = (struct ieee80211_hdr *) skb->data;
>         hdrlen = hostap_80211_get_hdrlen(hdr->frame_control);
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
>                        " (SA=%pM keyidx=%d)\n",
> diff --git a/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c b/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
> index 055e11d..810e9ba 100644
> --- a/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
> +++ b/drivers/net/wireless/intersil/hostap/hostap_80211_tx.c
> @@ -359,13 +359,13 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
>
>         /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
>          * call both MSDU and MPDU encryption functions from here. */
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = 0;
>         if (crypt->ops->encrypt_msdu)
>                 res = crypt->ops->encrypt_msdu(skb, hdr_len, crypt->priv);
>         if (res == 0 && crypt->ops->encrypt_mpdu)
>                 res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 kfree_skb(skb);
>                 return NULL;
> diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
> index ac65f12..d079d02 100644
> --- a/drivers/s390/net/ctcm_main.c
> +++ b/drivers/s390/net/ctcm_main.c
> @@ -483,7 +483,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
>                         spin_unlock_irqrestore(&ch->collect_lock, saveflags);
>                         return -EBUSY;
>                 } else {
> -                       atomic_inc(&skb->users);
> +                       refcount_inc(&skb->users);
>                         header.length = l;
>                         header.type = skb->protocol;
>                         header.unused = 0;
> @@ -500,7 +500,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
>          * Protect skb against beeing free'd by upper
>          * layers.
>          */
> -       atomic_inc(&skb->users);
> +       refcount_inc(&skb->users);
>         ch->prof.txlen += skb->len;
>         header.length = skb->len + LL_HEADER_LENGTH;
>         header.type = skb->protocol;
> @@ -517,14 +517,14 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
>         if (hi) {
>                 nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
>                 if (!nskb) {
> -                       atomic_dec(&skb->users);
> +                       refcount_dec(&skb->users);
>                         skb_pull(skb, LL_HEADER_LENGTH + 2);
>                         ctcm_clear_busy(ch->netdev);
>                         return -ENOMEM;
>                 } else {
>                         memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
> -                       atomic_inc(&nskb->users);
> -                       atomic_dec(&skb->users);
> +                       refcount_inc(&nskb->users);
> +                       refcount_dec(&skb->users);
>                         dev_kfree_skb_irq(skb);
>                         skb = nskb;
>                 }
> @@ -542,7 +542,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
>                          * Remove our header. It gets added
>                          * again on retransmit.
>                          */
> -                       atomic_dec(&skb->users);
> +                       refcount_dec(&skb->users);
>                         skb_pull(skb, LL_HEADER_LENGTH + 2);
>                         ctcm_clear_busy(ch->netdev);
>                         return -ENOMEM;
> @@ -553,7 +553,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
>                 ch->ccw[1].count = skb->len;
>                 skb_copy_from_linear_data(skb,
>                                 skb_put(ch->trans_skb, skb->len), skb->len);
> -               atomic_dec(&skb->users);
> +               refcount_dec(&skb->users);
>                 dev_kfree_skb_irq(skb);
>                 ccw_idx = 0;
>         } else {
> @@ -679,7 +679,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
>
>         if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
>                 spin_lock_irqsave(&ch->collect_lock, saveflags);
> -               atomic_inc(&skb->users);
> +               refcount_inc(&skb->users);
>                 p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
>
>                 if (!p_header) {
> @@ -716,7 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
>          * Protect skb against beeing free'd by upper
>          * layers.
>          */
> -       atomic_inc(&skb->users);
> +       refcount_inc(&skb->users);
>
>         /*
>          * IDAL support in CTCM is broken, so we have to
> @@ -729,8 +729,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
>                         goto nomem_exit;
>                 } else {
>                         memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
> -                       atomic_inc(&nskb->users);
> -                       atomic_dec(&skb->users);
> +                       refcount_inc(&nskb->users);
> +                       refcount_dec(&skb->users);
>                         dev_kfree_skb_irq(skb);
>                         skb = nskb;
>                 }
> @@ -810,7 +810,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
>                 ch->trans_skb->len = 0;
>                 ch->ccw[1].count = skb->len;
>                 memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
> -               atomic_dec(&skb->users);
> +               refcount_dec(&skb->users);
>                 dev_kfree_skb_irq(skb);
>                 ccw_idx = 0;
>                 CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
> @@ -855,7 +855,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
>                         "%s(%s): MEMORY allocation ERROR\n",
>                         CTCM_FUNTAIL, ch->id);
>         rc = -ENOMEM;
> -       atomic_dec(&skb->users);
> +       refcount_dec(&skb->users);
>         dev_kfree_skb_any(skb);
>         fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
>  done:
> diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
> index 3f85b97..44fd71c 100644
> --- a/drivers/s390/net/netiucv.c
> +++ b/drivers/s390/net/netiucv.c
> @@ -743,7 +743,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
>         conn->prof.tx_pending--;
>         if (single_flag) {
>                 if ((skb = skb_dequeue(&conn->commit_queue))) {
> -                       atomic_dec(&skb->users);
> +                       refcount_dec(&skb->users);
>                         if (privptr) {
>                                 privptr->stats.tx_packets++;
>                                 privptr->stats.tx_bytes +=
> @@ -767,7 +767,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
>                 txbytes += skb->len;
>                 txpackets++;
>                 stat_maxcq++;
> -               atomic_dec(&skb->users);
> +               refcount_dec(&skb->users);
>                 dev_kfree_skb_any(skb);
>         }
>         if (conn->collect_len > conn->prof.maxmulti)
> @@ -959,7 +959,7 @@ static void netiucv_purge_skb_queue(struct sk_buff_head *q)
>         struct sk_buff *skb;
>
>         while ((skb = skb_dequeue(q))) {
> -               atomic_dec(&skb->users);
> +               refcount_dec(&skb->users);
>                 dev_kfree_skb_any(skb);
>         }
>  }
> @@ -1177,7 +1177,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
>                         IUCV_DBF_TEXT(data, 2,
>                                       "EBUSY from netiucv_transmit_skb\n");
>                 } else {
> -                       atomic_inc(&skb->users);
> +                       refcount_inc(&skb->users);
>                         skb_queue_tail(&conn->collect_queue, skb);
>                         conn->collect_len += l;
>                         rc = 0;
> @@ -1247,7 +1247,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
>                 } else {
>                         if (copied)
>                                 dev_kfree_skb(skb);
> -                       atomic_inc(&nskb->users);
> +                       refcount_inc(&nskb->users);
>                         skb_queue_tail(&conn->commit_queue, nskb);
>                 }
>         }
> diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
> index e335583..e6ebcd7 100644
> --- a/drivers/s390/net/qeth_core_main.c
> +++ b/drivers/s390/net/qeth_core_main.c
> @@ -1239,7 +1239,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
>                                 iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR);
>                         }
>                 }
> -               atomic_dec(&skb->users);
> +               refcount_dec(&skb->users);
>                 dev_kfree_skb_any(skb);
>                 skb = skb_dequeue(&buf->skb_list);
>         }
> @@ -3970,7 +3970,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
>         int flush_cnt = 0, hdr_len, large_send = 0;
>
>         buffer = buf->buffer;
> -       atomic_inc(&skb->users);
> +       refcount_inc(&skb->users);
>         skb_queue_tail(&buf->skb_list, skb);
>
>         /*check first on TSO ....*/
> diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
> index 18e0ea8..9584b062 100644
> --- a/drivers/scsi/cxgbi/libcxgbi.h
> +++ b/drivers/scsi/cxgbi/libcxgbi.h
> @@ -378,7 +378,7 @@ static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk,
>          * just one user currently so we use atomic_set rather than skb_get
>          * to avoid the atomic op.
>          */
> -       atomic_set(&skb->users, 2);
> +       refcount_set(&skb->users, 2);
>
>         if (!csk->wr_pending_head)
>                 csk->wr_pending_head = skb;
> diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
> index e5ba7d1..2f72ee5 100644
> --- a/drivers/staging/rtl8192e/rtllib_rx.c
> +++ b/drivers/staging/rtl8192e/rtllib_rx.c
> @@ -310,9 +310,9 @@ rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
>         hdr = (struct rtllib_hdr_4addr *) skb->data;
>         hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 netdev_dbg(ieee->dev, "decryption failed (SA= %pM) res=%d\n",
>                            hdr->addr2, res);
> @@ -350,9 +350,9 @@ rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb,
>         hdr = (struct rtllib_hdr_4addr *) skb->data;
>         hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 netdev_dbg(ieee->dev,
>                            "MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n",
> diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
> index 78a3ad5..796580a 100644
> --- a/drivers/staging/rtl8192e/rtllib_tx.c
> +++ b/drivers/staging/rtl8192e/rtllib_tx.c
> @@ -190,14 +190,14 @@ int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
>         /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
>          * call both MSDU and MPDU encryption functions from here.
>          */
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = 0;
>         if (crypt->ops->encrypt_msdu)
>                 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
>         if (res == 0 && crypt->ops->encrypt_mpdu)
>                 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
>
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 netdev_info(ieee->dev, "%s: Encryption failed: len=%d.\n",
>                             ieee->dev->name, frag->len);
> diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
> index 9cf90d0..b6d5673 100644
> --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
> +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
> @@ -46,7 +46,7 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
>              ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
>                 entry = list_entry(ptr, struct ieee80211_crypt_data, list);
>
> -               if (atomic_read(&entry->refcnt) != 0 && !force)
> +               if (refcount_read(&entry->refcnt) != 0 && !force)
>                         continue;
>
>                 list_del(ptr);
> diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
> index 0b4ea43..01718c1 100644
> --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
> +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.h
> @@ -23,6 +23,7 @@
>  #ifndef IEEE80211_CRYPT_H
>  #define IEEE80211_CRYPT_H
>
> +#include <linux/refcount.h>
>  #include <linux/skbuff.h>
>
>  struct ieee80211_crypto_ops {
> @@ -72,7 +73,7 @@ struct ieee80211_crypt_data {
>         struct list_head list; /* delayed deletion list */
>         struct ieee80211_crypto_ops *ops;
>         void *priv;
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>  };
>
>  int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
> diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
> index 82f6543..1157a72 100644
> --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
> +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
> @@ -361,9 +361,9 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
>                 return -1;
>         }
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 IEEE80211_DEBUG_DROP(
>                         "decryption failed (SA=%pM"
> @@ -399,9 +399,9 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s
>         hdr = (struct rtl_80211_hdr_4addr *) skb->data;
>         hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
>
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
>                        " (SA=%pM keyidx=%d)\n",
> diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
> index 1ab0aea..014e53f 100644
> --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
> +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
> @@ -210,14 +210,14 @@ int ieee80211_encrypt_fragment(
>         // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
>         /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
>          * call both MSDU and MPDU encryption functions from here. */
> -       atomic_inc(&crypt->refcnt);
> +       refcount_inc(&crypt->refcnt);
>         res = 0;
>         if (crypt->ops->encrypt_msdu)
>                 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
>         if (res == 0 && crypt->ops->encrypt_mpdu)
>                 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
>
> -       atomic_dec(&crypt->refcnt);
> +       refcount_dec(&crypt->refcnt);
>         if (res < 0) {
>                 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
>                        ieee->dev->name, frag->len);
> diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
> index c1da539..0ec9bdb 100644
> --- a/include/linux/atmdev.h
> +++ b/include/linux/atmdev.h
> @@ -11,6 +11,7 @@
>  #include <linux/uio.h>
>  #include <net/sock.h>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <uapi/linux/atmdev.h>
>
>  #ifdef CONFIG_PROC_FS
> @@ -158,7 +159,7 @@ struct atm_dev {
>         struct k_atm_dev_stats stats;   /* statistics */
>         char            signal;         /* signal status (ATM_PHY_SIG_*) */
>         int             link_rate;      /* link rate (default: OC3) */
> -       atomic_t        refcnt;         /* reference count */
> +       refcount_t      refcnt;         /* reference count */
>         spinlock_t      lock;           /* protect internal members */
>  #ifdef CONFIG_PROC_FS
>         struct proc_dir_entry *proc_entry; /* proc entry */
> @@ -254,20 +255,20 @@ static inline void atm_return(struct atm_vcc *vcc,int truesize)
>
>  static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
>  {
> -       return (size + atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) <
> +       return (size + refcount_read(&sk_atm(vcc)->sk_wmem_alloc)) <
>                sk_atm(vcc)->sk_sndbuf;
>  }
>
>
>  static inline void atm_dev_hold(struct atm_dev *dev)
>  {
> -       atomic_inc(&dev->refcnt);
> +       refcount_inc(&dev->refcnt);
>  }
>
>
>  static inline void atm_dev_put(struct atm_dev *dev)
>  {
> -       if (atomic_dec_and_test(&dev->refcnt)) {
> +       if (refcount_dec_and_test(&dev->refcnt)) {
>                 BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags));
>                 if (dev->ops->dev_close)
>                         dev->ops->dev_close(dev);
> diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> index 1816c5e..26dc674 100644
> --- a/include/linux/ceph/libceph.h
> +++ b/include/linux/ceph/libceph.h
> @@ -14,6 +14,7 @@
>  #include <linux/wait.h>
>  #include <linux/writeback.h>
>  #include <linux/slab.h>
> +#include <linux/refcount.h>
>
>  #include <linux/ceph/types.h>
>  #include <linux/ceph/messenger.h>
> @@ -159,7 +160,7 @@ struct ceph_client {
>   * dirtied.
>   */
>  struct ceph_snap_context {
> -       atomic_t nref;
> +       refcount_t nref;
>         u64 seq;
>         u32 num_snaps;
>         u64 snaps[];
> diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
> index 03a6653..bd0db58 100644
> --- a/include/linux/ceph/osd_client.h
> +++ b/include/linux/ceph/osd_client.h
> @@ -5,6 +5,7 @@
>  #include <linux/kref.h>
>  #include <linux/mempool.h>
>  #include <linux/rbtree.h>
> +#include <linux/refcount.h>
>
>  #include <linux/ceph/types.h>
>  #include <linux/ceph/osdmap.h>
> @@ -28,7 +29,7 @@ typedef void (*ceph_osdc_unsafe_callback_t)(struct ceph_osd_request *, bool);
>
>  /* a given osd we're communicating with */
>  struct ceph_osd {
> -       atomic_t o_ref;
> +       refcount_t o_ref;
>         struct ceph_osd_client *o_osdc;
>         int o_osd;
>         int o_incarnation;
> diff --git a/include/linux/ceph/pagelist.h b/include/linux/ceph/pagelist.h
> index 13d71fe..75a7db2 100644
> --- a/include/linux/ceph/pagelist.h
> +++ b/include/linux/ceph/pagelist.h
> @@ -2,7 +2,7 @@
>  #define __FS_CEPH_PAGELIST_H
>
>  #include <asm/byteorder.h>
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/list.h>
>  #include <linux/types.h>
>
> @@ -13,7 +13,7 @@ struct ceph_pagelist {
>         size_t room;
>         struct list_head free_list;
>         size_t num_pages_free;
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>  };
>
>  struct ceph_pagelist_cursor {
> @@ -30,7 +30,7 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
>         pl->room = 0;
>         INIT_LIST_HEAD(&pl->free_list);
>         pl->num_pages_free = 0;
> -       atomic_set(&pl->refcnt, 1);
> +       refcount_set(&pl->refcnt, 1);
>  }
>
>  extern void ceph_pagelist_release(struct ceph_pagelist *pl);
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index a0934e6..f994406 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -7,6 +7,7 @@
>  #include <stdarg.h>
>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/compat.h>
>  #include <linux/skbuff.h>
>  #include <linux/linkage.h>
> @@ -421,7 +422,7 @@ struct bpf_prog {
>  };
>
>  struct sk_filter {
> -       atomic_t        refcnt;
> +       refcount_t      refcnt;
>         struct rcu_head rcu;
>         struct bpf_prog *prog;
>  };
> diff --git a/include/linux/igmp.h b/include/linux/igmp.h
> index 12f6fba..97caf18 100644
> --- a/include/linux/igmp.h
> +++ b/include/linux/igmp.h
> @@ -18,6 +18,7 @@
>  #include <linux/skbuff.h>
>  #include <linux/timer.h>
>  #include <linux/in.h>
> +#include <linux/refcount.h>
>  #include <uapi/linux/igmp.h>
>
>  static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
> @@ -84,7 +85,7 @@ struct ip_mc_list {
>         struct ip_mc_list __rcu *next_hash;
>         struct timer_list       timer;
>         int                     users;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         spinlock_t              lock;
>         char                    tm_running;
>         char                    reporter;
> diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
> index ee971f3..5cd9671 100644
> --- a/include/linux/inetdevice.h
> +++ b/include/linux/inetdevice.h
> @@ -11,6 +11,7 @@
>  #include <linux/timer.h>
>  #include <linux/sysctl.h>
>  #include <linux/rtnetlink.h>
> +#include <linux/refcount.h>
>
>  struct ipv4_devconf {
>         void    *sysctl;
> @@ -22,7 +23,7 @@ struct ipv4_devconf {
>
>  struct in_device {
>         struct net_device       *dev;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         int                     dead;
>         struct in_ifaddr        *ifa_list;      /* IP ifaddr chain              */
>
> @@ -212,7 +213,7 @@ static inline struct in_device *in_dev_get(const struct net_device *dev)
>         rcu_read_lock();
>         in_dev = __in_dev_get_rcu(dev);
>         if (in_dev)
> -               atomic_inc(&in_dev->refcnt);
> +               refcount_inc(&in_dev->refcnt);
>         rcu_read_unlock();
>         return in_dev;
>  }
> @@ -233,12 +234,12 @@ void in_dev_finish_destroy(struct in_device *idev);
>
>  static inline void in_dev_put(struct in_device *idev)
>  {
> -       if (atomic_dec_and_test(&idev->refcnt))
> +       if (refcount_dec_and_test(&idev->refcnt))
>                 in_dev_finish_destroy(idev);
>  }
>
> -#define __in_dev_put(idev)  atomic_dec(&(idev)->refcnt)
> -#define in_dev_hold(idev)   atomic_inc(&(idev)->refcnt)
> +#define __in_dev_put(idev)  refcount_dec(&(idev)->refcnt)
> +#define in_dev_hold(idev)   refcount_inc(&(idev)->refcnt)
>
>  #endif /* __KERNEL__ */
>
> diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
> index 1828900..27c0aaa 100644
> --- a/include/linux/netpoll.h
> +++ b/include/linux/netpoll.h
> @@ -11,6 +11,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/rcupdate.h>
>  #include <linux/list.h>
> +#include <linux/refcount.h>
>
>  union inet_addr {
>         __u32           all[4];
> @@ -34,7 +35,7 @@ struct netpoll {
>  };
>
>  struct netpoll_info {
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>
>         struct semaphore dev_lock;
>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index b53c0cf..12b8444 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -24,6 +24,7 @@
>  #include <linux/socket.h>
>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <asm/types.h>
>  #include <linux/spinlock.h>
>  #include <linux/net.h>
> @@ -243,13 +244,13 @@ struct napi_struct;
>
>  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
>  struct nf_conntrack {
> -       atomic_t use;
> +       refcount_t use;
>  };
>  #endif
>
>  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
>  struct nf_bridge_info {
> -       atomic_t                use;
> +       refcount_t              use;
>         enum {
>                 BRNF_PROTO_UNCHANGED,
>                 BRNF_PROTO_8021Q,
> @@ -809,7 +810,7 @@ struct sk_buff {
>         unsigned char           *head,
>                                 *data;
>         unsigned int            truesize;
> -       atomic_t                users;
> +       refcount_t              users;
>  };
>
>  #ifdef __KERNEL__
> @@ -938,7 +939,7 @@ struct sk_buff_fclones {
>
>         struct sk_buff  skb2;
>
> -       atomic_t        fclone_ref;
> +       refcount_t      fclone_ref;
>  };
>
>  /**
> @@ -958,7 +959,7 @@ static inline bool skb_fclone_busy(const struct sock *sk,
>         fclones = container_of(skb, struct sk_buff_fclones, skb1);
>
>         return skb->fclone == SKB_FCLONE_ORIG &&
> -              atomic_read(&fclones->fclone_ref) > 1 &&
> +              refcount_read(&fclones->fclone_ref) > 1 &&
>                fclones->skb2.sk == sk;
>  }
>
> @@ -1306,7 +1307,7 @@ static inline struct sk_buff *skb_queue_prev(const struct sk_buff_head *list,
>   */
>  static inline struct sk_buff *skb_get(struct sk_buff *skb)
>  {
> -       atomic_inc(&skb->users);
> +       refcount_inc(&skb->users);
>         return skb;
>  }
>
> @@ -1407,7 +1408,7 @@ static inline void __skb_header_release(struct sk_buff *skb)
>   */
>  static inline int skb_shared(const struct sk_buff *skb)
>  {
> -       return atomic_read(&skb->users) != 1;
> +       return refcount_read(&skb->users) != 1;
>  }
>
>  /**
> @@ -3557,25 +3558,25 @@ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr,
>  void nf_conntrack_destroy(struct nf_conntrack *nfct);
>  static inline void nf_conntrack_put(struct nf_conntrack *nfct)
>  {
> -       if (nfct && atomic_dec_and_test(&nfct->use))
> +       if (nfct && refcount_dec_and_test(&nfct->use))
>                 nf_conntrack_destroy(nfct);
>  }
>  static inline void nf_conntrack_get(struct nf_conntrack *nfct)
>  {
>         if (nfct)
> -               atomic_inc(&nfct->use);
> +               refcount_inc(&nfct->use);
>  }
>  #endif
>  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
>  static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
>  {
> -       if (nf_bridge && atomic_dec_and_test(&nf_bridge->use))
> +       if (nf_bridge && refcount_dec_and_test(&nf_bridge->use))
>                 kfree(nf_bridge);
>  }
>  static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
>  {
>         if (nf_bridge)
> -               atomic_inc(&nf_bridge->use);
> +               refcount_inc(&nf_bridge->use);
>  }
>  #endif /* CONFIG_BRIDGE_NETFILTER */
>  static inline void nf_reset(struct sk_buff *skb)
> diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
> index b1bc62b..bd36e0b 100644
> --- a/include/linux/sunrpc/auth.h
> +++ b/include/linux/sunrpc/auth.h
> @@ -15,7 +15,7 @@
>  #include <linux/sunrpc/msg_prot.h>
>  #include <linux/sunrpc/xdr.h>
>
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/rcupdate.h>
>  #include <linux/uidgid.h>
>  #include <linux/utsname.h>
> @@ -68,7 +68,7 @@ struct rpc_cred {
>  #endif
>         unsigned long           cr_expire;      /* when to gc */
>         unsigned long           cr_flags;       /* various flags */
> -       atomic_t                cr_count;       /* ref count */
> +       refcount_t              cr_count;       /* ref count */
>
>         kuid_t                  cr_uid;
>
> @@ -209,7 +209,7 @@ static inline
>  struct rpc_cred *      get_rpccred(struct rpc_cred *cred)
>  {
>         if (cred != NULL)
> -               atomic_inc(&cred->cr_count);
> +               refcount_inc(&cred->cr_count);
>         return cred;
>  }
>
> @@ -226,7 +226,7 @@ struct rpc_cred *   get_rpccred(struct rpc_cred *cred)
>  static inline struct rpc_cred *
>  get_rpccred_rcu(struct rpc_cred *cred)
>  {
> -       if (atomic_inc_not_zero(&cred->cr_count))
> +       if (refcount_inc_not_zero(&cred->cr_count))
>                 return cred;
>         return NULL;
>  }
> diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
> index 36eebc4..cebdf87 100644
> --- a/include/linux/sunrpc/auth_gss.h
> +++ b/include/linux/sunrpc/auth_gss.h
> @@ -13,6 +13,7 @@
>  #define _LINUX_SUNRPC_AUTH_GSS_H
>
>  #ifdef __KERNEL__
> +#include <linux/refcount.h>
>  #include <linux/sunrpc/auth.h>
>  #include <linux/sunrpc/svc.h>
>  #include <linux/sunrpc/gss_api.h>
> @@ -65,7 +66,7 @@ struct rpc_gss_init_res {
>   * the wire when communicating with a server. */
>
>  struct gss_cl_ctx {
> -       atomic_t                count;
> +       refcount_t              count;
>         enum rpc_gss_proc       gc_proc;
>         u32                     gc_seq;
>         spinlock_t              gc_seq_lock;
> diff --git a/include/net/addrconf.h b/include/net/addrconf.h
> index 8f998af..7caa848 100644
> --- a/include/net/addrconf.h
> +++ b/include/net/addrconf.h
> @@ -294,7 +294,7 @@ static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
>         rcu_read_lock();
>         idev = rcu_dereference(dev->ip6_ptr);
>         if (idev)
> -               atomic_inc(&idev->refcnt);
> +               refcount_inc(&idev->refcnt);
>         rcu_read_unlock();
>         return idev;
>  }
> @@ -310,36 +310,36 @@ void in6_dev_finish_destroy(struct inet6_dev *idev);
>
>  static inline void in6_dev_put(struct inet6_dev *idev)
>  {
> -       if (atomic_dec_and_test(&idev->refcnt))
> +       if (refcount_dec_and_test(&idev->refcnt))
>                 in6_dev_finish_destroy(idev);
>  }
>
>  static inline void __in6_dev_put(struct inet6_dev *idev)
>  {
> -       atomic_dec(&idev->refcnt);
> +       refcount_dec(&idev->refcnt);
>  }
>
>  static inline void in6_dev_hold(struct inet6_dev *idev)
>  {
> -       atomic_inc(&idev->refcnt);
> +       refcount_inc(&idev->refcnt);
>  }
>
>  void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
>
>  static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
>  {
> -       if (atomic_dec_and_test(&ifp->refcnt))
> +       if (refcount_dec_and_test(&ifp->refcnt))
>                 inet6_ifa_finish_destroy(ifp);
>  }
>
>  static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
>  {
> -       atomic_dec(&ifp->refcnt);
> +       refcount_dec(&ifp->refcnt);
>  }
>
>  static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
>  {
> -       atomic_inc(&ifp->refcnt);
> +       refcount_inc(&ifp->refcnt);
>  }
>
>
> diff --git a/include/net/af_unix.h b/include/net/af_unix.h
> index fd60ecc..3a385e4 100644
> --- a/include/net/af_unix.h
> +++ b/include/net/af_unix.h
> @@ -4,6 +4,7 @@
>  #include <linux/socket.h>
>  #include <linux/un.h>
>  #include <linux/mutex.h>
> +#include <linux/refcount.h>
>  #include <net/sock.h>
>
>  void unix_inflight(struct user_struct *user, struct file *fp);
> @@ -21,7 +22,7 @@ extern spinlock_t unix_table_lock;
>  extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
>
>  struct unix_address {
> -       atomic_t        refcnt;
> +       refcount_t      refcnt;
>         int             len;
>         unsigned int    hash;
>         struct sockaddr_un name[0];
> diff --git a/include/net/arp.h b/include/net/arp.h
> index 5e0f891..95cfce4 100644
> --- a/include/net/arp.h
> +++ b/include/net/arp.h
> @@ -28,7 +28,7 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32
>
>         rcu_read_lock_bh();
>         n = __ipv4_neigh_lookup_noref(dev, key);
> -       if (n && !atomic_inc_not_zero(&n->refcnt))
> +       if (n && !refcount_inc_not_zero(&n->refcnt))
>                 n = NULL;
>         rcu_read_unlock_bh();
>
> diff --git a/include/net/ax25.h b/include/net/ax25.h
> index e602f81..c4a0cf6 100644
> --- a/include/net/ax25.h
> +++ b/include/net/ax25.h
> @@ -11,7 +11,7 @@
>  #include <linux/timer.h>
>  #include <linux/list.h>
>  #include <linux/slab.h>
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <net/neighbour.h>
>  #include <net/sock.h>
>
> @@ -158,7 +158,7 @@ enum {
>
>  typedef struct ax25_uid_assoc {
>         struct hlist_node       uid_node;
> -       atomic_t                refcount;
> +       refcount_t              refcount;
>         kuid_t                  uid;
>         ax25_address            call;
>  } ax25_uid_assoc;
> @@ -167,11 +167,11 @@ typedef struct ax25_uid_assoc {
>         hlist_for_each_entry(__ax25, list, uid_node)
>
>  #define ax25_uid_hold(ax25) \
> -       atomic_inc(&((ax25)->refcount))
> +       refcount_inc(&((ax25)->refcount))
>
>  static inline void ax25_uid_put(ax25_uid_assoc *assoc)
>  {
> -       if (atomic_dec_and_test(&assoc->refcount)) {
> +       if (refcount_dec_and_test(&assoc->refcount)) {
>                 kfree(assoc);
>         }
>  }
> @@ -185,7 +185,7 @@ typedef struct {
>
>  typedef struct ax25_route {
>         struct ax25_route       *next;
> -       atomic_t                refcount;
> +       refcount_t              refcount;
>         ax25_address            callsign;
>         struct net_device       *dev;
>         ax25_digi               *digipeat;
> @@ -194,14 +194,14 @@ typedef struct ax25_route {
>
>  static inline void ax25_hold_route(ax25_route *ax25_rt)
>  {
> -       atomic_inc(&ax25_rt->refcount);
> +       refcount_inc(&ax25_rt->refcount);
>  }
>
>  void __ax25_put_route(ax25_route *ax25_rt);
>
>  static inline void ax25_put_route(ax25_route *ax25_rt)
>  {
> -       if (atomic_dec_and_test(&ax25_rt->refcount))
> +       if (refcount_dec_and_test(&ax25_rt->refcount))
>                 __ax25_put_route(ax25_rt);
>  }
>
> @@ -244,7 +244,7 @@ typedef struct ax25_cb {
>         unsigned char           window;
>         struct timer_list       timer, dtimer;
>         struct sock             *sk;            /* Backlink to socket */
> -       atomic_t                refcount;
> +       refcount_t              refcount;
>  } ax25_cb;
>
>  struct ax25_sock {
> @@ -266,11 +266,11 @@ static inline struct ax25_cb *sk_to_ax25(const struct sock *sk)
>         hlist_for_each_entry(__ax25, list, ax25_node)
>
>  #define ax25_cb_hold(__ax25) \
> -       atomic_inc(&((__ax25)->refcount))
> +       refcount_inc(&((__ax25)->refcount))
>
>  static __inline__ void ax25_cb_put(ax25_cb *ax25)
>  {
> -       if (atomic_dec_and_test(&ax25->refcount)) {
> +       if (refcount_dec_and_test(&ax25->refcount)) {
>                 kfree(ax25->digipeat);
>                 kfree(ax25);
>         }
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 90708f6..3c228fa 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -422,7 +422,7 @@ struct hci_dev {
>  struct hci_conn {
>         struct list_head list;
>
> -       atomic_t        refcnt;
> +       refcount_t      refcnt;
>
>         bdaddr_t        dst;
>         __u8            dst_type;
> @@ -942,17 +942,17 @@ static inline void hci_conn_put(struct hci_conn *conn)
>
>  static inline void hci_conn_hold(struct hci_conn *conn)
>  {
> -       BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
> +       BT_DBG("hcon %p orig refcnt %d", conn, refcount_read(&conn->refcnt));
>
> -       atomic_inc(&conn->refcnt);
> +       refcount_inc(&conn->refcnt);
>         cancel_delayed_work(&conn->disc_work);
>  }
>
>  static inline void hci_conn_drop(struct hci_conn *conn)
>  {
> -       BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
> +       BT_DBG("hcon %p orig refcnt %d", conn, refcount_read(&conn->refcnt));
>
> -       if (atomic_dec_and_test(&conn->refcnt)) {
> +       if (refcount_dec_and_test(&conn->refcnt)) {
>                 unsigned long timeo;
>
>                 switch (conn->type) {
> diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
> index 4190af5..da4acef 100644
> --- a/include/net/bluetooth/rfcomm.h
> +++ b/include/net/bluetooth/rfcomm.h
> @@ -21,6 +21,8 @@
>     SOFTWARE IS DISCLAIMED.
>  */
>
> +#include <linux/refcount.h>
> +
>  #ifndef __RFCOMM_H
>  #define __RFCOMM_H
>
> @@ -174,7 +176,7 @@ struct rfcomm_dlc {
>         struct mutex  lock;
>         unsigned long state;
>         unsigned long flags;
> -       atomic_t      refcnt;
> +       refcount_t    refcnt;
>         u8            dlci;
>         u8            addr;
>         u8            priority;
> @@ -247,12 +249,12 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
>
>  static inline void rfcomm_dlc_hold(struct rfcomm_dlc *d)
>  {
> -       atomic_inc(&d->refcnt);
> +       refcount_inc(&d->refcnt);
>  }
>
>  static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
>  {
> -       if (atomic_dec_and_test(&d->refcnt))
> +       if (refcount_dec_and_test(&d->refcnt))
>                 rfcomm_dlc_free(d);
>  }
>
> diff --git a/include/net/calipso.h b/include/net/calipso.h
> index b1b30cd..5f95b11 100644
> --- a/include/net/calipso.h
> +++ b/include/net/calipso.h
> @@ -38,7 +38,7 @@
>  #include <linux/skbuff.h>
>  #include <net/netlabel.h>
>  #include <net/request_sock.h>
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <asm/unaligned.h>
>
>  /* known doi values */
> @@ -57,7 +57,7 @@ struct calipso_doi {
>         u32 doi;
>         u32 type;
>
> -       atomic_t refcount;
> +       refcount_t refcount;
>         struct list_head list;
>         struct rcu_head rcu;
>  };
> diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
> index 3ebb168..026c7a3 100644
> --- a/include/net/cipso_ipv4.h
> +++ b/include/net/cipso_ipv4.h
> @@ -41,6 +41,7 @@
>  #include <net/netlabel.h>
>  #include <net/request_sock.h>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <asm/unaligned.h>
>
>  /* known doi values */
> @@ -85,7 +86,7 @@ struct cipso_v4_doi {
>         } map;
>         u8 tags[CIPSO_V4_TAG_MAXCNT];
>
> -       atomic_t refcount;
> +       refcount_t refcount;
>         struct list_head list;
>         struct rcu_head rcu;
>  };
> diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
> index f2ca135..81210a8 100644
> --- a/include/net/dn_fib.h
> +++ b/include/net/dn_fib.h
> @@ -2,6 +2,7 @@
>  #define _NET_DN_FIB_H
>
>  #include <linux/netlink.h>
> +#include <linux/refcount.h>
>
>  extern const struct nla_policy rtm_dn_policy[];
>
> @@ -28,7 +29,7 @@ struct dn_fib_info {
>         struct dn_fib_info      *fib_next;
>         struct dn_fib_info      *fib_prev;
>         int                     fib_treeref;
> -       atomic_t                fib_clntref;
> +       refcount_t              fib_clntref;
>         int                     fib_dead;
>         unsigned int            fib_flags;
>         int                     fib_protocol;
> @@ -130,7 +131,7 @@ void dn_fib_free_info(struct dn_fib_info *fi);
>
>  static inline void dn_fib_info_put(struct dn_fib_info *fi)
>  {
> -       if (atomic_dec_and_test(&fi->fib_clntref))
> +       if (refcount_dec_and_test(&fi->fib_clntref))
>                 dn_fib_free_info(fi);
>  }
>
> diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
> index 8dbfdf7..26ae0ad 100644
> --- a/include/net/fib_rules.h
> +++ b/include/net/fib_rules.h
> @@ -5,6 +5,7 @@
>  #include <linux/slab.h>
>  #include <linux/netdevice.h>
>  #include <linux/fib_rules.h>
> +#include <linux/refcount.h>
>  #include <net/flow.h>
>  #include <net/rtnetlink.h>
>
> @@ -29,7 +30,7 @@ struct fib_rule {
>         struct fib_rule __rcu   *ctarget;
>         struct net              *fr_net;
>
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         u32                     pref;
>         int                     suppress_ifgroup;
>         int                     suppress_prefixlen;
> @@ -103,12 +104,12 @@ struct fib_rules_ops {
>
>  static inline void fib_rule_get(struct fib_rule *rule)
>  {
> -       atomic_inc(&rule->refcnt);
> +       refcount_inc(&rule->refcnt);
>  }
>
>  static inline void fib_rule_put(struct fib_rule *rule)
>  {
> -       if (atomic_dec_and_test(&rule->refcnt))
> +       if (refcount_dec_and_test(&rule->refcnt))
>                 kfree_rcu(rule, rcu);
>  }
>
> diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
> index 0fa4c32..96a0e6e 100644
> --- a/include/net/if_inet6.h
> +++ b/include/net/if_inet6.h
> @@ -17,6 +17,7 @@
>
>  #include <net/snmp.h>
>  #include <linux/ipv6.h>
> +#include <linux/refcount.h>
>
>  /* inet6_dev.if_flags */
>
> @@ -45,7 +46,7 @@ struct inet6_ifaddr {
>         /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
>         __u32                   valid_lft;
>         __u32                   prefered_lft;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         spinlock_t              lock;
>
>         int                     state;
> @@ -126,7 +127,7 @@ struct ifmcaddr6 {
>         struct timer_list       mca_timer;
>         unsigned int            mca_flags;
>         int                     mca_users;
> -       atomic_t                mca_refcnt;
> +       refcount_t              mca_refcnt;
>         spinlock_t              mca_lock;
>         unsigned long           mca_cstamp;
>         unsigned long           mca_tstamp;
> @@ -146,7 +147,7 @@ struct ifacaddr6 {
>         struct rt6_info         *aca_rt;
>         struct ifacaddr6        *aca_next;
>         int                     aca_users;
> -       atomic_t                aca_refcnt;
> +       refcount_t              aca_refcnt;
>         unsigned long           aca_cstamp;
>         unsigned long           aca_tstamp;
>  };
> @@ -187,7 +188,7 @@ struct inet6_dev {
>
>         struct ifacaddr6        *ac_list;
>         rwlock_t                lock;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         __u32                   if_flags;
>         int                     dead;
>
> diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
> index 909972a..ed5cbba 100644
> --- a/include/net/inet_frag.h
> +++ b/include/net/inet_frag.h
> @@ -50,7 +50,7 @@ struct inet_frag_queue {
>         spinlock_t              lock;
>         struct timer_list       timer;
>         struct hlist_node       list;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         struct sk_buff          *fragments;
>         struct sk_buff          *fragments_tail;
>         ktime_t                 stamp;
> @@ -129,7 +129,7 @@ void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
>
>  static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
>  {
> -       if (atomic_dec_and_test(&q->refcnt))
> +       if (refcount_dec_and_test(&q->refcnt))
>                 inet_frag_destroy(q, f);
>  }
>
> diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
> index 0574493..08d0d57 100644
> --- a/include/net/inet_hashtables.h
> +++ b/include/net/inet_hashtables.h
> @@ -32,7 +32,7 @@
>  #include <net/tcp_states.h>
>  #include <net/netns/hash.h>
>
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <asm/byteorder.h>
>
>  /* This is for all connections with a full identity, no wildcards.
> @@ -329,7 +329,7 @@ static inline struct sock *inet_lookup(struct net *net,
>         sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
>                            dport, dif, &refcounted);
>
> -       if (sk && !refcounted && !atomic_inc_not_zero(&sk->sk_refcnt))
> +       if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
>                 sk = NULL;
>         return sk;
>  }
> diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
> index 235c781..f2a215f 100644
> --- a/include/net/inetpeer.h
> +++ b/include/net/inetpeer.h
> @@ -46,7 +46,7 @@ struct inet_peer {
>                 struct rcu_head     gc_rcu;
>         };
>         /*
> -        * Once inet_peer is queued for deletion (refcnt == -1), following field
> +        * Once inet_peer is queued for deletion (refcnt == 0), following field
>          * is not available: rid
>          * We can share memory with rcu_head to help keep inet_peer small.
>          */
> @@ -60,7 +60,7 @@ struct inet_peer {
>
>         /* following fields might be frequently dirtied */
>         __u32                   dtime;  /* the time of last use of not referenced entries */
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>  };
>
>  struct inet_peer_base {
> diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
> index 5f376af..cdf077b 100644
> --- a/include/net/ip_fib.h
> +++ b/include/net/ip_fib.h
> @@ -23,6 +23,7 @@
>  #include <net/inetpeer.h>
>  #include <linux/percpu.h>
>  #include <linux/notifier.h>
> +#include <linux/refcount.h>
>
>  struct fib_config {
>         u8                      fc_dst_len;
> @@ -105,7 +106,7 @@ struct fib_info {
>         struct hlist_node       fib_lhash;
>         struct net              *fib_net;
>         int                     fib_treeref;
> -       atomic_t                fib_clntref;
> +       refcount_t              fib_clntref;
>         unsigned int            fib_flags;
>         unsigned char           fib_dead;
>         unsigned char           fib_protocol;
> @@ -400,12 +401,12 @@ void free_fib_info(struct fib_info *fi);
>
>  static inline void fib_info_hold(struct fib_info *fi)
>  {
> -       atomic_inc(&fi->fib_clntref);
> +       refcount_inc(&fi->fib_clntref);
>  }
>
>  static inline void fib_info_put(struct fib_info *fi)
>  {
> -       if (atomic_dec_and_test(&fi->fib_clntref))
> +       if (refcount_dec_and_test(&fi->fib_clntref))
>                 free_fib_info(fi);
>  }
>
> diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> index cd6018a..95e1c5d 100644
> --- a/include/net/ip_vs.h
> +++ b/include/net/ip_vs.h
> @@ -12,6 +12,8 @@
>  #include <linux/list.h>                 /* for struct list_head */
>  #include <linux/spinlock.h>             /* for struct rwlock_t */
>  #include <linux/atomic.h>               /* for struct atomic_t */
> +#include <linux/refcount.h>             /* for struct refcount_t */
> +
>  #include <linux/compiler.h>
>  #include <linux/timer.h>
>  #include <linux/bug.h>
> @@ -525,7 +527,7 @@ struct ip_vs_conn {
>         struct netns_ipvs       *ipvs;
>
>         /* counter and timer */
> -       atomic_t                refcnt;         /* reference count */
> +       refcount_t              refcnt;         /* reference count */
>         struct timer_list       timer;          /* Expiration timer */
>         volatile unsigned long  timeout;        /* timeout */
>
> @@ -618,7 +620,7 @@ struct ip_vs_dest_user_kern {
>  struct ip_vs_service {
>         struct hlist_node       s_list;   /* for normal service table */
>         struct hlist_node       f_list;   /* for fwmark-based service table */
> -       atomic_t                refcnt;   /* reference counter */
> +       refcount_t              refcnt;   /* reference counter */
>
>         u16                     af;       /* address family */
>         __u16                   protocol; /* which protocol (TCP/UDP) */
> @@ -667,7 +669,7 @@ struct ip_vs_dest {
>         atomic_t                conn_flags;     /* flags to copy to conn */
>         atomic_t                weight;         /* server weight */
>
> -       atomic_t                refcnt;         /* reference counter */
> +       refcount_t              refcnt;         /* reference counter */
>         struct ip_vs_stats      stats;          /* statistics */
>         unsigned long           idle_start;     /* start time, jiffies */
>
> @@ -697,7 +699,7 @@ struct ip_vs_dest {
>  struct ip_vs_scheduler {
>         struct list_head        n_list;         /* d-linked list head */
>         char                    *name;          /* scheduler name */
> -       atomic_t                refcnt;         /* reference counter */
> +       refcount_t              refcnt;         /* reference counter */
>         struct module           *module;        /* THIS_MODULE/NULL */
>
>         /* scheduler initializing service */
> @@ -721,7 +723,7 @@ struct ip_vs_scheduler {
>  struct ip_vs_pe {
>         struct list_head        n_list;         /* d-linked list head */
>         char                    *name;          /* scheduler name */
> -       atomic_t                refcnt;         /* reference counter */
> +       refcount_t              refcnt;         /* reference counter */
>         struct module           *module;        /* THIS_MODULE/NULL */
>
>         /* get the connection template, if any */
> @@ -1211,14 +1213,14 @@ struct ip_vs_conn * ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af,
>   */
>  static inline bool __ip_vs_conn_get(struct ip_vs_conn *cp)
>  {
> -       return atomic_inc_not_zero(&cp->refcnt);
> +       return refcount_inc_not_zero(&cp->refcnt);
>  }
>
>  /* put back the conn without restarting its timer */
>  static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
>  {
>         smp_mb__before_atomic();
> -       atomic_dec(&cp->refcnt);
> +       refcount_dec(&cp->refcnt);
>  }
>  void ip_vs_conn_put(struct ip_vs_conn *cp);
>  void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
> @@ -1410,19 +1412,21 @@ void ip_vs_try_bind_dest(struct ip_vs_conn *cp);
>
>  static inline void ip_vs_dest_hold(struct ip_vs_dest *dest)
>  {
> -       atomic_inc(&dest->refcnt);
> +       refcount_inc(&dest->refcnt);
>  }
>
>  static inline void ip_vs_dest_put(struct ip_vs_dest *dest)
>  {
>         smp_mb__before_atomic();
> -       atomic_dec(&dest->refcnt);
> +       refcount_dec(&dest->refcnt);
>  }
>
>  static inline void ip_vs_dest_put_and_free(struct ip_vs_dest *dest)
>  {
> -       if (atomic_dec_return(&dest->refcnt) < 0)
> +       if (refcount_read(&dest->refcnt) == 0)
>                 kfree(dest);
> +       else
> +               refcount_dec(&dest->refcnt);
>  }
>
>  /* IPVS sync daemon data and function prototypes
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index 487e573..f23dc0b 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -16,6 +16,7 @@
>  #include <linux/ipv6.h>
>  #include <linux/hardirq.h>
>  #include <linux/jhash.h>
> +#include <linux/refcount.h>
>  #include <net/if_inet6.h>
>  #include <net/ndisc.h>
>  #include <net/flow.h>
> @@ -203,7 +204,7 @@ extern rwlock_t ip6_ra_lock;
>   */
>
>  struct ipv6_txoptions {
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         /* Length of this structure */
>         int                     tot_len;
>
> @@ -265,7 +266,7 @@ static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
>         rcu_read_lock();
>         opt = rcu_dereference(np->opt);
>         if (opt) {
> -               if (!atomic_inc_not_zero(&opt->refcnt))
> +               if (!refcount_inc_not_zero(&opt->refcnt))
>                         opt = NULL;
>                 else
>                         opt = rcu_pointer_handoff(opt);
> @@ -276,7 +277,7 @@ static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
>
>  static inline void txopt_put(struct ipv6_txoptions *opt)
>  {
> -       if (opt && atomic_dec_and_test(&opt->refcnt))
> +       if (opt && refcount_dec_and_test(&opt->refcnt))
>                 kfree_rcu(opt, rcu);
>  }
>
> diff --git a/include/net/ipx.h b/include/net/ipx.h
> index e5cff68..af32b97 100644
> --- a/include/net/ipx.h
> +++ b/include/net/ipx.h
> @@ -14,6 +14,7 @@
>  #include <linux/ipx.h>
>  #include <linux/list.h>
>  #include <linux/slab.h>
> +#include <linux/refcount.h>
>
>  struct ipx_address {
>         __be32  net;
> @@ -54,7 +55,7 @@ struct ipx_interface {
>         /* IPX address */
>         __be32                  if_netnum;
>         unsigned char           if_node[IPX_NODE_LEN];
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>
>         /* physical device info */
>         struct net_device       *if_dev;
> @@ -80,7 +81,7 @@ struct ipx_route {
>         unsigned char           ir_routed;
>         unsigned char           ir_router_node[IPX_NODE_LEN];
>         struct list_head        node; /* node in ipx_routes list */
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>  };
>
>  struct ipx_cb {
> @@ -139,7 +140,7 @@ const char *ipx_device_name(struct ipx_interface *intrfc);
>
>  static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
>  {
> -       atomic_inc(&intrfc->refcnt);
> +       refcount_inc(&intrfc->refcnt);
>  }
>
>  void ipxitf_down(struct ipx_interface *intrfc);
> @@ -157,18 +158,18 @@ int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
>
>  static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
>  {
> -       if (atomic_dec_and_test(&intrfc->refcnt))
> +       if (refcount_dec_and_test(&intrfc->refcnt))
>                 ipxitf_down(intrfc);
>  }
>
>  static __inline__ void ipxrtr_hold(struct ipx_route *rt)
>  {
> -               atomic_inc(&rt->refcnt);
> +               refcount_inc(&rt->refcnt);
>  }
>
>  static __inline__ void ipxrtr_put(struct ipx_route *rt)
>  {
> -               if (atomic_dec_and_test(&rt->refcnt))
> +               if (refcount_dec_and_test(&rt->refcnt))
>                                         kfree(rt);
>  }
>  #endif /* _NET_INET_IPX_H_ */
> diff --git a/include/net/lapb.h b/include/net/lapb.h
> index 9510f87..85e7737 100644
> --- a/include/net/lapb.h
> +++ b/include/net/lapb.h
> @@ -1,6 +1,7 @@
>  #ifndef _LAPB_H
>  #define _LAPB_H
>  #include <linux/lapb.h>
> +#include <linux/refcount.h>
>
>  #define        LAPB_HEADER_LEN 20              /* LAPB over Ethernet + a bit more */
>
> @@ -101,7 +102,7 @@ struct lapb_cb {
>         struct lapb_frame       frmr_data;
>         unsigned char           frmr_type;
>
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>  };
>
>  /* lapb_iface.c */
> diff --git a/include/net/lib80211.h b/include/net/lib80211.h
> index aab0f42..9fd9042 100644
> --- a/include/net/lib80211.h
> +++ b/include/net/lib80211.h
> @@ -93,7 +93,7 @@ struct lib80211_crypt_data {
>         struct list_head list;  /* delayed deletion list */
>         struct lib80211_crypto_ops *ops;
>         void *priv;
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>  };
>
>  struct lib80211_crypt_info {
> diff --git a/include/net/llc.h b/include/net/llc.h
> index e8e61d4..dc35f25 100644
> --- a/include/net/llc.h
> +++ b/include/net/llc.h
> @@ -55,7 +55,7 @@ struct llc_sap {
>         unsigned char    state;
>         unsigned char    p_bit;
>         unsigned char    f_bit;
> -       atomic_t         refcnt;
> +       refcount_t               refcnt;
>         int              (*rcv_func)(struct sk_buff *skb,
>                                      struct net_device *dev,
>                                      struct packet_type *pt,
> @@ -113,14 +113,14 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
>                                         struct net_device *orig_dev));
>  static inline void llc_sap_hold(struct llc_sap *sap)
>  {
> -       atomic_inc(&sap->refcnt);
> +       refcount_inc(&sap->refcnt);
>  }
>
>  void llc_sap_close(struct llc_sap *sap);
>
>  static inline void llc_sap_put(struct llc_sap *sap)
>  {
> -       if (atomic_dec_and_test(&sap->refcnt))
> +       if (refcount_dec_and_test(&sap->refcnt))
>                 llc_sap_close(sap);
>  }
>
> diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
> index d4c1c75..932ff0c 100644
> --- a/include/net/lwtunnel.h
> +++ b/include/net/lwtunnel.h
> @@ -5,6 +5,7 @@
>  #include <linux/netdevice.h>
>  #include <linux/skbuff.h>
>  #include <linux/types.h>
> +#include <linux/refcount.h>
>  #include <net/route.h>
>
>  #define LWTUNNEL_HASH_BITS   7
> @@ -25,7 +26,7 @@ struct lwtunnel_state {
>         __u16           type;
>         __u16           flags;
>         __u16           headroom;
> -       atomic_t        refcnt;
> +       refcount_t      refcnt;
>         int             (*orig_output)(struct net *net, struct sock *sk, struct sk_buff *skb);
>         int             (*orig_input)(struct sk_buff *);
>         struct          rcu_head rcu;
> @@ -53,7 +54,7 @@ static inline struct lwtunnel_state *
>  lwtstate_get(struct lwtunnel_state *lws)
>  {
>         if (lws)
> -               atomic_inc(&lws->refcnt);
> +               refcount_inc(&lws->refcnt);
>
>         return lws;
>  }
> @@ -63,7 +64,7 @@ static inline void lwtstate_put(struct lwtunnel_state *lws)
>         if (!lws)
>                 return;
>
> -       if (atomic_dec_and_test(&lws->refcnt))
> +       if (refcount_dec_and_test(&lws->refcnt))
>                 lwtstate_free(lws);
>  }
>
> diff --git a/include/net/ndisc.h b/include/net/ndisc.h
> index d562a2f..0224bce 100644
> --- a/include/net/ndisc.h
> +++ b/include/net/ndisc.h
> @@ -384,7 +384,7 @@ static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, cons
>
>         rcu_read_lock_bh();
>         n = __ipv6_neigh_lookup_noref(dev, pkey);
> -       if (n && !atomic_inc_not_zero(&n->refcnt))
> +       if (n && !refcount_inc_not_zero(&n->refcnt))
>                 n = NULL;
>         rcu_read_unlock_bh();
>
> diff --git a/include/net/neighbour.h b/include/net/neighbour.h
> index 8b68384..33e534a 100644
> --- a/include/net/neighbour.h
> +++ b/include/net/neighbour.h
> @@ -17,6 +17,7 @@
>   */
>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/netdevice.h>
>  #include <linux/skbuff.h>
>  #include <linux/rcupdate.h>
> @@ -76,7 +77,7 @@ struct neigh_parms {
>         void    *sysctl_table;
>
>         int dead;
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>         struct rcu_head rcu_head;
>
>         int     reachable_time;
> @@ -137,7 +138,7 @@ struct neighbour {
>         unsigned long           confirmed;
>         unsigned long           updated;
>         rwlock_t                lock;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         struct sk_buff_head     arp_queue;
>         unsigned int            arp_queue_len_bytes;
>         struct timer_list       timer;
> @@ -393,12 +394,12 @@ void neigh_sysctl_unregister(struct neigh_parms *p);
>
>  static inline void __neigh_parms_put(struct neigh_parms *parms)
>  {
> -       atomic_dec(&parms->refcnt);
> +       refcount_dec(&parms->refcnt);
>  }
>
>  static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
>  {
> -       atomic_inc(&parms->refcnt);
> +       refcount_inc(&parms->refcnt);
>         return parms;
>  }
>
> @@ -408,18 +409,18 @@ static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
>
>  static inline void neigh_release(struct neighbour *neigh)
>  {
> -       if (atomic_dec_and_test(&neigh->refcnt))
> +       if (refcount_dec_and_test(&neigh->refcnt))
>                 neigh_destroy(neigh);
>  }
>
>  static inline struct neighbour * neigh_clone(struct neighbour *neigh)
>  {
>         if (neigh)
> -               atomic_inc(&neigh->refcnt);
> +               refcount_inc(&neigh->refcnt);
>         return neigh;
>  }
>
> -#define neigh_hold(n)  atomic_inc(&(n)->refcnt)
> +#define neigh_hold(n)  refcount_inc(&(n)->refcnt)
>
>  static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
>  {
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index af8fe8a..ec6dcaf 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -5,6 +5,7 @@
>  #define __NET_NET_NAMESPACE_H
>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/workqueue.h>
>  #include <linux/list.h>
>  #include <linux/sysctl.h>
> @@ -45,7 +46,7 @@ struct netns_ipvs;
>  #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
>
>  struct net {
> -       atomic_t                passive;        /* To decided when the network
> +       refcount_t              passive;        /* To decided when the network
>                                                  * namespace should be freed.
>                                                  */
>         atomic_t                count;          /* To decided when the network
> diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h
> index 0b0c35c..925524e 100644
> --- a/include/net/netfilter/br_netfilter.h
> +++ b/include/net/netfilter/br_netfilter.h
> @@ -8,7 +8,7 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
>         skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC);
>
>         if (likely(skb->nf_bridge))
> -               atomic_set(&(skb->nf_bridge->use), 1);
> +               refcount_set(&(skb->nf_bridge->use), 1);
>
>         return skb->nf_bridge;
>  }
> diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
> index 5ed33ea..65cc2cb 100644
> --- a/include/net/netfilter/nf_conntrack_expect.h
> +++ b/include/net/netfilter/nf_conntrack_expect.h
> @@ -5,6 +5,8 @@
>  #ifndef _NF_CONNTRACK_EXPECT_H
>  #define _NF_CONNTRACK_EXPECT_H
>
> +#include <linux/refcount.h>
> +
>  #include <net/netfilter/nf_conntrack.h>
>  #include <net/netfilter/nf_conntrack_zones.h>
>
> @@ -37,7 +39,7 @@ struct nf_conntrack_expect {
>         struct timer_list timeout;
>
>         /* Usage count. */
> -       atomic_t use;
> +       refcount_t use;
>
>         /* Flags */
>         unsigned int flags;
> diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
> index 5cc5e9e..d40b893 100644
> --- a/include/net/netfilter/nf_conntrack_timeout.h
> +++ b/include/net/netfilter/nf_conntrack_timeout.h
> @@ -4,6 +4,7 @@
>  #include <net/net_namespace.h>
>  #include <linux/netfilter/nf_conntrack_common.h>
>  #include <linux/netfilter/nf_conntrack_tuple_common.h>
> +#include <linux/refcount.h>
>  #include <net/netfilter/nf_conntrack.h>
>  #include <net/netfilter/nf_conntrack_extend.h>
>
> @@ -12,7 +13,7 @@
>  struct ctnl_timeout {
>         struct list_head        head;
>         struct rcu_head         rcu_head;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         char                    name[CTNL_TIMEOUT_NAME_MAX];
>         __u16                   l3num;
>         struct nf_conntrack_l4proto *l4proto;
> diff --git a/include/net/netlabel.h b/include/net/netlabel.h
> index efe9806..72d6435 100644
> --- a/include/net/netlabel.h
> +++ b/include/net/netlabel.h
> @@ -37,7 +37,7 @@
>  #include <linux/in6.h>
>  #include <net/netlink.h>
>  #include <net/request_sock.h>
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
>
>  struct cipso_v4_doi;
>  struct calipso_doi;
> @@ -136,7 +136,7 @@ struct netlbl_audit {
>   *
>   */
>  struct netlbl_lsm_cache {
> -       atomic_t refcount;
> +       refcount_t refcount;
>         void (*free) (const void *data);
>         void *data;
>  };
> @@ -295,7 +295,7 @@ static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
>
>         cache = kzalloc(sizeof(*cache), flags);
>         if (cache)
> -               atomic_set(&cache->refcount, 1);
> +               refcount_set(&cache->refcount, 1);
>         return cache;
>  }
>
> @@ -309,7 +309,7 @@ static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
>   */
>  static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
>  {
> -       if (!atomic_dec_and_test(&cache->refcount))
> +       if (!refcount_dec_and_test(&cache->refcount))
>                 return;
>
>         if (cache->free)
> diff --git a/include/net/netrom.h b/include/net/netrom.h
> index 110350a..443a4ff 100644
> --- a/include/net/netrom.h
> +++ b/include/net/netrom.h
> @@ -11,6 +11,7 @@
>  #include <linux/list.h>
>  #include <linux/slab.h>
>  #include <net/sock.h>
> +#include <linux/refcount.h>
>
>  #define        NR_NETWORK_LEN                  15
>  #define        NR_TRANSPORT_LEN                5
> @@ -93,7 +94,7 @@ struct nr_neigh {
>         unsigned short          count;
>         unsigned int            number;
>         unsigned char           failed;
> -       atomic_t                refcount;
> +       refcount_t              refcount;
>  };
>
>  struct nr_route {
> @@ -109,7 +110,7 @@ struct nr_node {
>         unsigned char           which;
>         unsigned char           count;
>         struct nr_route         routes[3];
> -       atomic_t                refcount;
> +       refcount_t              refcount;
>         spinlock_t              node_lock;
>  };
>
> @@ -118,21 +119,21 @@ struct nr_node {
>   *********************************************************************/
>
>  #define nr_node_hold(__nr_node) \
> -       atomic_inc(&((__nr_node)->refcount))
> +       refcount_inc(&((__nr_node)->refcount))
>
>  static __inline__ void nr_node_put(struct nr_node *nr_node)
>  {
> -       if (atomic_dec_and_test(&nr_node->refcount)) {
> +       if (refcount_dec_and_test(&nr_node->refcount)) {
>                 kfree(nr_node);
>         }
>  }
>
>  #define nr_neigh_hold(__nr_neigh) \
> -       atomic_inc(&((__nr_neigh)->refcount))
> +       refcount_inc(&((__nr_neigh)->refcount))
>
>  static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
>  {
> -       if (atomic_dec_and_test(&nr_neigh->refcount)) {
> +       if (refcount_dec_and_test(&nr_neigh->refcount)) {
>                 if (nr_neigh->ax25)
>                         ax25_cb_put(nr_neigh->ax25);
>                 kfree(nr_neigh->digipeat);
> diff --git a/include/net/request_sock.h b/include/net/request_sock.h
> index 6ebe13e..696a53d 100644
> --- a/include/net/request_sock.h
> +++ b/include/net/request_sock.h
> @@ -19,6 +19,7 @@
>  #include <linux/spinlock.h>
>  #include <linux/types.h>
>  #include <linux/bug.h>
> +#include <linux/refcount.h>
>
>  #include <net/sock.h>
>
> @@ -89,7 +90,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
>                 return NULL;
>         req->rsk_listener = NULL;
>         if (attach_listener) {
> -               if (unlikely(!atomic_inc_not_zero(&sk_listener->sk_refcnt))) {
> +               if (unlikely(!refcount_inc_not_zero(&sk_listener->sk_refcnt))) {
>                         kmem_cache_free(ops->slab, req);
>                         return NULL;
>                 }
> @@ -100,7 +101,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
>         sk_node_init(&req_to_sk(req)->sk_node);
>         sk_tx_queue_clear(req_to_sk(req));
>         req->saved_syn = NULL;
> -       atomic_set(&req->rsk_refcnt, 0);
> +       refcount_set(&req->rsk_refcnt, 0);
>
>         return req;
>  }
> @@ -108,7 +109,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
>  static inline void reqsk_free(struct request_sock *req)
>  {
>         /* temporary debugging */
> -       WARN_ON_ONCE(atomic_read(&req->rsk_refcnt) != 0);
> +       WARN_ON_ONCE(refcount_read(&req->rsk_refcnt) != 0);
>
>         req->rsk_ops->destructor(req);
>         if (req->rsk_listener)
> @@ -119,7 +120,7 @@ static inline void reqsk_free(struct request_sock *req)
>
>  static inline void reqsk_put(struct request_sock *req)
>  {
> -       if (atomic_dec_and_test(&req->rsk_refcnt))
> +       if (refcount_dec_and_test(&req->rsk_refcnt))
>                 reqsk_free(req);
>  }
>
> diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
> index 498f81b..fbcdd64 100644
> --- a/include/net/sch_generic.h
> +++ b/include/net/sch_generic.h
> @@ -8,6 +8,7 @@
>  #include <linux/pkt_cls.h>
>  #include <linux/percpu.h>
>  #include <linux/dynamic_queue_limits.h>
> +#include <linux/refcount.h>
>  #include <net/gen_stats.h>
>  #include <net/rtnetlink.h>
>
> @@ -93,7 +94,7 @@ struct Qdisc {
>         struct sk_buff          *skb_bad_txq;
>         struct rcu_head         rcu_head;
>         int                     padded;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>
>         spinlock_t              busylock ____cacheline_aligned_in_smp;
>  };
> diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
> index 9b9fb12..328fccc 100644
> --- a/include/net/sctp/auth.h
> +++ b/include/net/sctp/auth.h
> @@ -31,6 +31,7 @@
>  #define __sctp_auth_h__
>
>  #include <linux/list.h>
> +#include <linux/refcount.h>
>
>  struct sctp_endpoint;
>  struct sctp_association;
> @@ -53,7 +54,7 @@ struct sctp_hmac {
>   * over SCTP-AUTH
>   */
>  struct sctp_auth_bytes {
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>         __u32 len;
>         __u8  data[];
>  };
> @@ -76,7 +77,7 @@ static inline void sctp_auth_key_hold(struct sctp_auth_bytes *key)
>         if (!key)
>                 return;
>
> -       atomic_inc(&key->refcnt);
> +       refcount_inc(&key->refcnt);
>  }
>
>  void sctp_auth_key_put(struct sctp_auth_bytes *key);
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 92daabd..07d514d 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -524,7 +524,7 @@ struct sctp_datamsg {
>         /* Chunks waiting to be submitted to lower layer. */
>         struct list_head chunks;
>         /* Reference counting. */
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>         /* When is this message no longer interesting to the peer? */
>         unsigned long expires_at;
>         /* Did the messenge fail to send? */
> @@ -552,7 +552,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *);
>  struct sctp_chunk {
>         struct list_head list;
>
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>
>         /* How many times this chunk have been sent, for prsctp RTX policy */
>         int sent_count;
> @@ -764,7 +764,7 @@ struct sctp_transport {
>         struct rhlist_head node;
>
>         /* Reference counting. */
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>                 /* RTO-Pending : A flag used to track if one of the DATA
>                  *              chunks sent to this address is currently being
>                  *              used to compute a RTT. If this flag is 0,
> @@ -1195,7 +1195,7 @@ struct sctp_ep_common {
>          *   refcnt   - Reference count access to this object.
>          *   dead     - Do not attempt to use this object.
>          */
> -       atomic_t    refcnt;
> +       refcount_t    refcnt;
>         bool        dead;
>
>         /* What socket does this endpoint belong to?  */
> diff --git a/include/net/sock.h b/include/net/sock.h
> index f0e867f..3b646eb 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -66,6 +66,7 @@
>  #include <linux/poll.h>
>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <net/dst.h>
>  #include <net/checksum.h>
>  #include <net/tcp_states.h>
> @@ -218,7 +219,7 @@ struct sock_common {
>                 u32             skc_tw_rcv_nxt; /* struct tcp_timewait_sock  */
>         };
>
> -       atomic_t                skc_refcnt;
> +       refcount_t              skc_refcnt;
>         /* private: */
>         int                     skc_dontcopy_end[0];
>         union {
> @@ -386,7 +387,7 @@ struct sock {
>
>         /* ===== cache line for TX ===== */
>         int                     sk_wmem_queued;
> -       atomic_t                sk_wmem_alloc;
> +       refcount_t              sk_wmem_alloc;
>         unsigned long           sk_tsq_flags;
>         struct sk_buff          *sk_send_head;
>         struct sk_buff_head     sk_write_queue;
> @@ -599,7 +600,7 @@ static inline bool __sk_del_node_init(struct sock *sk)
>
>  static __always_inline void sock_hold(struct sock *sk)
>  {
> -       atomic_inc(&sk->sk_refcnt);
> +       refcount_inc(&sk->sk_refcnt);
>  }
>
>  /* Ungrab socket in the context, which assumes that socket refcnt
> @@ -607,7 +608,7 @@ static __always_inline void sock_hold(struct sock *sk)
>   */
>  static __always_inline void __sock_put(struct sock *sk)
>  {
> -       atomic_dec(&sk->sk_refcnt);
> +       refcount_dec(&sk->sk_refcnt);
>  }
>
>  static inline bool sk_del_node_init(struct sock *sk)
> @@ -616,7 +617,7 @@ static inline bool sk_del_node_init(struct sock *sk)
>
>         if (rc) {
>                 /* paranoid for a while -acme */
> -               WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
> +               WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
>                 __sock_put(sk);
>         }
>         return rc;
> @@ -638,7 +639,7 @@ static inline bool sk_nulls_del_node_init_rcu(struct sock *sk)
>
>         if (rc) {
>                 /* paranoid for a while -acme */
> -               WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
> +               WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
>                 __sock_put(sk);
>         }
>         return rc;
> @@ -1124,9 +1125,9 @@ static inline void sk_refcnt_debug_dec(struct sock *sk)
>
>  static inline void sk_refcnt_debug_release(const struct sock *sk)
>  {
> -       if (atomic_read(&sk->sk_refcnt) != 1)
> +       if (refcount_read(&sk->sk_refcnt) != 1)
>                 printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n",
> -                      sk->sk_prot->name, sk, atomic_read(&sk->sk_refcnt));
> +                      sk->sk_prot->name, sk, refcount_read(&sk->sk_refcnt));
>  }
>  #else /* SOCK_REFCNT_DEBUG */
>  #define sk_refcnt_debug_inc(sk) do { } while (0)
> @@ -1634,7 +1635,7 @@ void sock_init_data(struct socket *sock, struct sock *sk);
>  /* Ungrab socket and destroy it, if it was the last reference. */
>  static inline void sock_put(struct sock *sk)
>  {
> -       if (atomic_dec_and_test(&sk->sk_refcnt))
> +       if (refcount_dec_and_test(&sk->sk_refcnt))
>                 sk_free(sk);
>  }
>  /* Generic version of sock_put(), dealing with all sockets
> @@ -1889,7 +1890,7 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, struct iov_iter *fro
>   */
>  static inline int sk_wmem_alloc_get(const struct sock *sk)
>  {
> -       return atomic_read(&sk->sk_wmem_alloc) - 1;
> +       return refcount_read(&sk->sk_wmem_alloc) - 1;
>  }
>
>  /**
> @@ -2031,7 +2032,7 @@ static inline unsigned long sock_wspace(struct sock *sk)
>         int amt = 0;
>
>         if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
> -               amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
> +               amt = sk->sk_sndbuf - refcount_read(&sk->sk_wmem_alloc);
>                 if (amt < 0)
>                         amt = 0;
>         }
> @@ -2112,7 +2113,7 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag);
>   */
>  static inline bool sock_writeable(const struct sock *sk)
>  {
> -       return atomic_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1);
> +       return refcount_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1);
>  }
>
>  static inline gfp_t gfp_any(void)
> diff --git a/include/net/vxlan.h b/include/net/vxlan.h
> index 49a5920..5c117b4 100644
> --- a/include/net/vxlan.h
> +++ b/include/net/vxlan.h
> @@ -183,7 +183,7 @@ struct vxlan_sock {
>         struct hlist_node hlist;
>         struct socket    *sock;
>         struct hlist_head vni_list[VNI_HASH_SIZE];
> -       atomic_t          refcnt;
> +       refcount_t        refcnt;
>         u32               flags;
>  };
>
> diff --git a/include/net/x25.h b/include/net/x25.h
> index c383aa4..6219daf 100644
> --- a/include/net/x25.h
> +++ b/include/net/x25.h
> @@ -11,6 +11,7 @@
>  #define _X25_H
>  #include <linux/x25.h>
>  #include <linux/slab.h>
> +#include <linux/refcount.h>
>  #include <net/sock.h>
>
>  #define        X25_ADDR_LEN                    16
> @@ -129,7 +130,7 @@ struct x25_route {
>         struct x25_address      address;
>         unsigned int            sigdigits;
>         struct net_device       *dev;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>  };
>
>  struct x25_neigh {
> @@ -141,7 +142,7 @@ struct x25_neigh {
>         unsigned long           t20;
>         struct timer_list       t20timer;
>         unsigned long           global_facil_mask;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>  };
>
>  struct x25_sock {
> @@ -171,7 +172,7 @@ struct x25_forward {
>         unsigned int            lci;
>         struct net_device       *dev1;
>         struct net_device       *dev2;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>  };
>
>  static inline struct x25_sock *x25_sk(const struct sock *sk)
> @@ -242,12 +243,12 @@ void x25_link_free(void);
>  /* x25_neigh.c */
>  static __inline__ void x25_neigh_hold(struct x25_neigh *nb)
>  {
> -       atomic_inc(&nb->refcnt);
> +       refcount_inc(&nb->refcnt);
>  }
>
>  static __inline__ void x25_neigh_put(struct x25_neigh *nb)
>  {
> -       if (atomic_dec_and_test(&nb->refcnt))
> +       if (refcount_dec_and_test(&nb->refcnt))
>                 kfree(nb);
>  }
>
> @@ -265,12 +266,12 @@ void x25_route_free(void);
>
>  static __inline__ void x25_route_hold(struct x25_route *rt)
>  {
> -       atomic_inc(&rt->refcnt);
> +       refcount_inc(&rt->refcnt);
>  }
>
>  static __inline__ void x25_route_put(struct x25_route *rt)
>  {
> -       if (atomic_dec_and_test(&rt->refcnt))
> +       if (refcount_dec_and_test(&rt->refcnt))
>                 kfree(rt);
>  }
>
> diff --git a/include/net/xfrm.h b/include/net/xfrm.h
> index 31947b9..54a8967 100644
> --- a/include/net/xfrm.h
> +++ b/include/net/xfrm.h
> @@ -13,6 +13,7 @@
>  #include <linux/mutex.h>
>  #include <linux/audit.h>
>  #include <linux/slab.h>
> +#include <linux/refcount.h>
>
>  #include <net/sock.h>
>  #include <net/dst.h>
> @@ -130,7 +131,7 @@ struct xfrm_state {
>         struct hlist_node       bysrc;
>         struct hlist_node       byspi;
>
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         spinlock_t              lock;
>
>         struct xfrm_id          id;
> @@ -524,7 +525,7 @@ struct xfrm_policy {
>
>         /* This lock only affects elements except for entry. */
>         rwlock_t                lock;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         struct timer_list       timer;
>
>         struct flow_cache_object flo;
> @@ -779,14 +780,14 @@ static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
>  static inline void xfrm_pol_hold(struct xfrm_policy *policy)
>  {
>         if (likely(policy != NULL))
> -               atomic_inc(&policy->refcnt);
> +               refcount_inc(&policy->refcnt);
>  }
>
>  void xfrm_policy_destroy(struct xfrm_policy *policy);
>
>  static inline void xfrm_pol_put(struct xfrm_policy *policy)
>  {
> -       if (atomic_dec_and_test(&policy->refcnt))
> +       if (refcount_dec_and_test(&policy->refcnt))
>                 xfrm_policy_destroy(policy);
>  }
>
> @@ -801,18 +802,18 @@ void __xfrm_state_destroy(struct xfrm_state *);
>
>  static inline void __xfrm_state_put(struct xfrm_state *x)
>  {
> -       atomic_dec(&x->refcnt);
> +       refcount_dec(&x->refcnt);
>  }
>
>  static inline void xfrm_state_put(struct xfrm_state *x)
>  {
> -       if (atomic_dec_and_test(&x->refcnt))
> +       if (refcount_dec_and_test(&x->refcnt))
>                 __xfrm_state_destroy(x);
>  }
>
>  static inline void xfrm_state_hold(struct xfrm_state *x)
>  {
> -       atomic_inc(&x->refcnt);
> +       refcount_inc(&x->refcnt);
>  }
>
>  static inline bool addr_match(const void *token1, const void *token2,
> @@ -975,7 +976,7 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
>  void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
>
>  struct sec_path {
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         int                     len;
>         struct xfrm_state       *xvec[XFRM_MAX_DEPTH];
>  };
> @@ -993,7 +994,7 @@ static inline struct sec_path *
>  secpath_get(struct sec_path *sp)
>  {
>         if (sp)
> -               atomic_inc(&sp->refcnt);
> +               refcount_inc(&sp->refcnt);
>         return sp;
>  }
>
> @@ -1002,7 +1003,7 @@ void __secpath_destroy(struct sec_path *sp);
>  static inline void
>  secpath_put(struct sec_path *sp)
>  {
> -       if (sp && atomic_dec_and_test(&sp->refcnt))
> +       if (sp && refcount_dec_and_test(&sp->refcnt))
>                 __secpath_destroy(sp);
>  }
>
> diff --git a/net/atm/br2684.c b/net/atm/br2684.c
> index fca84e1..4e11119 100644
> --- a/net/atm/br2684.c
> +++ b/net/atm/br2684.c
> @@ -252,7 +252,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
>
>         ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
>         pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
> -       atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
>         ATM_SKB(skb)->atm_options = atmvcc->atm_options;
>         dev->stats.tx_packets++;
>         dev->stats.tx_bytes += skb->len;
> diff --git a/net/atm/clip.c b/net/atm/clip.c
> index 53b4ac0..e2e1318 100644
> --- a/net/atm/clip.c
> +++ b/net/atm/clip.c
> @@ -137,11 +137,11 @@ static int neigh_check_cb(struct neighbour *n)
>         if (entry->vccs || time_before(jiffies, entry->expires))
>                 return 0;
>
> -       if (atomic_read(&n->refcnt) > 1) {
> +       if (refcount_read(&n->refcnt) > 1) {
>                 struct sk_buff *skb;
>
>                 pr_debug("destruction postponed with ref %d\n",
> -                        atomic_read(&n->refcnt));
> +                        refcount_read(&n->refcnt));
>
>                 while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
>                         dev_kfree_skb(skb);
> @@ -381,7 +381,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
>                 memcpy(here, llc_oui, sizeof(llc_oui));
>                 ((__be16 *) here)[3] = skb->protocol;
>         }
> -       atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
>         ATM_SKB(skb)->atm_options = vcc->atm_options;
>         entry->vccs->last_use = jiffies;
>         pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
> @@ -767,7 +767,7 @@ static void atmarp_info(struct seq_file *seq, struct neighbour *n,
>                         seq_printf(seq, "(resolving)\n");
>                 else
>                         seq_printf(seq, "(expired, ref %d)\n",
> -                                  atomic_read(&entry->neigh->refcnt));
> +                                  refcount_read(&entry->neigh->refcnt));
>         } else if (!svc) {
>                 seq_printf(seq, "%d.%d.%d\n",
>                            clip_vcc->vcc->dev->number,
> diff --git a/net/atm/common.c b/net/atm/common.c
> index a3ca922..16b2c25 100644
> --- a/net/atm/common.c
> +++ b/net/atm/common.c
> @@ -75,7 +75,7 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
>         while (!(skb = alloc_skb(size, GFP_KERNEL)))
>                 schedule();
>         pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
> -       atomic_add(skb->truesize, &sk->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk->sk_wmem_alloc);
>         return skb;
>  }
>
> @@ -85,9 +85,9 @@ static void vcc_sock_destruct(struct sock *sk)
>                 printk(KERN_DEBUG "%s: rmem leakage (%d bytes) detected.\n",
>                        __func__, atomic_read(&sk->sk_rmem_alloc));
>
> -       if (atomic_read(&sk->sk_wmem_alloc))
> +       if (refcount_read(&sk->sk_wmem_alloc))
>                 printk(KERN_DEBUG "%s: wmem leakage (%d bytes) detected.\n",
> -                      __func__, atomic_read(&sk->sk_wmem_alloc));
> +                      __func__, refcount_read(&sk->sk_wmem_alloc));
>  }
>
>  static void vcc_def_wakeup(struct sock *sk)
> @@ -106,7 +106,7 @@ static inline int vcc_writable(struct sock *sk)
>         struct atm_vcc *vcc = atm_sk(sk);
>
>         return (vcc->qos.txtp.max_sdu +
> -               atomic_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
> +               refcount_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
>  }
>
>  static void vcc_write_space(struct sock *sk)
> @@ -161,7 +161,7 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family, i
>         memset(&vcc->local, 0, sizeof(struct sockaddr_atmsvc));
>         memset(&vcc->remote, 0, sizeof(struct sockaddr_atmsvc));
>         vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
> -       atomic_set(&sk->sk_wmem_alloc, 1);
> +       refcount_set(&sk->sk_wmem_alloc, 1);
>         atomic_set(&sk->sk_rmem_alloc, 0);
>         vcc->push = NULL;
>         vcc->pop = NULL;
> diff --git a/net/atm/lec.c b/net/atm/lec.c
> index 019557d..1bc6722 100644
> --- a/net/atm/lec.c
> +++ b/net/atm/lec.c
> @@ -101,12 +101,12 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
>  /* must be done under lec_arp_lock */
>  static inline void lec_arp_hold(struct lec_arp_table *entry)
>  {
> -       atomic_inc(&entry->usage);
> +       refcount_inc(&entry->usage);
>  }
>
>  static inline void lec_arp_put(struct lec_arp_table *entry)
>  {
> -       if (atomic_dec_and_test(&entry->usage))
> +       if (refcount_dec_and_test(&entry->usage))
>                 kfree(entry);
>  }
>
> @@ -181,7 +181,7 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
>         ATM_SKB(skb)->vcc = vcc;
>         ATM_SKB(skb)->atm_options = vcc->atm_options;
>
> -       atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
>         if (vcc->send(vcc, skb) < 0) {
>                 dev->stats.tx_dropped++;
>                 return;
> @@ -345,7 +345,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
>         int i;
>         char *tmp;              /* FIXME */
>
> -       atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
> +       WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
>         mesg = (struct atmlec_msg *)skb->data;
>         tmp = skb->data;
>         tmp += sizeof(struct atmlec_msg);
> @@ -1216,6 +1216,7 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
>  #include <linux/timer.h>
>  #include <linux/param.h>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/inetdevice.h>
>  #include <net/route.h>
>
> @@ -1562,7 +1563,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv,
>         to_return->last_used = jiffies;
>         to_return->priv = priv;
>         skb_queue_head_init(&to_return->tx_wait);
> -       atomic_set(&to_return->usage, 1);
> +       refcount_set(&to_return->usage, 1);
>         return to_return;
>  }
>
> diff --git a/net/atm/lec_arpc.h b/net/atm/lec_arpc.h
> index ec67435..7ff4e7c 100644
> --- a/net/atm/lec_arpc.h
> +++ b/net/atm/lec_arpc.h
> @@ -47,7 +47,7 @@ struct lec_arp_table {
>                                          * the length of the tlvs array
>                                          */
>         struct sk_buff_head tx_wait;    /* wait queue for outgoing packets */
> -       atomic_t usage;                 /* usage count */
> +       refcount_t usage;                               /* usage count */
>  };
>
>  /*
> diff --git a/net/atm/mpc.c b/net/atm/mpc.c
> index 3b3b1a2..5741820 100644
> --- a/net/atm/mpc.c
> +++ b/net/atm/mpc.c
> @@ -555,7 +555,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
>                                         sizeof(struct llc_snap_hdr));
>         }
>
> -       atomic_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
>         ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
>         entry->shortcut->send(entry->shortcut, skb);
>         entry->packets_fwded++;
> @@ -911,7 +911,7 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
>
>         struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
>         struct k_message *mesg = (struct k_message *)skb->data;
> -       atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
> +       WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
>
>         if (mpc == NULL) {
>                 pr_info("no mpc found\n");
> diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
> index a89fdeb..4ccaa16 100644
> --- a/net/atm/mpoa_caches.c
> +++ b/net/atm/mpoa_caches.c
> @@ -40,7 +40,7 @@ static in_cache_entry *in_cache_get(__be32 dst_ip,
>         entry = client->in_cache;
>         while (entry != NULL) {
>                 if (entry->ctrl_info.in_dst_ip == dst_ip) {
> -                       atomic_inc(&entry->use);
> +                       refcount_inc(&entry->use);
>                         read_unlock_bh(&client->ingress_lock);
>                         return entry;
>                 }
> @@ -61,7 +61,7 @@ static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip,
>         entry = client->in_cache;
>         while (entry != NULL) {
>                 if ((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask)) {
> -                       atomic_inc(&entry->use);
> +                       refcount_inc(&entry->use);
>                         read_unlock_bh(&client->ingress_lock);
>                         return entry;
>                 }
> @@ -82,7 +82,7 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
>         entry = client->in_cache;
>         while (entry != NULL) {
>                 if (entry->shortcut == vcc) {
> -                       atomic_inc(&entry->use);
> +                       refcount_inc(&entry->use);
>                         read_unlock_bh(&client->ingress_lock);
>                         return entry;
>                 }
> @@ -105,7 +105,7 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
>
>         dprintk("adding an ingress entry, ip = %pI4\n", &dst_ip);
>
> -       atomic_set(&entry->use, 1);
> +       refcount_set(&entry->use, 1);
>         dprintk("new_in_cache_entry: about to lock\n");
>         write_lock_bh(&client->ingress_lock);
>         entry->next = client->in_cache;
> @@ -121,7 +121,7 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
>         entry->count = 1;
>         entry->entry_state = INGRESS_INVALID;
>         entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
> -       atomic_inc(&entry->use);
> +       refcount_inc(&entry->use);
>
>         write_unlock_bh(&client->ingress_lock);
>         dprintk("new_in_cache_entry: unlocked\n");
> @@ -178,7 +178,7 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
>
>  static void in_cache_put(in_cache_entry *entry)
>  {
> -       if (atomic_dec_and_test(&entry->use)) {
> +       if (refcount_dec_and_test(&entry->use)) {
>                 memset(entry, 0, sizeof(in_cache_entry));
>                 kfree(entry);
>         }
> @@ -339,7 +339,7 @@ static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id,
>         entry = mpc->eg_cache;
>         while (entry != NULL) {
>                 if (entry->ctrl_info.cache_id == cache_id) {
> -                       atomic_inc(&entry->use);
> +                       refcount_inc(&entry->use);
>                         read_unlock_irq(&mpc->egress_lock);
>                         return entry;
>                 }
> @@ -360,7 +360,7 @@ static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc)
>         entry = mpc->eg_cache;
>         while (entry != NULL) {
>                 if (entry->ctrl_info.tag == tag) {
> -                       atomic_inc(&entry->use);
> +                       refcount_inc(&entry->use);
>                         read_unlock_irqrestore(&mpc->egress_lock, flags);
>                         return entry;
>                 }
> @@ -382,7 +382,7 @@ static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc,
>         entry = mpc->eg_cache;
>         while (entry != NULL) {
>                 if (entry->shortcut == vcc) {
> -                       atomic_inc(&entry->use);
> +                       refcount_inc(&entry->use);
>                         read_unlock_irqrestore(&mpc->egress_lock, flags);
>                         return entry;
>                 }
> @@ -402,7 +402,7 @@ static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr,
>         entry = mpc->eg_cache;
>         while (entry != NULL) {
>                 if (entry->latest_ip_addr == ipaddr) {
> -                       atomic_inc(&entry->use);
> +                       refcount_inc(&entry->use);
>                         read_unlock_irq(&mpc->egress_lock);
>                         return entry;
>                 }
> @@ -415,7 +415,7 @@ static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr,
>
>  static void eg_cache_put(eg_cache_entry *entry)
>  {
> -       if (atomic_dec_and_test(&entry->use)) {
> +       if (refcount_dec_and_test(&entry->use)) {
>                 memset(entry, 0, sizeof(eg_cache_entry));
>                 kfree(entry);
>         }
> @@ -468,7 +468,7 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
>         dprintk("adding an egress entry, ip = %pI4, this should be our IP\n",
>                 &msg->content.eg_info.eg_dst_ip);
>
> -       atomic_set(&entry->use, 1);
> +       refcount_set(&entry->use, 1);
>         dprintk("new_eg_cache_entry: about to lock\n");
>         write_lock_irq(&client->egress_lock);
>         entry->next = client->eg_cache;
> @@ -484,7 +484,7 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
>         dprintk("new_eg_cache_entry cache_id %u\n",
>                 ntohl(entry->ctrl_info.cache_id));
>         dprintk("mps_ip = %pI4\n", &entry->ctrl_info.mps_ip);
> -       atomic_inc(&entry->use);
> +       refcount_inc(&entry->use);
>
>         write_unlock_irq(&client->egress_lock);
>         dprintk("new_eg_cache_entry: unlocked\n");
> diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h
> index 8e5f78c..30fe348 100644
> --- a/net/atm/mpoa_caches.h
> +++ b/net/atm/mpoa_caches.h
> @@ -6,6 +6,7 @@
>  #include <linux/atm.h>
>  #include <linux/atmdev.h>
>  #include <linux/atmmpc.h>
> +#include <linux/refcount.h>
>
>  struct mpoa_client;
>
> @@ -25,7 +26,7 @@ typedef struct in_cache_entry {
>         struct   atm_vcc *shortcut;
>         uint8_t  MPS_ctrl_ATM_addr[ATM_ESA_LEN];
>         struct   in_ctrl_info ctrl_info;
> -       atomic_t use;
> +       refcount_t use;
>  } in_cache_entry;
>
>  struct in_cache_ops{
> @@ -58,7 +59,7 @@ typedef struct eg_cache_entry{
>         uint16_t             entry_state;
>         __be32             latest_ip_addr;    /* The src IP address of the last packet */
>         struct eg_ctrl_info  ctrl_info;
> -       atomic_t             use;
> +       refcount_t             use;
>  } eg_cache_entry;
>
>  struct eg_cache_ops{
> diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
> index c4e0984..21d9d34 100644
> --- a/net/atm/pppoatm.c
> +++ b/net/atm/pppoatm.c
> @@ -350,7 +350,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
>                 return 1;
>         }
>
> -       atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
>         ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
>         pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
>                  skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
> diff --git a/net/atm/proc.c b/net/atm/proc.c
> index bbb6461..4caca2a 100644
> --- a/net/atm/proc.c
> +++ b/net/atm/proc.c
> @@ -61,7 +61,7 @@ static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev)
>         add_stats(seq, "0", &dev->stats.aal0);
>         seq_puts(seq, "  ");
>         add_stats(seq, "5", &dev->stats.aal5);
> -       seq_printf(seq, "\t[%d]", atomic_read(&dev->refcnt));
> +       seq_printf(seq, "\t[%d]", refcount_read(&dev->refcnt));
>         seq_putc(seq, '\n');
>  }
>
> @@ -211,7 +211,7 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
>                    vcc->flags, sk->sk_err,
>                    sk_wmem_alloc_get(sk), sk->sk_sndbuf,
>                    sk_rmem_alloc_get(sk), sk->sk_rcvbuf,
> -                  atomic_read(&sk->sk_refcnt));
> +                  refcount_read(&sk->sk_refcnt));
>  }
>
>  static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
> diff --git a/net/atm/raw.c b/net/atm/raw.c
> index 2e17e97..821c079 100644
> --- a/net/atm/raw.c
> +++ b/net/atm/raw.c
> @@ -35,7 +35,7 @@ static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb)
>
>         pr_debug("(%d) %d -= %d\n",
>                  vcc->vci, sk_wmem_alloc_get(sk), skb->truesize);
> -       atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
> +       WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc));
>         dev_kfree_skb_any(skb);
>         sk->sk_write_space(sk);
>  }
> diff --git a/net/atm/resources.c b/net/atm/resources.c
> index 0447d5d..9182447 100644
> --- a/net/atm/resources.c
> +++ b/net/atm/resources.c
> @@ -109,7 +109,7 @@ struct atm_dev *atm_dev_register(const char *type, struct device *parent,
>         else
>                 memset(&dev->flags, 0, sizeof(dev->flags));
>         memset(&dev->stats, 0, sizeof(dev->stats));
> -       atomic_set(&dev->refcnt, 1);
> +       refcount_set(&dev->refcnt, 1);
>
>         if (atm_proc_dev_register(dev) < 0) {
>                 pr_err("atm_proc_dev_register failed for dev %s\n", type);
> diff --git a/net/atm/signaling.c b/net/atm/signaling.c
> index adb6e3d..ca59496 100644
> --- a/net/atm/signaling.c
> +++ b/net/atm/signaling.c
> @@ -67,7 +67,7 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb)
>         struct sock *sk;
>
>         msg = (struct atmsvc_msg *) skb->data;
> -       atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
> +       WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
>         vcc = *(struct atm_vcc **) &msg->vcc;
>         pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc);
>         sk = sk_atm(vcc);
> diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
> index 90fcf5f..163e81f 100644
> --- a/net/ax25/af_ax25.c
> +++ b/net/ax25/af_ax25.c
> @@ -510,7 +510,7 @@ ax25_cb *ax25_create_cb(void)
>         if ((ax25 = kzalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
>                 return NULL;
>
> -       atomic_set(&ax25->refcount, 1);
> +       refcount_set(&ax25->refcount, 1);
>
>         skb_queue_head_init(&ax25->write_queue);
>         skb_queue_head_init(&ax25->frag_queue);
> diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
> index e1fda27..0446b89 100644
> --- a/net/ax25/ax25_route.c
> +++ b/net/ax25/ax25_route.c
> @@ -114,7 +114,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
>                 return -ENOMEM;
>         }
>
> -       atomic_set(&ax25_rt->refcount, 1);
> +       refcount_set(&ax25_rt->refcount, 1);
>         ax25_rt->callsign     = route->dest_addr;
>         ax25_rt->dev          = ax25_dev->dev;
>         ax25_rt->digipeat     = NULL;
> diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
> index 0403b0d..83b035f 100644
> --- a/net/ax25/ax25_uid.c
> +++ b/net/ax25/ax25_uid.c
> @@ -107,7 +107,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
>                 if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
>                         return -ENOMEM;
>
> -               atomic_set(&ax25_uid->refcount, 1);
> +               refcount_set(&ax25_uid->refcount, 1);
>                 ax25_uid->uid  = sax25_kuid;
>                 ax25_uid->call = sax->sax25_call;
>
> diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
> index 5f123c3..d6c68c2 100644
> --- a/net/bluetooth/a2mp.c
> +++ b/net/bluetooth/a2mp.c
> @@ -810,7 +810,7 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
>  /* AMP Manager functions */
>  struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr)
>  {
> -       BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount));
> +       BT_DBG("mgr %p orig refcnt %d", mgr, refcount_read(&mgr->kref.refcount));
>
>         kref_get(&mgr->kref);
>
> @@ -833,7 +833,7 @@ static void amp_mgr_destroy(struct kref *kref)
>
>  int amp_mgr_put(struct amp_mgr *mgr)
>  {
> -       BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount));
> +       BT_DBG("mgr %p orig refcnt %d", mgr, refcount_read(&mgr->kref.refcount));
>
>         return kref_put(&mgr->kref, &amp_mgr_destroy);
>  }
> diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
> index 1aff2da..8196f6f 100644
> --- a/net/bluetooth/af_bluetooth.c
> +++ b/net/bluetooth/af_bluetooth.c
> @@ -629,7 +629,7 @@ static int bt_seq_show(struct seq_file *seq, void *v)
>                 seq_printf(seq,
>                            "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu",
>                            sk,
> -                          atomic_read(&sk->sk_refcnt),
> +                          refcount_read(&sk->sk_refcnt),
>                            sk_rmem_alloc_get(sk),
>                            sk_wmem_alloc_get(sk),
>                            from_kuid(seq_user_ns(seq), sock_i_uid(sk)),
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index dc59eae..1102858 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -397,7 +397,7 @@ static void hci_conn_timeout(struct work_struct *work)
>  {
>         struct hci_conn *conn = container_of(work, struct hci_conn,
>                                              disc_work.work);
> -       int refcnt = atomic_read(&conn->refcnt);
> +       int refcnt = refcount_read(&conn->refcnt);
>
>         BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
>
> @@ -553,7 +553,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
>         INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout);
>         INIT_WORK(&conn->le_scan_cleanup, le_scan_cleanup);
>
> -       atomic_set(&conn->refcnt, 0);
> +       refcount_set(&conn->refcnt, 0);
>
>         hci_dev_hold(hdev);
>
> diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
> index f7eb02f..8ebca90 100644
> --- a/net/bluetooth/rfcomm/core.c
> +++ b/net/bluetooth/rfcomm/core.c
> @@ -311,7 +311,7 @@ struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio)
>
>         skb_queue_head_init(&d->tx_queue);
>         mutex_init(&d->lock);
> -       atomic_set(&d->refcnt, 1);
> +       refcount_set(&d->refcnt, 1);
>
>         rfcomm_dlc_clear_state(d);
>
> @@ -342,7 +342,7 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
>  {
>         struct rfcomm_session *s = d->session;
>
> -       BT_DBG("dlc %p refcnt %d session %p", d, atomic_read(&d->refcnt), s);
> +       BT_DBG("dlc %p refcnt %d session %p", d, refcount_read(&d->refcnt), s);
>
>         list_del(&d->list);
>         d->session = NULL;
> diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
> index 7511df7..55d07a9 100644
> --- a/net/bluetooth/rfcomm/sock.c
> +++ b/net/bluetooth/rfcomm/sock.c
> @@ -196,7 +196,7 @@ static void rfcomm_sock_kill(struct sock *sk)
>         if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
>                 return;
>
> -       BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, atomic_read(&sk->sk_refcnt));
> +       BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
>
>         /* Kill poor orphan */
>         bt_sock_unlink(&rfcomm_sk_list, sk);
> diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
> index 8ca6a92..89a857c 100644
> --- a/net/bridge/br_netfilter_hooks.c
> +++ b/net/bridge/br_netfilter_hooks.c
> @@ -149,12 +149,12 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
>  {
>         struct nf_bridge_info *nf_bridge = skb->nf_bridge;
>
> -       if (atomic_read(&nf_bridge->use) > 1) {
> +       if (refcount_read(&nf_bridge->use) > 1) {
>                 struct nf_bridge_info *tmp = nf_bridge_alloc(skb);
>
>                 if (tmp) {
>                         memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info));
> -                       atomic_set(&tmp->use, 1);
> +                       refcount_set(&tmp->use, 1);
>                 }
>                 nf_bridge_put(nf_bridge);
>                 nf_bridge = tmp;
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 8ce621e..050ce1d 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -21,6 +21,7 @@
>  #include <net/ip6_fib.h>
>  #include <linux/if_vlan.h>
>  #include <linux/rhashtable.h>
> +#include <linux/refcount.h>
>
>  #define BR_HASH_BITS 8
>  #define BR_HASH_SIZE (1 << BR_HASH_BITS)
> @@ -121,7 +122,7 @@ struct net_bridge_vlan {
>                 struct net_bridge_port  *port;
>         };
>         union {
> -               atomic_t                refcnt;
> +               refcount_t              refcnt;
>                 struct net_bridge_vlan  *brvlan;
>         };
>         struct list_head                vlist;
> diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
> index b6de4f4..0a0ef24 100644
> --- a/net/bridge/br_vlan.c
> +++ b/net/bridge/br_vlan.c
> @@ -157,7 +157,7 @@ static struct net_bridge_vlan *br_vlan_get_master(struct net_bridge *br, u16 vid
>                 if (WARN_ON(!masterv))
>                         return NULL;
>         }
> -       atomic_inc(&masterv->refcnt);
> +       refcount_inc(&masterv->refcnt);
>
>         return masterv;
>  }
> @@ -181,7 +181,7 @@ static void br_vlan_put_master(struct net_bridge_vlan *masterv)
>                 return;
>
>         vg = br_vlan_group(masterv->br);
> -       if (atomic_dec_and_test(&masterv->refcnt)) {
> +       if (refcount_dec_and_test(&masterv->refcnt)) {
>                 rhashtable_remove_fast(&vg->vlan_hash,
>                                        &masterv->vnode, br_vlan_rht_params);
>                 __vlan_del_list(masterv);
> @@ -563,7 +563,7 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
>                                 br_err(br, "failed insert local address into bridge forwarding table\n");
>                                 return ret;
>                         }
> -                       atomic_inc(&vlan->refcnt);
> +                       refcount_inc(&vlan->refcnt);
>                         vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY;
>                         vg->num_vlans++;
>                 }
> @@ -585,7 +585,7 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
>         vlan->flags &= ~BRIDGE_VLAN_INFO_PVID;
>         vlan->br = br;
>         if (flags & BRIDGE_VLAN_INFO_BRENTRY)
> -               atomic_set(&vlan->refcnt, 1);
> +               refcount_set(&vlan->refcnt, 1);
>         ret = __vlan_add(vlan, flags);
>         if (ret) {
>                 free_percpu(vlan->stats);
> diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
> index 92cbbd2..a21eea9 100644
> --- a/net/caif/caif_socket.c
> +++ b/net/caif/caif_socket.c
> @@ -1009,7 +1009,7 @@ static const struct proto_ops caif_stream_ops = {
>  static void caif_sock_destructor(struct sock *sk)
>  {
>         struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
> -       caif_assert(!atomic_read(&sk->sk_wmem_alloc));
> +       caif_assert(!refcount_read(&sk->sk_wmem_alloc));
>         caif_assert(sk_unhashed(sk));
>         caif_assert(!sk->sk_socket);
>         if (!sock_flag(sk, SOCK_DEAD)) {
> diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
> index b490e74..88a324e 100644
> --- a/net/ceph/osd_client.c
> +++ b/net/ceph/osd_client.c
> @@ -1005,7 +1005,7 @@ static bool osd_registered(struct ceph_osd *osd)
>   */
>  static void osd_init(struct ceph_osd *osd)
>  {
> -       atomic_set(&osd->o_ref, 1);
> +       refcount_set(&osd->o_ref, 1);
>         RB_CLEAR_NODE(&osd->o_node);
>         osd->o_requests = RB_ROOT;
>         osd->o_linger_requests = RB_ROOT;
> @@ -1050,9 +1050,9 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
>
>  static struct ceph_osd *get_osd(struct ceph_osd *osd)
>  {
> -       if (atomic_inc_not_zero(&osd->o_ref)) {
> -               dout("get_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref)-1,
> -                    atomic_read(&osd->o_ref));
> +       if (refcount_inc_not_zero(&osd->o_ref)) {
> +               dout("get_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref)-1,
> +                    refcount_read(&osd->o_ref));
>                 return osd;
>         } else {
>                 dout("get_osd %p FAIL\n", osd);
> @@ -1062,9 +1062,9 @@ static struct ceph_osd *get_osd(struct ceph_osd *osd)
>
>  static void put_osd(struct ceph_osd *osd)
>  {
> -       dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
> -            atomic_read(&osd->o_ref) - 1);
> -       if (atomic_dec_and_test(&osd->o_ref)) {
> +       dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
> +            refcount_read(&osd->o_ref) - 1);
> +       if (refcount_dec_and_test(&osd->o_ref)) {
>                 osd_cleanup(osd);
>                 kfree(osd);
>         }
> @@ -4149,7 +4149,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
>                 close_osd(osd);
>         }
>         up_write(&osdc->lock);
> -       WARN_ON(atomic_read(&osdc->homeless_osd.o_ref) != 1);
> +       WARN_ON(refcount_read(&osdc->homeless_osd.o_ref) != 1);
>         osd_cleanup(&osdc->homeless_osd);
>
>         WARN_ON(!list_empty(&osdc->osd_lru));
> diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c
> index 6864007..ce09f73 100644
> --- a/net/ceph/pagelist.c
> +++ b/net/ceph/pagelist.c
> @@ -16,7 +16,7 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
>
>  void ceph_pagelist_release(struct ceph_pagelist *pl)
>  {
> -       if (!atomic_dec_and_test(&pl->refcnt))
> +       if (!refcount_dec_and_test(&pl->refcnt))
>                 return;
>         ceph_pagelist_unmap_tail(pl);
>         while (!list_empty(&pl->head)) {
> diff --git a/net/ceph/snapshot.c b/net/ceph/snapshot.c
> index 154683f..46db6f7 100644
> --- a/net/ceph/snapshot.c
> +++ b/net/ceph/snapshot.c
> @@ -51,7 +51,7 @@ struct ceph_snap_context *ceph_create_snap_context(u32 snap_count,
>         if (!snapc)
>                 return NULL;
>
> -       atomic_set(&snapc->nref, 1);
> +       refcount_set(&snapc->nref, 1);
>         snapc->num_snaps = snap_count;
>
>         return snapc;
> @@ -61,7 +61,7 @@ EXPORT_SYMBOL(ceph_create_snap_context);
>  struct ceph_snap_context *ceph_get_snap_context(struct ceph_snap_context *sc)
>  {
>         if (sc)
> -               atomic_inc(&sc->nref);
> +               refcount_inc(&sc->nref);
>         return sc;
>  }
>  EXPORT_SYMBOL(ceph_get_snap_context);
> @@ -70,7 +70,7 @@ void ceph_put_snap_context(struct ceph_snap_context *sc)
>  {
>         if (!sc)
>                 return;
> -       if (atomic_dec_and_test(&sc->nref)) {
> +       if (refcount_dec_and_test(&sc->nref)) {
>                 /*printk(" deleting snap_context %p\n", sc);*/
>                 kfree(sc);
>         }
> diff --git a/net/core/datagram.c b/net/core/datagram.c
> index 662bea5..0595e9b 100644
> --- a/net/core/datagram.c
> +++ b/net/core/datagram.c
> @@ -244,7 +244,7 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
>                                         }
>                                 }
>                                 *peeked = 1;
> -                               atomic_inc(&skb->users);
> +                               refcount_inc(&skb->users);
>                         } else {
>                                 __skb_unlink(skb, queue);
>                                 if (destructor)
> @@ -313,9 +313,9 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
>  {
>         bool slow;
>
> -       if (likely(atomic_read(&skb->users) == 1))
> +       if (likely(refcount_read(&skb->users) == 1))
>                 smp_rmb();
> -       else if (likely(!atomic_dec_and_test(&skb->users))) {
> +       else if (likely(!refcount_dec_and_test(&skb->users))) {
>                 sk_peek_offset_bwd(sk, len);
>                 return;
>         }
> @@ -341,7 +341,7 @@ int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
>                 spin_lock_bh(&sk->sk_receive_queue.lock);
>                 if (skb == skb_peek(&sk->sk_receive_queue)) {
>                         __skb_unlink(skb, &sk->sk_receive_queue);
> -                       atomic_dec(&skb->users);
> +                       refcount_dec(&skb->users);
>                         err = 0;
>                 }
>                 spin_unlock_bh(&sk->sk_receive_queue.lock);
> @@ -591,7 +591,7 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
>                 skb->data_len += copied;
>                 skb->len += copied;
>                 skb->truesize += truesize;
> -               atomic_add(truesize, &skb->sk->sk_wmem_alloc);
> +               refcount_add(truesize, &skb->sk->sk_wmem_alloc);
>                 while (copied) {
>                         int size = min_t(int, copied, PAGE_SIZE - start);
>                         skb_fill_page_desc(skb, frag++, pages[n], start, size);
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 8db5a0b..2661354 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -1806,7 +1806,7 @@ static inline int deliver_skb(struct sk_buff *skb,
>  {
>         if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
>                 return -ENOMEM;
> -       atomic_inc(&skb->users);
> +       refcount_inc(&skb->users);
>         return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
>  }
>
> @@ -2447,10 +2447,10 @@ void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason)
>  {
>         unsigned long flags;
>
> -       if (likely(atomic_read(&skb->users) == 1)) {
> +       if (likely(refcount_read(&skb->users) == 1)) {
>                 smp_rmb();
> -               atomic_set(&skb->users, 0);
> -       } else if (likely(!atomic_dec_and_test(&skb->users))) {
> +               refcount_set(&skb->users, 0);
> +       } else if (likely(!refcount_dec_and_test(&skb->users))) {
>                 return;
>         }
>         get_kfree_skb_cb(skb)->reason = reason;
> @@ -3845,7 +3845,7 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
>                         struct sk_buff *skb = clist;
>                         clist = clist->next;
>
> -                       WARN_ON(atomic_read(&skb->users));
> +                       WARN_ON(refcount_read(&skb->users));
>                         if (likely(get_kfree_skb_cb(skb)->reason == SKB_REASON_CONSUMED))
>                                 trace_consume_skb(skb);
>                         else
> diff --git a/net/core/dst.c b/net/core/dst.c
> index b5cbbe0..6d11cbe 100644
> --- a/net/core/dst.c
> +++ b/net/core/dst.c
> @@ -300,14 +300,9 @@ static void dst_destroy_rcu(struct rcu_head *head)
>  void dst_release(struct dst_entry *dst)
>  {
>         if (dst) {
> -               int newrefcnt;
>                 unsigned short nocache = dst->flags & DST_NOCACHE;
>
> -               newrefcnt = atomic_dec_return(&dst->__refcnt);
> -               if (unlikely(newrefcnt < 0))
> -                       net_warn_ratelimited("%s: dst:%p refcnt:%d\n",
> -                                            __func__, dst, newrefcnt);
> -               if (!newrefcnt && unlikely(nocache))
> +               if (!atomic_dec_and_test(&dst->__refcnt) && unlikely(nocache))
>                         call_rcu(&dst->rcu_head, dst_destroy_rcu);
>         }
>  }
> diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
> index b6791d9..53d55d5 100644
> --- a/net/core/fib_rules.c
> +++ b/net/core/fib_rules.c
> @@ -32,7 +32,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
>         if (r == NULL)
>                 return -ENOMEM;
>
> -       atomic_set(&r->refcnt, 1);
> +       refcount_set(&r->refcnt, 1);
>         r->action = FR_ACT_TO_TBL;
>         r->pref = pref;
>         r->table = table;
> @@ -269,7 +269,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
>
>                 if (err != -EAGAIN) {
>                         if ((arg->flags & FIB_LOOKUP_NOREF) ||
> -                           likely(atomic_inc_not_zero(&rule->refcnt))) {
> +                           likely(refcount_inc_not_zero(&rule->refcnt))) {
>                                 arg->rule = rule;
>                                 goto out;
>                         }
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 1969b3f..fce4f06 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -927,7 +927,7 @@ static void sk_filter_release_rcu(struct rcu_head *rcu)
>   */
>  static void sk_filter_release(struct sk_filter *fp)
>  {
> -       if (atomic_dec_and_test(&fp->refcnt))
> +       if (refcount_dec_and_test(&fp->refcnt))
>                 call_rcu(&fp->rcu, sk_filter_release_rcu);
>  }
>
> @@ -949,7 +949,7 @@ bool sk_filter_charge(struct sock *sk, struct sk_filter *fp)
>         /* same check as in sock_kmalloc() */
>         if (filter_size <= sysctl_optmem_max &&
>             atomic_read(&sk->sk_omem_alloc) + filter_size < sysctl_optmem_max) {
> -               atomic_inc(&fp->refcnt);
> +               refcount_set(&fp->refcnt, 1);
>                 atomic_add(filter_size, &sk->sk_omem_alloc);
>                 return true;
>         }
> @@ -1178,7 +1178,7 @@ static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk)
>                 return -ENOMEM;
>
>         fp->prog = prog;
> -       atomic_set(&fp->refcnt, 0);
> +       refcount_set(&fp->refcnt, 0);
>
>         if (!sk_filter_charge(sk, fp)) {
>                 kfree(fp);
> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index 7bb12e0..dee2486 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -140,7 +140,7 @@ static int neigh_forced_gc(struct neigh_table *tbl)
>                          * - it is not permanent
>                          */
>                         write_lock(&n->lock);
> -                       if (atomic_read(&n->refcnt) == 1 &&
> +                       if (refcount_read(&n->refcnt) == 1 &&
>                             !(n->nud_state & NUD_PERMANENT)) {
>                                 rcu_assign_pointer(*np,
>                                         rcu_dereference_protected(n->next,
> @@ -218,7 +218,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
>                         neigh_del_timer(n);
>                         n->dead = 1;
>
> -                       if (atomic_read(&n->refcnt) != 1) {
> +                       if (refcount_read(&n->refcnt) != 1) {
>                                 /* The most unpleasant situation.
>                                    We must destroy neighbour entry,
>                                    but someone still uses it.
> @@ -299,7 +299,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device
>
>         NEIGH_CACHE_STAT_INC(tbl, allocs);
>         n->tbl            = tbl;
> -       atomic_set(&n->refcnt, 1);
> +       refcount_set(&n->refcnt, 1);
>         n->dead           = 1;
>  out:
>         return n;
> @@ -408,7 +408,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
>         rcu_read_lock_bh();
>         n = __neigh_lookup_noref(tbl, pkey, dev);
>         if (n) {
> -               if (!atomic_inc_not_zero(&n->refcnt))
> +               if (!refcount_inc_not_zero(&n->refcnt))
>                         n = NULL;
>                 NEIGH_CACHE_STAT_INC(tbl, hits);
>         }
> @@ -437,7 +437,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
>              n = rcu_dereference_bh(n->next)) {
>                 if (!memcmp(n->primary_key, pkey, key_len) &&
>                     net_eq(dev_net(n->dev), net)) {
> -                       if (!atomic_inc_not_zero(&n->refcnt))
> +                       if (!refcount_inc_not_zero(&n->refcnt))
>                                 n = NULL;
>                         NEIGH_CACHE_STAT_INC(tbl, hits);
>                         break;
> @@ -673,7 +673,7 @@ static void neigh_parms_destroy(struct neigh_parms *parms);
>
>  static inline void neigh_parms_put(struct neigh_parms *parms)
>  {
> -       if (atomic_dec_and_test(&parms->refcnt))
> +       if (refcount_dec_and_test(&parms->refcnt))
>                 neigh_parms_destroy(parms);
>  }
>
> @@ -785,7 +785,7 @@ static void neigh_periodic_work(struct work_struct *work)
>                         if (time_before(n->used, n->confirmed))
>                                 n->used = n->confirmed;
>
> -                       if (atomic_read(&n->refcnt) == 1 &&
> +                       if (refcount_read(&n->refcnt) == 1 &&
>                             (state == NUD_FAILED ||
>                              time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
>                                 *np = n->next;
> @@ -1436,7 +1436,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
>         p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
>         if (p) {
>                 p->tbl            = tbl;
> -               atomic_set(&p->refcnt, 1);
> +               refcount_set(&p->refcnt, 1);
>                 p->reachable_time =
>                                 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
>                 dev_hold(dev);
> @@ -1499,7 +1499,7 @@ void neigh_table_init(int index, struct neigh_table *tbl)
>         INIT_LIST_HEAD(&tbl->parms_list);
>         list_add(&tbl->parms.list, &tbl->parms_list);
>         write_pnet(&tbl->parms.net, &init_net);
> -       atomic_set(&tbl->parms.refcnt, 1);
> +       refcount_set(&tbl->parms.refcnt, 1);
>         tbl->parms.reachable_time =
>                           neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
>
> @@ -1746,7 +1746,7 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
>
>         if ((parms->dev &&
>              nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
> -           nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
> +           nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
>             nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
>                         NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
>             /* approximative value for deprecated QUEUE_LEN (in packets) */
> @@ -2183,7 +2183,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
>         ci.ndm_used      = jiffies_to_clock_t(now - neigh->used);
>         ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
>         ci.ndm_updated   = jiffies_to_clock_t(now - neigh->updated);
> -       ci.ndm_refcnt    = atomic_read(&neigh->refcnt) - 1;
> +       ci.ndm_refcnt    = refcount_read(&neigh->refcnt) - 1;
>         read_unlock_bh(&neigh->lock);
>
>         if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
> diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
> index b0c04cf..cc3c21a 100644
> --- a/net/core/net-sysfs.c
> +++ b/net/core/net-sysfs.c
> @@ -1443,7 +1443,7 @@ static void *net_grab_current_ns(void)
>         struct net *ns = current->nsproxy->net_ns;
>  #ifdef CONFIG_NET_NS
>         if (ns)
> -               atomic_inc(&ns->passive);
> +               refcount_inc(&ns->passive);
>  #endif
>         return ns;
>  }
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index 3c4bbec..a0eb969 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -281,7 +281,7 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
>         LIST_HEAD(net_exit_list);
>
>         atomic_set(&net->count, 1);
> -       atomic_set(&net->passive, 1);
> +       refcount_set(&net->passive, 1);
>         net->dev_base_seq = 1;
>         net->user_ns = user_ns;
>         idr_init(&net->netns_ids);
> @@ -358,7 +358,7 @@ static void net_free(struct net *net)
>  void net_drop_ns(void *p)
>  {
>         struct net *ns = p;
> -       if (ns && atomic_dec_and_test(&ns->passive))
> +       if (ns && refcount_dec_and_test(&ns->passive))
>                 net_free(ns);
>  }
>
> diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> index 9424673..8b9083d 100644
> --- a/net/core/netpoll.c
> +++ b/net/core/netpoll.c
> @@ -271,7 +271,7 @@ static void zap_completion_queue(void)
>                         struct sk_buff *skb = clist;
>                         clist = clist->next;
>                         if (!skb_irq_freeable(skb)) {
> -                               atomic_inc(&skb->users);
> +                               refcount_inc(&skb->users);
>                                 dev_kfree_skb_any(skb); /* put this one back */
>                         } else {
>                                 __kfree_skb(skb);
> @@ -303,7 +303,7 @@ static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
>                 return NULL;
>         }
>
> -       atomic_set(&skb->users, 1);
> +       refcount_set(&skb->users, 1);
>         skb_reserve(skb, reserve);
>         return skb;
>  }
> @@ -626,7 +626,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
>                 skb_queue_head_init(&npinfo->txq);
>                 INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
>
> -               atomic_set(&npinfo->refcnt, 1);
> +               refcount_set(&npinfo->refcnt, 1);
>
>                 ops = np->dev->netdev_ops;
>                 if (ops->ndo_netpoll_setup) {
> @@ -636,7 +636,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
>                 }
>         } else {
>                 npinfo = rtnl_dereference(ndev->npinfo);
> -               atomic_inc(&npinfo->refcnt);
> +               refcount_inc(&npinfo->refcnt);
>         }
>
>         npinfo->netpoll = np;
> @@ -815,7 +815,7 @@ void __netpoll_cleanup(struct netpoll *np)
>
>         synchronize_srcu(&netpoll_srcu);
>
> -       if (atomic_dec_and_test(&npinfo->refcnt)) {
> +       if (refcount_dec_and_test(&npinfo->refcnt)) {
>                 const struct net_device_ops *ops;
>
>                 ops = np->dev->netdev_ops;
> diff --git a/net/core/pktgen.c b/net/core/pktgen.c
> index 8e69ce4..787d624 100644
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -3361,7 +3361,7 @@ static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
>  {
>         ktime_t idle_start = ktime_get();
>
> -       while (atomic_read(&(pkt_dev->skb->users)) != 1) {
> +       while (refcount_read(&(pkt_dev->skb->users)) != 1) {
>                 if (signal_pending(current))
>                         break;
>
> @@ -3418,7 +3418,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
>         if (pkt_dev->xmit_mode == M_NETIF_RECEIVE) {
>                 skb = pkt_dev->skb;
>                 skb->protocol = eth_type_trans(skb, skb->dev);
> -               atomic_add(burst, &skb->users);
> +               refcount_add(burst, &skb->users);
>                 local_bh_disable();
>                 do {
>                         ret = netif_receive_skb(skb);
> @@ -3426,11 +3426,11 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
>                                 pkt_dev->errors++;
>                         pkt_dev->sofar++;
>                         pkt_dev->seq_num++;
> -                       if (atomic_read(&skb->users) != burst) {
> +                       if (refcount_read(&skb->users) != burst) {
>                                 /* skb was queued by rps/rfs or taps,
>                                  * so cannot reuse this skb
>                                  */
> -                               atomic_sub(burst - 1, &skb->users);
> +                               WARN_ON(refcount_sub_and_test(burst - 1, &skb->users));
>                                 /* get out of the loop and wait
>                                  * until skb is consumed
>                                  */
> @@ -3446,7 +3446,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
>                 goto out; /* Skips xmit_mode M_START_XMIT */
>         } else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) {
>                 local_bh_disable();
> -               atomic_inc(&pkt_dev->skb->users);
> +               refcount_inc(&pkt_dev->skb->users);
>
>                 ret = dev_queue_xmit(pkt_dev->skb);
>                 switch (ret) {
> @@ -3487,7 +3487,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
>                 pkt_dev->last_ok = 0;
>                 goto unlock;
>         }
> -       atomic_add(burst, &pkt_dev->skb->users);
> +       refcount_add(burst, &pkt_dev->skb->users);
>
>  xmit_more:
>         ret = netdev_start_xmit(pkt_dev->skb, odev, txq, --burst > 0);
> @@ -3513,11 +3513,11 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
>                 /* fallthru */
>         case NETDEV_TX_BUSY:
>                 /* Retry it next time */
> -               atomic_dec(&(pkt_dev->skb->users));
> +               refcount_dec(&(pkt_dev->skb->users));
>                 pkt_dev->last_ok = 0;
>         }
>         if (unlikely(burst))
> -               atomic_sub(burst, &pkt_dev->skb->users);
> +               WARN_ON(refcount_sub_and_test(burst, &pkt_dev->skb->users));
>  unlock:
>         HARD_TX_UNLOCK(odev, txq);
>
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 18b5aae..b2d9035 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -647,7 +647,7 @@ int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int g
>
>         NETLINK_CB(skb).dst_group = group;
>         if (echo)
> -               atomic_inc(&skb->users);
> +               refcount_inc(&skb->users);
>         netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL);
>         if (echo)
>                 err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 5a03730..ac86c66 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -176,7 +176,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node)
>         memset(skb, 0, offsetof(struct sk_buff, tail));
>         skb->head = NULL;
>         skb->truesize = sizeof(struct sk_buff);
> -       atomic_set(&skb->users, 1);
> +       refcount_set(&skb->users, 1);
>
>         skb->mac_header = (typeof(skb->mac_header))~0U;
>  out:
> @@ -247,7 +247,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
>         /* Account for allocated memory : skb + skb->head */
>         skb->truesize = SKB_TRUESIZE(size);
>         skb->pfmemalloc = pfmemalloc;
> -       atomic_set(&skb->users, 1);
> +       refcount_set(&skb->users, 1);
>         skb->head = data;
>         skb->data = data;
>         skb_reset_tail_pointer(skb);
> @@ -268,7 +268,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
>
>                 kmemcheck_annotate_bitfield(&fclones->skb2, flags1);
>                 skb->fclone = SKB_FCLONE_ORIG;
> -               atomic_set(&fclones->fclone_ref, 1);
> +               refcount_set(&fclones->fclone_ref, 1);
>
>                 fclones->skb2.fclone = SKB_FCLONE_CLONE;
>                 fclones->skb2.pfmemalloc = pfmemalloc;
> @@ -315,7 +315,7 @@ struct sk_buff *__build_skb(void *data, unsigned int frag_size)
>
>         memset(skb, 0, offsetof(struct sk_buff, tail));
>         skb->truesize = SKB_TRUESIZE(size);
> -       atomic_set(&skb->users, 1);
> +       refcount_set(&skb->users, 1);
>         skb->head = data;
>         skb->data = data;
>         skb_reset_tail_pointer(skb);
> @@ -630,7 +630,7 @@ static void kfree_skbmem(struct sk_buff *skb)
>                  * This test would have no chance to be true for the clone,
>                  * while here, branch prediction will be good.
>                  */
> -               if (atomic_read(&fclones->fclone_ref) == 1)
> +               if (refcount_read(&fclones->fclone_ref) == 1)
>                         goto fastpath;
>                 break;
>
> @@ -638,7 +638,7 @@ static void kfree_skbmem(struct sk_buff *skb)
>                 fclones = container_of(skb, struct sk_buff_fclones, skb2);
>                 break;
>         }
> -       if (!atomic_dec_and_test(&fclones->fclone_ref))
> +       if (!refcount_dec_and_test(&fclones->fclone_ref))
>                 return;
>  fastpath:
>         kmem_cache_free(skbuff_fclone_cache, fclones);
> @@ -697,9 +697,9 @@ void kfree_skb(struct sk_buff *skb)
>  {
>         if (unlikely(!skb))
>                 return;
> -       if (likely(atomic_read(&skb->users) == 1))
> +       if (likely(refcount_read(&skb->users) == 1))
>                 smp_rmb();
> -       else if (likely(!atomic_dec_and_test(&skb->users)))
> +       else if (likely(!refcount_dec_and_test(&skb->users)))
>                 return;
>         trace_kfree_skb(skb, __builtin_return_address(0));
>         __kfree_skb(skb);
> @@ -749,9 +749,9 @@ void consume_skb(struct sk_buff *skb)
>  {
>         if (unlikely(!skb))
>                 return;
> -       if (likely(atomic_read(&skb->users) == 1))
> +       if (likely(refcount_read(&skb->users) == 1))
>                 smp_rmb();
> -       else if (likely(!atomic_dec_and_test(&skb->users)))
> +       else if (likely(!refcount_dec_and_test(&skb->users)))
>                 return;
>         trace_consume_skb(skb);
>         __kfree_skb(skb);
> @@ -808,9 +808,9 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
>                 return;
>         }
>
> -       if (likely(atomic_read(&skb->users) == 1))
> +       if (likely(refcount_read(&skb->users) == 1))
>                 smp_rmb();
> -       else if (likely(!atomic_dec_and_test(&skb->users)))
> +       else if (likely(!refcount_dec_and_test(&skb->users)))
>                 return;
>         /* if reaching here SKB is ready to free */
>         trace_consume_skb(skb);
> @@ -910,7 +910,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
>         C(head_frag);
>         C(data);
>         C(truesize);
> -       atomic_set(&n->users, 1);
> +       refcount_set(&n->users, 1);
>
>         atomic_inc(&(skb_shinfo(skb)->dataref));
>         skb->cloned = 1;
> @@ -1022,9 +1022,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
>                 return NULL;
>
>         if (skb->fclone == SKB_FCLONE_ORIG &&
> -           atomic_read(&fclones->fclone_ref) == 1) {
> +           refcount_read(&fclones->fclone_ref) == 1) {
>                 n = &fclones->skb2;
> -               atomic_set(&fclones->fclone_ref, 2);
> +               refcount_set(&fclones->fclone_ref, 2);
>         } else {
>                 if (skb_pfmemalloc(skb))
>                         gfp_mask |= __GFP_MEMALLOC;
> @@ -2983,7 +2983,7 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
>                 get_page(pfrag->page);
>
>                 skb->truesize += copy;
> -               atomic_add(copy, &sk->sk_wmem_alloc);
> +               refcount_add(copy, &sk->sk_wmem_alloc);
>                 skb->len += copy;
>                 skb->data_len += copy;
>                 offset += copy;
> @@ -3761,7 +3761,7 @@ struct sk_buff *skb_clone_sk(struct sk_buff *skb)
>         struct sock *sk = skb->sk;
>         struct sk_buff *clone;
>
> -       if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt))
> +       if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
>                 return NULL;
>
>         clone = skb_clone(skb, GFP_ATOMIC);
> diff --git a/net/core/sock.c b/net/core/sock.c
> index f560e08..b11edc1 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1406,7 +1406,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
>                 if (likely(sk->sk_net_refcnt))
>                         get_net(net);
>                 sock_net_set(sk, net);
> -               atomic_set(&sk->sk_wmem_alloc, 1);
> +               refcount_set(&sk->sk_wmem_alloc, 1);
>
>                 mem_cgroup_sk_alloc(sk);
>                 cgroup_sk_alloc(&sk->sk_cgrp_data);
> @@ -1430,7 +1430,7 @@ static void __sk_destruct(struct rcu_head *head)
>                 sk->sk_destruct(sk);
>
>         filter = rcu_dereference_check(sk->sk_filter,
> -                                      atomic_read(&sk->sk_wmem_alloc) == 0);
> +                                      refcount_read(&sk->sk_wmem_alloc) == 0);
>         if (filter) {
>                 sk_filter_uncharge(sk, filter);
>                 RCU_INIT_POINTER(sk->sk_filter, NULL);
> @@ -1475,7 +1475,7 @@ void sk_free(struct sock *sk)
>          * some packets are still in some tx queue.
>          * If not null, sock_wfree() will call __sk_free(sk) later
>          */
> -       if (atomic_dec_and_test(&sk->sk_wmem_alloc))
> +       if (refcount_dec_and_test(&sk->sk_wmem_alloc))
>                 __sk_free(sk);
>  }
>  EXPORT_SYMBOL(sk_free);
> @@ -1511,7 +1511,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
>                 /*
>                  * sk_wmem_alloc set to one (see sk_free() and sock_wfree())
>                  */
> -               atomic_set(&newsk->sk_wmem_alloc, 1);
> +               refcount_set(&newsk->sk_wmem_alloc, 1);
>                 atomic_set(&newsk->sk_omem_alloc, 0);
>                 skb_queue_head_init(&newsk->sk_receive_queue);
>                 skb_queue_head_init(&newsk->sk_write_queue);
> @@ -1564,7 +1564,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
>                  * (Documentation/RCU/rculist_nulls.txt for details)
>                  */
>                 smp_wmb();
> -               atomic_set(&newsk->sk_refcnt, 2);
> +               refcount_set(&newsk->sk_refcnt, 2);
>
>                 /*
>                  * Increment the counter in the same struct proto as the master
> @@ -1633,7 +1633,7 @@ void sock_wfree(struct sk_buff *skb)
>                  * Keep a reference on sk_wmem_alloc, this will be released
>                  * after sk_write_space() call
>                  */
> -               atomic_sub(len - 1, &sk->sk_wmem_alloc);
> +               WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
>                 sk->sk_write_space(sk);
>                 len = 1;
>         }
> @@ -1641,7 +1641,7 @@ void sock_wfree(struct sk_buff *skb)
>          * if sk_wmem_alloc reaches 0, we must finish what sk_free()
>          * could not do because of in-flight packets
>          */
> -       if (atomic_sub_and_test(len, &sk->sk_wmem_alloc))
> +       if (refcount_sub_and_test(len, &sk->sk_wmem_alloc))
>                 __sk_free(sk);
>  }
>  EXPORT_SYMBOL(sock_wfree);
> @@ -1653,7 +1653,7 @@ void __sock_wfree(struct sk_buff *skb)
>  {
>         struct sock *sk = skb->sk;
>
> -       if (atomic_sub_and_test(skb->truesize, &sk->sk_wmem_alloc))
> +       if (refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc))
>                 __sk_free(sk);
>  }
>
> @@ -1675,7 +1675,7 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
>          * is enough to guarantee sk_free() wont free this sock until
>          * all in-flight packets are completed
>          */
> -       atomic_add(skb->truesize, &sk->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk->sk_wmem_alloc);
>  }
>  EXPORT_SYMBOL(skb_set_owner_w);
>
> @@ -1703,7 +1703,7 @@ void skb_orphan_partial(struct sk_buff *skb)
>             || skb->destructor == tcp_wfree
>  #endif
>                 ) {
> -               atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
> +               WARN_ON(refcount_sub_and_test(skb->truesize - 1, &skb->sk->sk_wmem_alloc));
>                 skb->truesize = 1;
>         } else {
>                 skb_orphan(skb);
> @@ -1762,7 +1762,7 @@ EXPORT_SYMBOL(sock_i_ino);
>  struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
>                              gfp_t priority)
>  {
> -       if (force || atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
> +       if (force || refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
>                 struct sk_buff *skb = alloc_skb(size, priority);
>                 if (skb) {
>                         skb_set_owner_w(skb, sk);
> @@ -1837,7 +1837,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo)
>                         break;
>                 set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
>                 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
> -               if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf)
> +               if (refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf)
>                         break;
>                 if (sk->sk_shutdown & SEND_SHUTDOWN)
>                         break;
> @@ -2140,7 +2140,7 @@ int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
>                 if (sk->sk_type == SOCK_STREAM) {
>                         if (sk->sk_wmem_queued < prot->sysctl_wmem[0])
>                                 return 1;
> -               } else if (atomic_read(&sk->sk_wmem_alloc) <
> +               } else if (refcount_read(&sk->sk_wmem_alloc) <
>                            prot->sysctl_wmem[0])
>                                 return 1;
>         }
> @@ -2406,7 +2406,7 @@ static void sock_def_write_space(struct sock *sk)
>         /* Do not wake up a writer until he can make "significant"
>          * progress.  --DaveM
>          */
> -       if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
> +       if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
>                 wq = rcu_dereference(sk->sk_wq);
>                 if (skwq_has_sleeper(wq))
>                         wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
> @@ -2512,7 +2512,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
>          * (Documentation/RCU/rculist_nulls.txt for details)
>          */
>         smp_wmb();
> -       atomic_set(&sk->sk_refcnt, 1);
> +       refcount_set(&sk->sk_refcnt, 1);
>         atomic_set(&sk->sk_drops, 0);
>  }
>  EXPORT_SYMBOL(sock_init_data);
> diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
> index adfc790..616bd53 100644
> --- a/net/dccp/ipv6.c
> +++ b/net/dccp/ipv6.c
> @@ -351,7 +351,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
>         if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) ||
>             np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
>             np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
> -               atomic_inc(&skb->users);
> +               refcount_inc(&skb->users);
>                 ireq->pktopts = skb;
>         }
>         ireq->ir_iif = sk->sk_bound_dev_if;
> diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
> index 7af0ba61..2e22484 100644
> --- a/net/decnet/dn_fib.c
> +++ b/net/decnet/dn_fib.c
> @@ -389,7 +389,7 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct nlattr *att
>         }
>
>         fi->fib_treeref++;
> -       atomic_inc(&fi->fib_clntref);
> +       refcount_inc(&fi->fib_clntref);
>         spin_lock(&dn_fib_info_lock);
>         fi->fib_next = dn_fib_info_list;
>         fi->fib_prev = NULL;
> @@ -425,7 +425,7 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn
>                 switch (type) {
>                 case RTN_NAT:
>                         DN_FIB_RES_RESET(*res);
> -                       atomic_inc(&fi->fib_clntref);
> +                       refcount_inc(&fi->fib_clntref);
>                         return 0;
>                 case RTN_UNICAST:
>                 case RTN_LOCAL:
> @@ -438,7 +438,7 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn
>                         }
>                         if (nhsel < fi->fib_nhs) {
>                                 res->nh_sel = nhsel;
> -                               atomic_inc(&fi->fib_clntref);
> +                               refcount_inc(&fi->fib_clntref);
>                                 return 0;
>                         }
>                         endfor_nexthops(fi);
> diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
> index 482730c..d8f7b6d 100644
> --- a/net/decnet/dn_neigh.c
> +++ b/net/decnet/dn_neigh.c
> @@ -559,7 +559,7 @@ static inline void dn_neigh_format_entry(struct seq_file *seq,
>                    (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
>                    (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
>                    dn->n.nud_state,
> -                  atomic_read(&dn->n.refcnt),
> +                  refcount_read(&dn->n.refcnt),
>                    dn->blksize,
>                    (dn->n.dev) ? dn->n.dev->name : "?");
>         read_unlock(&n->lock);
> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
> index f750698..e771346 100644
> --- a/net/ipv4/af_inet.c
> +++ b/net/ipv4/af_inet.c
> @@ -150,7 +150,7 @@ void inet_sock_destruct(struct sock *sk)
>         }
>
>         WARN_ON(atomic_read(&sk->sk_rmem_alloc));
> -       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
> +       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
>         WARN_ON(sk->sk_wmem_queued);
>         WARN_ON(sk->sk_forward_alloc);
>
> diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
> index 72d6f05..55b5300 100644
> --- a/net/ipv4/cipso_ipv4.c
> +++ b/net/ipv4/cipso_ipv4.c
> @@ -265,7 +265,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
>                     entry->key_len == key_len &&
>                     memcmp(entry->key, key, key_len) == 0) {
>                         entry->activity += 1;
> -                       atomic_inc(&entry->lsm_data->refcount);
> +                       refcount_inc(&entry->lsm_data->refcount);
>                         secattr->cache = entry->lsm_data;
>                         secattr->flags |= NETLBL_SECATTR_CACHE;
>                         secattr->type = NETLBL_NLTYPE_CIPSOV4;
> @@ -332,7 +332,7 @@ int cipso_v4_cache_add(const unsigned char *cipso_ptr,
>         }
>         entry->key_len = cipso_ptr_len;
>         entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
> -       atomic_inc(&secattr->cache->refcount);
> +       refcount_inc(&secattr->cache->refcount);
>         entry->lsm_data = secattr->cache;
>
>         bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETS - 1);
> @@ -375,7 +375,7 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
>         struct cipso_v4_doi *iter;
>
>         list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
> -               if (iter->doi == doi && atomic_read(&iter->refcount))
> +               if (iter->doi == doi && refcount_read(&iter->refcount))
>                         return iter;
>         return NULL;
>  }
> @@ -429,7 +429,7 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
>                 }
>         }
>
> -       atomic_set(&doi_def->refcount, 1);
> +       refcount_set(&doi_def->refcount, 1);
>
>         spin_lock(&cipso_v4_doi_list_lock);
>         if (cipso_v4_doi_search(doi_def->doi)) {
> @@ -533,7 +533,7 @@ int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)
>                 ret_val = -ENOENT;
>                 goto doi_remove_return;
>         }
> -       if (!atomic_dec_and_test(&doi_def->refcount)) {
> +       if (!refcount_dec_and_test(&doi_def->refcount)) {
>                 spin_unlock(&cipso_v4_doi_list_lock);
>                 ret_val = -EBUSY;
>                 goto doi_remove_return;
> @@ -576,7 +576,7 @@ struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
>         doi_def = cipso_v4_doi_search(doi);
>         if (!doi_def)
>                 goto doi_getdef_return;
> -       if (!atomic_inc_not_zero(&doi_def->refcount))
> +       if (!refcount_inc_not_zero(&doi_def->refcount))
>                 doi_def = NULL;
>
>  doi_getdef_return:
> @@ -597,7 +597,7 @@ void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def)
>         if (!doi_def)
>                 return;
>
> -       if (!atomic_dec_and_test(&doi_def->refcount))
> +       if (!refcount_dec_and_test(&doi_def->refcount))
>                 return;
>         spin_lock(&cipso_v4_doi_list_lock);
>         list_del_rcu(&doi_def->list);
> @@ -630,7 +630,7 @@ int cipso_v4_doi_walk(u32 *skip_cnt,
>
>         rcu_read_lock();
>         list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
> -               if (atomic_read(&iter_doi->refcount) > 0) {
> +               if (refcount_read(&iter_doi->refcount) > 0) {
>                         if (doi_cnt++ < *skip_cnt)
>                                 continue;
>                         ret_val = callback(iter_doi, cb_arg);
> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
> index 4cd2ee8..db5ba13 100644
> --- a/net/ipv4/devinet.c
> +++ b/net/ipv4/devinet.c
> @@ -252,7 +252,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
>         /* Reference in_dev->dev */
>         dev_hold(dev);
>         /* Account for reference dev->ip_ptr (below) */
> -       in_dev_hold(in_dev);
> +       refcount_set(&in_dev->refcnt, 1);
>
>         err = devinet_sysctl_register(in_dev);
>         if (err) {
> diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
> index 7a5b4c7..49ce888 100644
> --- a/net/ipv4/fib_semantics.c
> +++ b/net/ipv4/fib_semantics.c
> @@ -1185,7 +1185,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
>         }
>
>         fi->fib_treeref++;
> -       atomic_inc(&fi->fib_clntref);
> +       refcount_set(&fi->fib_clntref, 1);
>         spin_lock_bh(&fib_info_lock);
>         hlist_add_head(&fi->fib_hash,
>                        &fib_info_hash[fib_info_hashfn(fi)]);
> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
> index 2919d1a..77e51ca 100644
> --- a/net/ipv4/fib_trie.c
> +++ b/net/ipv4/fib_trie.c
> @@ -1542,7 +1542,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
>                         }
>
>                         if (!(fib_flags & FIB_LOOKUP_NOREF))
> -                               atomic_inc(&fi->fib_clntref);
> +                               refcount_inc(&fi->fib_clntref);
>
>                         res->prefixlen = KEYLENGTH - fa->fa_slen;
>                         res->nh_sel = nhsel;
> diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
> index 68d6221..3c675e3 100644
> --- a/net/ipv4/igmp.c
> +++ b/net/ipv4/igmp.c
> @@ -173,7 +173,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
>
>  static void ip_ma_put(struct ip_mc_list *im)
>  {
> -       if (atomic_dec_and_test(&im->refcnt)) {
> +       if (refcount_dec_and_test(&im->refcnt)) {
>                 in_dev_put(im->interface);
>                 kfree_rcu(im, rcu);
>         }
> @@ -199,7 +199,7 @@ static void igmp_stop_timer(struct ip_mc_list *im)
>  {
>         spin_lock_bh(&im->lock);
>         if (del_timer(&im->timer))
> -               atomic_dec(&im->refcnt);
> +               refcount_dec(&im->refcnt);
>         im->tm_running = 0;
>         im->reporter = 0;
>         im->unsolicit_count = 0;
> @@ -213,7 +213,7 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
>
>         im->tm_running = 1;
>         if (!mod_timer(&im->timer, jiffies+tv+2))
> -               atomic_inc(&im->refcnt);
> +               refcount_inc(&im->refcnt);
>  }
>
>  static void igmp_gq_start_timer(struct in_device *in_dev)
> @@ -244,7 +244,7 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
>                         spin_unlock_bh(&im->lock);
>                         return;
>                 }
> -               atomic_dec(&im->refcnt);
> +               refcount_dec(&im->refcnt);
>         }
>         igmp_start_timer(im, max_delay);
>         spin_unlock_bh(&im->lock);
> @@ -1367,7 +1367,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
>         /* initial mode is (EX, empty) */
>         im->sfmode = MCAST_EXCLUDE;
>         im->sfcount[MCAST_EXCLUDE] = 1;
> -       atomic_set(&im->refcnt, 1);
> +       refcount_set(&im->refcnt, 1);
>         spin_lock_init(&im->lock);
>  #ifdef CONFIG_IP_MULTICAST
>         setup_timer(&im->timer, igmp_timer_expire, (unsigned long)im);
> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> index 19ea045..edf004d 100644
> --- a/net/ipv4/inet_connection_sock.c
> +++ b/net/ipv4/inet_connection_sock.c
> @@ -630,7 +630,7 @@ static void reqsk_queue_hash_req(struct request_sock *req,
>          * are committed to memory and refcnt initialized.
>          */
>         smp_wmb();
> -       atomic_set(&req->rsk_refcnt, 2 + 1);
> +       refcount_set(&req->rsk_refcnt, 2 + 1);
>  }
>
>  void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
> diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
> index b5e9317..96e95e8 100644
> --- a/net/ipv4/inet_fragment.c
> +++ b/net/ipv4/inet_fragment.c
> @@ -276,11 +276,11 @@ static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f)
>  void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
>  {
>         if (del_timer(&fq->timer))
> -               atomic_dec(&fq->refcnt);
> +               refcount_dec(&fq->refcnt);
>
>         if (!(fq->flags & INET_FRAG_COMPLETE)) {
>                 fq_unlink(fq, f);
> -               atomic_dec(&fq->refcnt);
> +               refcount_dec(&fq->refcnt);
>         }
>  }
>  EXPORT_SYMBOL(inet_frag_kill);
> @@ -329,7 +329,7 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
>          */
>         hlist_for_each_entry(qp, &hb->chain, list) {
>                 if (qp->net == nf && f->match(qp, arg)) {
> -                       atomic_inc(&qp->refcnt);
> +                       refcount_inc(&qp->refcnt);
>                         spin_unlock(&hb->chain_lock);
>                         qp_in->flags |= INET_FRAG_COMPLETE;
>                         inet_frag_put(qp_in, f);
> @@ -339,9 +339,9 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
>  #endif
>         qp = qp_in;
>         if (!mod_timer(&qp->timer, jiffies + nf->timeout))
> -               atomic_inc(&qp->refcnt);
> +               refcount_inc(&qp->refcnt);
>
> -       atomic_inc(&qp->refcnt);
> +       refcount_inc(&qp->refcnt);
>         hlist_add_head(&qp->list, &hb->chain);
>
>         spin_unlock(&hb->chain_lock);
> @@ -370,7 +370,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
>
>         setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
>         spin_lock_init(&q->lock);
> -       atomic_set(&q->refcnt, 1);
> +       refcount_set(&q->refcnt, 1);
>
>         return q;
>  }
> @@ -405,7 +405,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
>         spin_lock(&hb->chain_lock);
>         hlist_for_each_entry(q, &hb->chain, list) {
>                 if (q->net == nf && f->match(q, key)) {
> -                       atomic_inc(&q->refcnt);
> +                       refcount_inc(&q->refcnt);
>                         spin_unlock(&hb->chain_lock);
>                         return q;
>                 }
> diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
> index ca97835..e34f3bd 100644
> --- a/net/ipv4/inet_hashtables.c
> +++ b/net/ipv4/inet_hashtables.c
> @@ -249,7 +249,7 @@ EXPORT_SYMBOL_GPL(__inet_lookup_listener);
>  /* All sockets share common refcount, but have different destructors */
>  void sock_gen_put(struct sock *sk)
>  {
> -       if (!atomic_dec_and_test(&sk->sk_refcnt))
> +       if (!refcount_dec_and_test(&sk->sk_refcnt))
>                 return;
>
>         if (sk->sk_state == TCP_TIME_WAIT)
> @@ -290,7 +290,7 @@ struct sock *__inet_lookup_established(struct net *net,
>                         continue;
>                 if (likely(INET_MATCH(sk, net, acookie,
>                                       saddr, daddr, ports, dif))) {
> -                       if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
> +                       if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
>                                 goto out;
>                         if (unlikely(!INET_MATCH(sk, net, acookie,
>                                                  saddr, daddr, ports, dif))) {
> diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
> index ddcd56c..e0b6cc5 100644
> --- a/net/ipv4/inet_timewait_sock.c
> +++ b/net/ipv4/inet_timewait_sock.c
> @@ -76,7 +76,7 @@ void inet_twsk_free(struct inet_timewait_sock *tw)
>
>  void inet_twsk_put(struct inet_timewait_sock *tw)
>  {
> -       if (atomic_dec_and_test(&tw->tw_refcnt))
> +       if (refcount_dec_and_test(&tw->tw_refcnt))
>                 inet_twsk_free(tw);
>  }
>  EXPORT_SYMBOL_GPL(inet_twsk_put);
> @@ -131,7 +131,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
>          * We can use atomic_set() because prior spin_lock()/spin_unlock()
>          * committed into memory all tw fields.
>          */
> -       atomic_set(&tw->tw_refcnt, 4);
> +       refcount_set(&tw->tw_refcnt, 4);
>         inet_twsk_add_node_rcu(tw, &ehead->chain);
>
>         /* Step 3: Remove SK from hash chain */
> @@ -195,7 +195,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
>                  * to a non null value before everything is setup for this
>                  * timewait socket.
>                  */
> -               atomic_set(&tw->tw_refcnt, 0);
> +               refcount_set(&tw->tw_refcnt, 0);
>
>                 __module_get(tw->tw_prot->owner);
>         }
> @@ -279,7 +279,7 @@ void inet_twsk_purge(struct inet_hashinfo *hashinfo,
>                                 atomic_read(&twsk_net(tw)->count))
>                                 continue;
>
> -                       if (unlikely(!atomic_inc_not_zero(&tw->tw_refcnt)))
> +                       if (unlikely(!refcount_inc_not_zero(&tw->tw_refcnt)))
>                                 continue;
>
>                         if (unlikely((tw->tw_family != family) ||
> diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
> index 86fa458..c5a117c 100644
> --- a/net/ipv4/inetpeer.c
> +++ b/net/ipv4/inetpeer.c
> @@ -115,7 +115,7 @@ static void inetpeer_gc_worker(struct work_struct *work)
>
>                 n = list_entry(p->gc_list.next, struct inet_peer, gc_list);
>
> -               if (!atomic_read(&p->refcnt)) {
> +               if (refcount_read(&p->refcnt) == 1) {
>                         list_del(&p->gc_list);
>                         kmem_cache_free(peer_cachep, p);
>                 }
> @@ -202,10 +202,11 @@ static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
>                 int cmp = inetpeer_addr_cmp(daddr, &u->daddr);
>                 if (cmp == 0) {
>                         /* Before taking a reference, check if this entry was
> -                        * deleted (refcnt=-1)
> +                        * deleted (refcnt=0)
>                          */
> -                       if (!atomic_add_unless(&u->refcnt, 1, -1))
> +                       if (!refcount_inc_not_zero(&u->refcnt)) {
>                                 u = NULL;
> +                       }
>                         return u;
>                 }
>                 if (cmp == -1)
> @@ -382,11 +383,10 @@ static int inet_peer_gc(struct inet_peer_base *base,
>         while (stackptr > stack) {
>                 stackptr--;
>                 p = rcu_deref_locked(**stackptr, base);
> -               if (atomic_read(&p->refcnt) == 0) {
> +               if (refcount_read(&p->refcnt) == 1) {
>                         smp_rmb();
>                         delta = (__u32)jiffies - p->dtime;
> -                       if (delta >= ttl &&
> -                           atomic_cmpxchg(&p->refcnt, 0, -1) == 0) {
> +                       if (delta >= ttl && refcount_dec_if_one(&p->refcnt)) {
>                                 p->gc_next = gchead;
>                                 gchead = p;
>                         }
> @@ -432,7 +432,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
>  relookup:
>         p = lookup(daddr, stack, base);
>         if (p != peer_avl_empty) {
> -               atomic_inc(&p->refcnt);
> +               refcount_inc(&p->refcnt);
>                 write_sequnlock_bh(&base->lock);
>                 return p;
>         }
> @@ -444,7 +444,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
>         p = create ? kmem_cache_alloc(peer_cachep, GFP_ATOMIC) : NULL;
>         if (p) {
>                 p->daddr = *daddr;
> -               atomic_set(&p->refcnt, 1);
> +               refcount_set(&p->refcnt, 2);
>                 atomic_set(&p->rid, 0);
>                 p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
>                 p->rate_tokens = 0;
> @@ -468,7 +468,7 @@ void inet_putpeer(struct inet_peer *p)
>  {
>         p->dtime = (__u32)jiffies;
>         smp_mb__before_atomic();
> -       atomic_dec(&p->refcnt);
> +       refcount_dec(&p->refcnt);
>  }
>  EXPORT_SYMBOL_GPL(inet_putpeer);
>
> diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
> index bbe7f72..4fed6f6 100644
> --- a/net/ipv4/ip_fragment.c
> +++ b/net/ipv4/ip_fragment.c
> @@ -303,7 +303,7 @@ static int ip_frag_reinit(struct ipq *qp)
>         unsigned int sum_truesize = 0;
>
>         if (!mod_timer(&qp->q.timer, jiffies + qp->q.net->timeout)) {
> -               atomic_inc(&qp->q.refcnt);
> +               refcount_inc(&qp->q.refcnt);
>                 return -ETIMEDOUT;
>         }
>
> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> index fac275c4..4c611f2 100644
> --- a/net/ipv4/ip_output.c
> +++ b/net/ipv4/ip_output.c
> @@ -1030,7 +1030,7 @@ static int __ip_append_data(struct sock *sk,
>                                                 (flags & MSG_DONTWAIT), &err);
>                         } else {
>                                 skb = NULL;
> -                               if (atomic_read(&sk->sk_wmem_alloc) <=
> +                               if (refcount_read(&sk->sk_wmem_alloc) <=
>                                     2 * sk->sk_sndbuf)
>                                         skb = sock_wmalloc(sk,
>                                                            alloclen + hh_len + 15, 1,
> @@ -1135,7 +1135,7 @@ static int __ip_append_data(struct sock *sk,
>                         skb->len += copy;
>                         skb->data_len += copy;
>                         skb->truesize += copy;
> -                       atomic_add(copy, &sk->sk_wmem_alloc);
> +                       refcount_add(copy, &sk->sk_wmem_alloc);
>                 }
>                 offset += copy;
>                 length -= copy;
> @@ -1359,7 +1359,7 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
>                 skb->len += len;
>                 skb->data_len += len;
>                 skb->truesize += len;
> -               atomic_add(len, &sk->sk_wmem_alloc);
> +               refcount_add(len, &sk->sk_wmem_alloc);
>                 offset += len;
>                 size -= len;
>         }
> diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
> index 21db00d..9b8bb40 100644
> --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
> +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
> @@ -22,6 +22,7 @@
>  #include <linux/icmp.h>
>  #include <linux/if_arp.h>
>  #include <linux/seq_file.h>
> +#include <linux/refcount.h>
>  #include <linux/netfilter_arp.h>
>  #include <linux/netfilter/x_tables.h>
>  #include <linux/netfilter_ipv4/ip_tables.h>
> @@ -40,8 +41,8 @@ MODULE_DESCRIPTION("Xtables: CLUSTERIP target");
>
>  struct clusterip_config {
>         struct list_head list;                  /* list of all configs */
> -       atomic_t refcount;                      /* reference count */
> -       atomic_t entries;                       /* number of entries/rules
> +       refcount_t refcount;                    /* reference count */
> +       refcount_t entries;                     /* number of entries/rules
>                                                  * referencing us */
>
>         __be32 clusterip;                       /* the IP address */
> @@ -77,7 +78,7 @@ struct clusterip_net {
>  static inline void
>  clusterip_config_get(struct clusterip_config *c)
>  {
> -       atomic_inc(&c->refcount);
> +       refcount_inc(&c->refcount);
>  }
>
>
> @@ -89,7 +90,7 @@ static void clusterip_config_rcu_free(struct rcu_head *head)
>  static inline void
>  clusterip_config_put(struct clusterip_config *c)
>  {
> -       if (atomic_dec_and_test(&c->refcount))
> +       if (refcount_dec_and_test(&c->refcount))
>                 call_rcu_bh(&c->rcu, clusterip_config_rcu_free);
>  }
>
> @@ -103,7 +104,7 @@ clusterip_config_entry_put(struct clusterip_config *c)
>         struct clusterip_net *cn = net_generic(net, clusterip_net_id);
>
>         local_bh_disable();
> -       if (atomic_dec_and_lock(&c->entries, &cn->lock)) {
> +       if (refcount_dec_and_lock(&c->entries, &cn->lock)) {
>                 list_del_rcu(&c->list);
>                 spin_unlock(&cn->lock);
>                 local_bh_enable();
> @@ -144,10 +145,10 @@ clusterip_config_find_get(struct net *net, __be32 clusterip, int entry)
>         rcu_read_lock_bh();
>         c = __clusterip_config_find(net, clusterip);
>         if (c) {
> -               if (unlikely(!atomic_inc_not_zero(&c->refcount)))
> +               if (unlikely(!refcount_inc_not_zero(&c->refcount)))
>                         c = NULL;
>                 else if (entry)
> -                       atomic_inc(&c->entries);
> +                       refcount_inc(&c->entries);
>         }
>         rcu_read_unlock_bh();
>
> @@ -182,8 +183,8 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
>         clusterip_config_init_nodelist(c, i);
>         c->hash_mode = i->hash_mode;
>         c->hash_initval = i->hash_initval;
> -       atomic_set(&c->refcount, 1);
> -       atomic_set(&c->entries, 1);
> +       refcount_set(&c->refcount, 1);
> +       refcount_set(&c->entries, 1);
>
>  #ifdef CONFIG_PROC_FS
>         {
> diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
> index 86cca61..4ecef05 100644
> --- a/net/ipv4/ping.c
> +++ b/net/ipv4/ping.c
> @@ -289,7 +289,7 @@ void ping_close(struct sock *sk, long timeout)
>  {
>         pr_debug("ping_close(sk=%p,sk->num=%u)\n",
>                  inet_sk(sk), inet_sk(sk)->inet_num);
> -       pr_debug("isk->refcnt = %d\n", sk->sk_refcnt.counter);
> +       pr_debug("isk->refcnt = %d\n", refcount_read(&sk->sk_refcnt));
>
>         sk_common_release(sk);
>  }
> @@ -1123,7 +1123,7 @@ static void ping_v4_format_sock(struct sock *sp, struct seq_file *f,
>                 0, 0L, 0,
>                 from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
>                 0, sock_i_ino(sp),
> -               atomic_read(&sp->sk_refcnt), sp,
> +               refcount_read(&sp->sk_refcnt), sp,
>                 atomic_read(&sp->sk_drops));
>  }
>
> diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
> index 4e49e5c..c772a96 100644
> --- a/net/ipv4/raw.c
> +++ b/net/ipv4/raw.c
> @@ -1054,7 +1054,7 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
>                 0, 0L, 0,
>                 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
>                 0, sock_i_ino(sp),
> -               atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
> +               refcount_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
>  }
>
>  static int raw_seq_show(struct seq_file *seq, void *v)
> diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
> index 3e88467..1f7b47e 100644
> --- a/net/ipv4/syncookies.c
> +++ b/net/ipv4/syncookies.c
> @@ -223,7 +223,7 @@ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
>         child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst,
>                                                  NULL, &own_req);
>         if (child) {
> -               atomic_set(&req->rsk_refcnt, 1);
> +               refcount_set(&req->rsk_refcnt, 1);
>                 sock_rps_save_rxhash(child, skb);
>                 inet_csk_reqsk_queue_add(sk, req, child);
>         } else {
> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index 4a04496..bb42a42 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -642,7 +642,7 @@ static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
>         return skb->len < size_goal &&
>                sysctl_tcp_autocorking &&
>                skb != tcp_write_queue_head(sk) &&
> -              atomic_read(&sk->sk_wmem_alloc) > skb->truesize;
> +              refcount_read(&sk->sk_wmem_alloc) > skb->truesize;
>  }
>
>  static void tcp_push(struct sock *sk, int flags, int mss_now,
> @@ -670,7 +670,7 @@ static void tcp_push(struct sock *sk, int flags, int mss_now,
>                 /* It is possible TX completion already happened
>                  * before we set TSQ_THROTTLED.
>                  */
> -               if (atomic_read(&sk->sk_wmem_alloc) > skb->truesize)
> +               if (refcount_read(&sk->sk_wmem_alloc) > skb->truesize)
>                         return;
>         }
>
> diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
> index 4e777a3..ca4a679 100644
> --- a/net/ipv4/tcp_fastopen.c
> +++ b/net/ipv4/tcp_fastopen.c
> @@ -213,7 +213,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
>         inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS,
>                                   TCP_TIMEOUT_INIT, TCP_RTO_MAX);
>
> -       atomic_set(&req->rsk_refcnt, 2);
> +       refcount_set(&req->rsk_refcnt, 2);
>
>         /* Now finish processing the fastopen child socket. */
>         inet_csk(child)->icsk_af_ops->rebuild_header(child);
> diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
> index fe9da4f..adcdcef 100644
> --- a/net/ipv4/tcp_ipv4.c
> +++ b/net/ipv4/tcp_ipv4.c
> @@ -2263,7 +2263,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
>                 from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)),
>                 icsk->icsk_probes_out,
>                 sock_i_ino(sk),
> -               atomic_read(&sk->sk_refcnt), sk,
> +               refcount_read(&sk->sk_refcnt), sk,
>                 jiffies_to_clock_t(icsk->icsk_rto),
>                 jiffies_to_clock_t(icsk->icsk_ack.ato),
>                 (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
> @@ -2289,7 +2289,7 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw,
>                 " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
>                 i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
>                 3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
> -               atomic_read(&tw->tw_refcnt), tw);
> +               refcount_read(&tw->tw_refcnt), tw);
>  }
>
>  #define TMPSZ 150
> diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
> index bc68da3..11f69bb 100644
> --- a/net/ipv4/tcp_offload.c
> +++ b/net/ipv4/tcp_offload.c
> @@ -152,7 +152,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
>                 swap(gso_skb->sk, skb->sk);
>                 swap(gso_skb->destructor, skb->destructor);
>                 sum_truesize += skb->truesize;
> -               atomic_add(sum_truesize - gso_skb->truesize,
> +               refcount_add(sum_truesize - gso_skb->truesize,
>                            &skb->sk->sk_wmem_alloc);
>         }
>
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index 1d5331a..91cdf1c 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -862,12 +862,11 @@ void tcp_wfree(struct sk_buff *skb)
>         struct sock *sk = skb->sk;
>         struct tcp_sock *tp = tcp_sk(sk);
>         unsigned long flags, nval, oval;
> -       int wmem;
>
>         /* Keep one reference on sk_wmem_alloc.
>          * Will be released by sk_free() from here or tcp_tasklet_func()
>          */
> -       wmem = atomic_sub_return(skb->truesize - 1, &sk->sk_wmem_alloc);
> +       WARN_ON(refcount_sub_and_test(skb->truesize - 1, &sk->sk_wmem_alloc));
>
>         /* If this softirq is serviced by ksoftirqd, we are likely under stress.
>          * Wait until our queues (qdisc + devices) are drained.
> @@ -876,7 +875,7 @@ void tcp_wfree(struct sk_buff *skb)
>          * - chance for incoming ACK (processed by another cpu maybe)
>          *   to migrate this flow (skb->ooo_okay will be eventually set)
>          */
> -       if (wmem >= SKB_TRUESIZE(1) && this_cpu_ksoftirqd() == current)
> +       if (refcount_read(&sk->sk_wmem_alloc) >= SKB_TRUESIZE(1) && this_cpu_ksoftirqd() == current)
>                 goto out;
>
>         for (oval = READ_ONCE(sk->sk_tsq_flags);; oval = nval) {
> @@ -973,7 +972,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
>         skb->sk = sk;
>         skb->destructor = skb_is_tcp_pure_ack(skb) ? __sock_wfree : tcp_wfree;
>         skb_set_hash_from_sk(skb, sk);
> -       atomic_add(skb->truesize, &sk->sk_wmem_alloc);
> +       refcount_add(skb->truesize, &sk->sk_wmem_alloc);
>
>         /* Build TCP header and checksum it. */
>         th = (struct tcphdr *)skb->data;
> @@ -2091,7 +2090,7 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
>         limit = min_t(u32, limit, sysctl_tcp_limit_output_bytes);
>         limit <<= factor;
>
> -       if (atomic_read(&sk->sk_wmem_alloc) > limit) {
> +       if (refcount_read(&sk->sk_wmem_alloc) > limit) {
>                 /* Always send the 1st or 2nd skb in write queue.
>                  * No need to wait for TX completion to call us back,
>                  * after softirq/tasklet schedule.
> @@ -2107,7 +2106,7 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
>                  * test again the condition.
>                  */
>                 smp_mb__after_atomic();
> -               if (atomic_read(&sk->sk_wmem_alloc) > limit)
> +               if (refcount_read(&sk->sk_wmem_alloc) > limit)
>                         return true;
>         }
>         return false;
> @@ -2724,7 +2723,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
>         /* Do not sent more than we queued. 1/4 is reserved for possible
>          * copying overhead: fragmentation, tunneling, mangling etc.
>          */
> -       if (atomic_read(&sk->sk_wmem_alloc) >
> +       if (refcount_read(&sk->sk_wmem_alloc) >
>             min_t(u32, sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2),
>                   sk->sk_sndbuf))
>                 return -EAGAIN;
> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> index 1307a7c..9cf2697 100644
> --- a/net/ipv4/udp.c
> +++ b/net/ipv4/udp.c
> @@ -589,7 +589,7 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
>
>         sk = __udp4_lib_lookup(net, saddr, sport, daddr, dport,
>                                dif, &udp_table, NULL);
> -       if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
> +       if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
>                 sk = NULL;
>         return sk;
>  }
> @@ -2093,7 +2093,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
>                                              uh->source, iph->saddr, dif);
>         }
>
> -       if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2))
> +       if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
>                 return;
>
>         skb->sk = sk;
> @@ -2541,7 +2541,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
>                 0, 0L, 0,
>                 from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
>                 0, sock_i_ino(sp),
> -               atomic_read(&sp->sk_refcnt), sp,
> +               refcount_read(&sp->sk_refcnt), sp,
>                 atomic_read(&sp->sk_drops));
>  }
>
> diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
> index 9a89c10..4515836 100644
> --- a/net/ipv4/udp_diag.c
> +++ b/net/ipv4/udp_diag.c
> @@ -55,7 +55,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
>                                 req->id.idiag_dport,
>                                 req->id.idiag_if, tbl, NULL);
>  #endif
> -       if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
> +       if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
>                 sk = NULL;
>         rcu_read_unlock();
>         err = -ENOENT;
> @@ -206,7 +206,7 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
>                 return -EINVAL;
>         }
>
> -       if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
> +       if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
>                 sk = NULL;
>
>         rcu_read_unlock();
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index c1e124b..9db691e 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -419,7 +419,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
>         }
>
>         /* One reference from device. */
> -       in6_dev_hold(ndev);
> +       refcount_set(&ndev->refcnt, 1);
>
>         if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
>                 ndev->cnf.accept_dad = -1;
> @@ -1009,7 +1009,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
>         ifa->idev = idev;
>         in6_dev_hold(idev);
>         /* For caller */
> -       in6_ifa_hold(ifa);
> +       refcount_set(&ifa->refcnt, 1);
>
>         /* Add to big hash table */
>         hash = inet6_addr_hash(addr);
> diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
> index a8f6986..9340804 100644
> --- a/net/ipv6/addrlabel.c
> +++ b/net/ipv6/addrlabel.c
> @@ -18,6 +18,7 @@
>  #include <linux/if_addrlabel.h>
>  #include <linux/netlink.h>
>  #include <linux/rtnetlink.h>
> +#include <linux/refcount.h>
>
>  #if 0
>  #define ADDRLABEL(x...) printk(x)
> @@ -36,7 +37,7 @@ struct ip6addrlbl_entry {
>         int addrtype;
>         u32 label;
>         struct hlist_node list;
> -       atomic_t refcnt;
> +       refcount_t refcnt;
>         struct rcu_head rcu;
>  };
>
> @@ -137,12 +138,12 @@ static void ip6addrlbl_free_rcu(struct rcu_head *h)
>
>  static bool ip6addrlbl_hold(struct ip6addrlbl_entry *p)
>  {
> -       return atomic_inc_not_zero(&p->refcnt);
> +       return refcount_inc_not_zero(&p->refcnt);
>  }
>
>  static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p)
>  {
> -       if (atomic_dec_and_test(&p->refcnt))
> +       if (refcount_dec_and_test(&p->refcnt))
>                 call_rcu(&p->rcu, ip6addrlbl_free_rcu);
>  }
>
> @@ -236,7 +237,7 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net,
>         newp->label = label;
>         INIT_HLIST_NODE(&newp->list);
>         write_pnet(&newp->lbl_net, net);
> -       atomic_set(&newp->refcnt, 1);
> +       refcount_set(&newp->refcnt, 1);
>         return newp;
>  }
>
> diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
> index 514ac25..0bbab8a 100644
> --- a/net/ipv6/anycast.c
> +++ b/net/ipv6/anycast.c
> @@ -203,12 +203,12 @@ void ipv6_sock_ac_close(struct sock *sk)
>
>  static void aca_get(struct ifacaddr6 *aca)
>  {
> -       atomic_inc(&aca->aca_refcnt);
> +       refcount_inc(&aca->aca_refcnt);
>  }
>
>  static void aca_put(struct ifacaddr6 *ac)
>  {
> -       if (atomic_dec_and_test(&ac->aca_refcnt)) {
> +       if (refcount_dec_and_test(&ac->aca_refcnt)) {
>                 in6_dev_put(ac->aca_idev);
>                 dst_release(&ac->aca_rt->dst);
>                 kfree(ac);
> @@ -232,7 +232,7 @@ static struct ifacaddr6 *aca_alloc(struct rt6_info *rt,
>         aca->aca_users = 1;
>         /* aca_tstamp should be updated upon changes */
>         aca->aca_cstamp = aca->aca_tstamp = jiffies;
> -       atomic_set(&aca->aca_refcnt, 1);
> +       refcount_set(&aca->aca_refcnt, 1);
>
>         return aca;
>  }
> diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
> index 37ac9de..a475564 100644
> --- a/net/ipv6/calipso.c
> +++ b/net/ipv6/calipso.c
> @@ -227,7 +227,7 @@ static int calipso_cache_check(const unsigned char *key,
>                     entry->key_len == key_len &&
>                     memcmp(entry->key, key, key_len) == 0) {
>                         entry->activity += 1;
> -                       atomic_inc(&entry->lsm_data->refcount);
> +                       refcount_inc(&entry->lsm_data->refcount);
>                         secattr->cache = entry->lsm_data;
>                         secattr->flags |= NETLBL_SECATTR_CACHE;
>                         secattr->type = NETLBL_NLTYPE_CALIPSO;
> @@ -296,7 +296,7 @@ static int calipso_cache_add(const unsigned char *calipso_ptr,
>         }
>         entry->key_len = calipso_ptr_len;
>         entry->hash = calipso_map_cache_hash(calipso_ptr, calipso_ptr_len);
> -       atomic_inc(&secattr->cache->refcount);
> +       refcount_inc(&secattr->cache->refcount);
>         entry->lsm_data = secattr->cache;
>
>         bkt = entry->hash & (CALIPSO_CACHE_BUCKETS - 1);
> @@ -338,7 +338,7 @@ static struct calipso_doi *calipso_doi_search(u32 doi)
>         struct calipso_doi *iter;
>
>         list_for_each_entry_rcu(iter, &calipso_doi_list, list)
> -               if (iter->doi == doi && atomic_read(&iter->refcount))
> +               if (iter->doi == doi && refcount_read(&iter->refcount))
>                         return iter;
>         return NULL;
>  }
> @@ -370,7 +370,7 @@ static int calipso_doi_add(struct calipso_doi *doi_def,
>         if (doi_def->doi == CALIPSO_DOI_UNKNOWN)
>                 goto doi_add_return;
>
> -       atomic_set(&doi_def->refcount, 1);
> +       refcount_set(&doi_def->refcount, 1);
>
>         spin_lock(&calipso_doi_list_lock);
>         if (calipso_doi_search(doi_def->doi)) {
> @@ -458,7 +458,7 @@ static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info)
>                 ret_val = -ENOENT;
>                 goto doi_remove_return;
>         }
> -       if (!atomic_dec_and_test(&doi_def->refcount)) {
> +       if (!refcount_dec_and_test(&doi_def->refcount)) {
>                 spin_unlock(&calipso_doi_list_lock);
>                 ret_val = -EBUSY;
>                 goto doi_remove_return;
> @@ -499,7 +499,7 @@ static struct calipso_doi *calipso_doi_getdef(u32 doi)
>         doi_def = calipso_doi_search(doi);
>         if (!doi_def)
>                 goto doi_getdef_return;
> -       if (!atomic_inc_not_zero(&doi_def->refcount))
> +       if (!refcount_inc_not_zero(&doi_def->refcount))
>                 doi_def = NULL;
>
>  doi_getdef_return:
> @@ -520,7 +520,7 @@ static void calipso_doi_putdef(struct calipso_doi *doi_def)
>         if (!doi_def)
>                 return;
>
> -       if (!atomic_dec_and_test(&doi_def->refcount))
> +       if (!refcount_dec_and_test(&doi_def->refcount))
>                 return;
>         spin_lock(&calipso_doi_list_lock);
>         list_del_rcu(&doi_def->list);
> @@ -553,7 +553,7 @@ static int calipso_doi_walk(u32 *skip_cnt,
>
>         rcu_read_lock();
>         list_for_each_entry_rcu(iter_doi, &calipso_doi_list, list)
> -               if (atomic_read(&iter_doi->refcount) > 0) {
> +               if (refcount_read(&iter_doi->refcount) > 0) {
>                         if (doi_cnt++ < *skip_cnt)
>                                 continue;
>                         ret_val = callback(iter_doi, cb_arg);
> diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
> index a3eaafd..0470d88 100644
> --- a/net/ipv6/datagram.c
> +++ b/net/ipv6/datagram.c
> @@ -1039,6 +1039,6 @@ void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
>                    from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
>                    0,
>                    sock_i_ino(sp),
> -                  atomic_read(&sp->sk_refcnt), sp,
> +                  refcount_read(&sp->sk_refcnt), sp,
>                    atomic_read(&sp->sk_drops));
>  }
> diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
> index e419850..51e04e6 100644
> --- a/net/ipv6/exthdrs.c
> +++ b/net/ipv6/exthdrs.c
> @@ -995,7 +995,7 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
>                         *((char **)&opt2->dst1opt) += dif;
>                 if (opt2->srcrt)
>                         *((char **)&opt2->srcrt) += dif;
> -               atomic_set(&opt2->refcnt, 1);
> +               refcount_set(&opt2->refcnt, 1);
>         }
>         return opt2;
>  }
> @@ -1080,7 +1080,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
>                 return ERR_PTR(-ENOBUFS);
>
>         memset(opt2, 0, tot_len);
> -       atomic_set(&opt2->refcnt, 1);
> +       refcount_set(&opt2->refcnt, 1);
>         opt2->tot_len = tot_len;
>         p = (char *)(opt2 + 1);
>
> diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
> index 02761c9..e707108 100644
> --- a/net/ipv6/inet6_hashtables.c
> +++ b/net/ipv6/inet6_hashtables.c
> @@ -75,7 +75,7 @@ struct sock *__inet6_lookup_established(struct net *net,
>                         continue;
>                 if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif))
>                         continue;
> -               if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
> +               if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
>                         goto out;
>
>                 if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports, dif))) {
> @@ -172,7 +172,7 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
>
>         sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
>                             ntohs(dport), dif, &refcounted);
> -       if (sk && !refcounted && !atomic_inc_not_zero(&sk->sk_refcnt))
> +       if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
>                 sk = NULL;
>         return sk;
>  }
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 70d0de40..cf36fc2 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -1455,7 +1455,7 @@ static int __ip6_append_data(struct sock *sk,
>                                                 (flags & MSG_DONTWAIT), &err);
>                         } else {
>                                 skb = NULL;
> -                               if (atomic_read(&sk->sk_wmem_alloc) <=
> +                               if (refcount_read(&sk->sk_wmem_alloc) <=
>                                     2 * sk->sk_sndbuf)
>                                         skb = sock_wmalloc(sk,
>                                                            alloclen + hh_len, 1,
> @@ -1565,7 +1565,7 @@ static int __ip6_append_data(struct sock *sk,
>                         skb->len += copy;
>                         skb->data_len += copy;
>                         skb->truesize += copy;
> -                       atomic_add(copy, &sk->sk_wmem_alloc);
> +                       refcount_add(copy, &sk->sk_wmem_alloc);
>                 }
>                 offset += copy;
>                 length -= copy;
> diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
> index ee97c44..9c39746 100644
> --- a/net/ipv6/ipv6_sockglue.c
> +++ b/net/ipv6/ipv6_sockglue.c
> @@ -505,7 +505,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
>                         break;
>
>                 memset(opt, 0, sizeof(*opt));
> -               atomic_set(&opt->refcnt, 1);
> +               refcount_set(&opt->refcnt, 1);
>                 opt->tot_len = sizeof(*opt) + optlen;
>                 retv = -EFAULT;
>                 if (copy_from_user(opt+1, optval, optlen))
> diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
> index 14a3903..4ae7a0b 100644
> --- a/net/ipv6/mcast.c
> +++ b/net/ipv6/mcast.c
> @@ -701,7 +701,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
>
>         spin_lock_bh(&mc->mca_lock);
>         if (del_timer(&mc->mca_timer))
> -               atomic_dec(&mc->mca_refcnt);
> +               refcount_dec(&mc->mca_refcnt);
>  done:
>         ip6_mc_clear_src(mc);
>         spin_unlock_bh(&mc->mca_lock);
> @@ -813,12 +813,12 @@ static void mld_clear_delrec(struct inet6_dev *idev)
>
>  static void mca_get(struct ifmcaddr6 *mc)
>  {
> -       atomic_inc(&mc->mca_refcnt);
> +       refcount_inc(&mc->mca_refcnt);
>  }
>
>  static void ma_put(struct ifmcaddr6 *mc)
>  {
> -       if (atomic_dec_and_test(&mc->mca_refcnt)) {
> +       if (refcount_dec_and_test(&mc->mca_refcnt)) {
>                 in6_dev_put(mc->idev);
>                 kfree(mc);
>         }
> @@ -840,7 +840,7 @@ static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
>         mc->mca_users = 1;
>         /* mca_stamp should be updated upon changes */
>         mc->mca_cstamp = mc->mca_tstamp = jiffies;
> -       atomic_set(&mc->mca_refcnt, 1);
> +       refcount_set(&mc->mca_refcnt, 1);
>         spin_lock_init(&mc->mca_lock);
>
>         /* initial mode is (EX, empty) */
> @@ -1058,7 +1058,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
>                 return;
>
>         if (del_timer(&ma->mca_timer)) {
> -               atomic_dec(&ma->mca_refcnt);
> +               refcount_dec(&ma->mca_refcnt);
>                 delay = ma->mca_timer.expires - jiffies;
>         }
>
> @@ -1067,7 +1067,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
>
>         ma->mca_timer.expires = jiffies + delay;
>         if (!mod_timer(&ma->mca_timer, jiffies + delay))
> -               atomic_inc(&ma->mca_refcnt);
> +               refcount_inc(&ma->mca_refcnt);
>         ma->mca_flags |= MAF_TIMER_RUNNING;
>  }
>
> @@ -1462,7 +1462,7 @@ int igmp6_event_report(struct sk_buff *skb)
>                 if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) {
>                         spin_lock(&ma->mca_lock);
>                         if (del_timer(&ma->mca_timer))
> -                               atomic_dec(&ma->mca_refcnt);
> +                               refcount_dec(&ma->mca_refcnt);
>                         ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING);
>                         spin_unlock(&ma->mca_lock);
>                         break;
> @@ -2385,12 +2385,12 @@ static void igmp6_join_group(struct ifmcaddr6 *ma)
>
>         spin_lock_bh(&ma->mca_lock);
>         if (del_timer(&ma->mca_timer)) {
> -               atomic_dec(&ma->mca_refcnt);
> +               refcount_dec(&ma->mca_refcnt);
>                 delay = ma->mca_timer.expires - jiffies;
>         }
>
>         if (!mod_timer(&ma->mca_timer, jiffies + delay))
> -               atomic_inc(&ma->mca_refcnt);
> +               refcount_inc(&ma->mca_refcnt);
>         ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
>         spin_unlock_bh(&ma->mca_lock);
>  }
> diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
> index a4d4976..8681837 100644
> --- a/net/ipv6/syncookies.c
> +++ b/net/ipv6/syncookies.c
> @@ -188,7 +188,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
>         if (ipv6_opt_accepted(sk, skb, &TCP_SKB_CB(skb)->header.h6) ||
>             np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
>             np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
> -               atomic_inc(&skb->users);
> +               refcount_inc(&skb->users);
>                 ireq->pktopts = skb;
>         }
>
> diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
> index 73bc8fc6..c88b5c9 100644
> --- a/net/ipv6/tcp_ipv6.c
> +++ b/net/ipv6/tcp_ipv6.c
> @@ -704,7 +704,7 @@ static void tcp_v6_init_req(struct request_sock *req,
>              np->rxopt.bits.rxinfo ||
>              np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim ||
>              np->rxopt.bits.rxohlim || np->repflow)) {
> -               atomic_inc(&skb->users);
> +               refcount_inc(&skb->users);
>                 ireq->pktopts = skb;
>         }
>  }
> @@ -1785,7 +1785,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
>                    from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
>                    icsk->icsk_probes_out,
>                    sock_i_ino(sp),
> -                  atomic_read(&sp->sk_refcnt), sp,
> +                  refcount_read(&sp->sk_refcnt), sp,
>                    jiffies_to_clock_t(icsk->icsk_rto),
>                    jiffies_to_clock_t(icsk->icsk_ack.ato),
>                    (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
> @@ -1818,7 +1818,7 @@ static void get_timewait6_sock(struct seq_file *seq,
>                    dest->s6_addr32[2], dest->s6_addr32[3], destp,
>                    tw->tw_substate, 0, 0,
>                    3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
> -                  atomic_read(&tw->tw_refcnt), tw);
> +                  refcount_read(&tw->tw_refcnt), tw);
>  }
>
>  static int tcp6_seq_show(struct seq_file *seq, void *v)
> diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
> index 4d5c4ee..d2f5307 100644
> --- a/net/ipv6/udp.c
> +++ b/net/ipv6/udp.c
> @@ -311,7 +311,7 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
>
>         sk =  __udp6_lib_lookup(net, saddr, sport, daddr, dport,
>                                 dif, &udp_table, NULL);
> -       if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
> +       if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
>                 sk = NULL;
>         return sk;
>  }
> diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
> index b578956..c8594de 100644
> --- a/net/ipv6/xfrm6_input.c
> +++ b/net/ipv6/xfrm6_input.c
> @@ -70,7 +70,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
>         int i = 0;
>
>         /* Allocate new secpath or COW existing one. */
> -       if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
> +       if (!skb->sp || refcount_read(&skb->sp->refcnt) != 1) {
>                 struct sec_path *sp;
>
>                 sp = secpath_dup(skb->sp);
> diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
> index d7b731a..4e438bc 100644
> --- a/net/ipv6/xfrm6_tunnel.c
> +++ b/net/ipv6/xfrm6_tunnel.c
> @@ -59,7 +59,7 @@ struct xfrm6_tunnel_spi {
>         struct hlist_node       list_byspi;
>         xfrm_address_t          addr;
>         u32                     spi;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         struct rcu_head         rcu_head;
>  };
>
> @@ -160,7 +160,7 @@ static u32 __xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr)
>
>         memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr));
>         x6spi->spi = spi;
> -       atomic_set(&x6spi->refcnt, 1);
> +       refcount_set(&x6spi->refcnt, 1);
>
>         hlist_add_head_rcu(&x6spi->list_byspi, &xfrm6_tn->spi_byspi[index]);
>
> @@ -178,7 +178,7 @@ __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr)
>         spin_lock_bh(&xfrm6_tunnel_spi_lock);
>         x6spi = __xfrm6_tunnel_spi_lookup(net, saddr);
>         if (x6spi) {
> -               atomic_inc(&x6spi->refcnt);
> +               refcount_inc(&x6spi->refcnt);
>                 spi = x6spi->spi;
>         } else
>                 spi = __xfrm6_tunnel_alloc_spi(net, saddr);
> @@ -207,7 +207,7 @@ static void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr)
>                                   list_byaddr)
>         {
>                 if (xfrm6_addr_equal(&x6spi->addr, saddr)) {
> -                       if (atomic_dec_and_test(&x6spi->refcnt)) {
> +                       if (refcount_dec_and_test(&x6spi->refcnt)) {
>                                 hlist_del_rcu(&x6spi->list_byaddr);
>                                 hlist_del_rcu(&x6spi->list_byspi);
>                                 call_rcu(&x6spi->rcu_head, x6spi_destroy_rcu);
> diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
> index 8a9219f..0675b4a 100644
> --- a/net/ipx/af_ipx.c
> +++ b/net/ipx/af_ipx.c
> @@ -308,7 +308,7 @@ void ipxitf_down(struct ipx_interface *intrfc)
>
>  static void __ipxitf_put(struct ipx_interface *intrfc)
>  {
> -       if (atomic_dec_and_test(&intrfc->refcnt))
> +       if (refcount_dec_and_test(&intrfc->refcnt))
>                 __ipxitf_down(intrfc);
>  }
>
> @@ -876,7 +876,7 @@ static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __be32 netnum,
>                 intrfc->if_ipx_offset   = ipx_offset;
>                 intrfc->if_sknum        = IPX_MIN_EPHEMERAL_SOCKET;
>                 INIT_HLIST_HEAD(&intrfc->if_sklist);
> -               atomic_set(&intrfc->refcnt, 1);
> +               refcount_set(&intrfc->refcnt, 1);
>                 spin_lock_init(&intrfc->if_sklist_lock);
>         }
>
> @@ -1105,7 +1105,7 @@ static struct ipx_interface *ipxitf_auto_create(struct net_device *dev,
>                 memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
>                         dev->dev_addr, dev->addr_len);
>                 spin_lock_init(&intrfc->if_sklist_lock);
> -               atomic_set(&intrfc->refcnt, 1);
> +               refcount_set(&intrfc->refcnt, 1);
>                 ipxitf_insert(intrfc);
>                 dev_hold(dev);
>         }
> diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
> index c1d247e..7d75e4c 100644
> --- a/net/ipx/ipx_proc.c
> +++ b/net/ipx/ipx_proc.c
> @@ -53,7 +53,7 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v)
>         seq_printf(seq, "%-11s", ipx_device_name(i));
>         seq_printf(seq, "%-9s", ipx_frame_name(i->if_dlink_type));
>  #ifdef IPX_REFCNT_DEBUG
> -       seq_printf(seq, "%6d", atomic_read(&i->refcnt));
> +       seq_printf(seq, "%6d", refcount_read(&i->refcnt));
>  #endif
>         seq_puts(seq, "\n");
>  out:
> diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
> index 3e2a32a..b5d9144 100644
> --- a/net/ipx/ipx_route.c
> +++ b/net/ipx/ipx_route.c
> @@ -59,7 +59,7 @@ int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
>                 if (!rt)
>                         goto out;
>
> -               atomic_set(&rt->refcnt, 1);
> +               refcount_set(&rt->refcnt, 1);
>                 ipxrtr_hold(rt);
>                 write_lock_bh(&ipx_routes_lock);
>                 list_add(&rt->node, &ipx_routes);
> diff --git a/net/kcm/kcmproc.c b/net/kcm/kcmproc.c
> index bf75c92..c343ac6 100644
> --- a/net/kcm/kcmproc.c
> +++ b/net/kcm/kcmproc.c
> @@ -162,7 +162,7 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
>                    psock->sk->sk_receive_queue.qlen,
>                    atomic_read(&psock->sk->sk_rmem_alloc),
>                    psock->sk->sk_write_queue.qlen,
> -                  atomic_read(&psock->sk->sk_wmem_alloc));
> +                  refcount_read(&psock->sk->sk_wmem_alloc));
>
>         if (psock->done)
>                 seq_puts(seq, "Done ");
> diff --git a/net/key/af_key.c b/net/key/af_key.c
> index c6252ed..b7b0d36 100644
> --- a/net/key/af_key.c
> +++ b/net/key/af_key.c
> @@ -104,7 +104,7 @@ static void pfkey_sock_destruct(struct sock *sk)
>         }
>
>         WARN_ON(atomic_read(&sk->sk_rmem_alloc));
> -       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
> +       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
>
>         atomic_dec(&net_pfkey->socks_nr);
>  }
> @@ -194,11 +194,11 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
>
>         sock_hold(sk);
>         if (*skb2 == NULL) {
> -               if (atomic_read(&skb->users) != 1) {
> +               if (refcount_read(&skb->users) != 1) {
>                         *skb2 = skb_clone(skb, allocation);
>                 } else {
>                         *skb2 = skb;
> -                       atomic_inc(&skb->users);
> +                       refcount_inc(&skb->users);
>                 }
>         }
>         if (*skb2 != NULL) {
> @@ -2152,7 +2152,7 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy *
>         }
>
>         hdr->sadb_msg_len = size / sizeof(uint64_t);
> -       hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
> +       hdr->sadb_msg_reserved = refcount_read(&xp->refcnt);
>
>         return 0;
>  }
> @@ -3711,7 +3711,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
>         else
>                 seq_printf(f, "%pK %-6d %-6u %-6u %-6u %-6lu\n",
>                                s,
> -                              atomic_read(&s->sk_refcnt),
> +                              refcount_read(&s->sk_refcnt),
>                                sk_rmem_alloc_get(s),
>                                sk_wmem_alloc_get(s),
>                                from_kuid_munged(seq_user_ns(f), sock_i_uid(s)),
> diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
> index 85948c6..e273741 100644
> --- a/net/l2tp/l2tp_core.c
> +++ b/net/l2tp/l2tp_core.c
> @@ -132,12 +132,12 @@ static inline struct l2tp_net *l2tp_pernet(struct net *net)
>   */
>  static inline void l2tp_tunnel_inc_refcount_1(struct l2tp_tunnel *tunnel)
>  {
> -       atomic_inc(&tunnel->ref_count);
> +       refcount_inc(&tunnel->ref_count);
>  }
>
>  static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel)
>  {
> -       if (atomic_dec_and_test(&tunnel->ref_count))
> +       if (refcount_dec_and_test(&tunnel->ref_count))
>                 l2tp_tunnel_free(tunnel);
>  }
>  #ifdef L2TP_REFCNT_DEBUG
> @@ -145,14 +145,14 @@ static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel)
>  do {                                                                   \
>         pr_debug("l2tp_tunnel_inc_refcount: %s:%d %s: cnt=%d\n",        \
>                  __func__, __LINE__, (_t)->name,                        \
> -                atomic_read(&_t->ref_count));                          \
> +                refcount_read(&_t->ref_count));                        \
>         l2tp_tunnel_inc_refcount_1(_t);                                 \
>  } while (0)
>  #define l2tp_tunnel_dec_refcount(_t)                                   \
>  do {                                                                   \
>         pr_debug("l2tp_tunnel_dec_refcount: %s:%d %s: cnt=%d\n",        \
>                  __func__, __LINE__, (_t)->name,                        \
> -                atomic_read(&_t->ref_count));                          \
> +                refcount_read(&_t->ref_count));                        \
>         l2tp_tunnel_dec_refcount_1(_t);                                 \
>  } while (0)
>  #else
> @@ -1303,7 +1303,7 @@ static void l2tp_udp_encap_destroy(struct sock *sk)
>   */
>  static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
>  {
> -       BUG_ON(atomic_read(&tunnel->ref_count) != 0);
> +       BUG_ON(refcount_read(&tunnel->ref_count) != 0);
>         BUG_ON(tunnel->sock != NULL);
>         l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: free...\n", tunnel->name);
>         kfree_rcu(tunnel, rcu);
> @@ -1654,7 +1654,7 @@ void l2tp_session_free(struct l2tp_session *session)
>  {
>         struct l2tp_tunnel *tunnel = session->tunnel;
>
> -       BUG_ON(atomic_read(&session->ref_count) != 0);
> +       BUG_ON(refcount_read(&session->ref_count) != 0);
>
>         if (tunnel) {
>                 BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
> diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
> index 8f560f7..f170e97 100644
> --- a/net/l2tp/l2tp_core.h
> +++ b/net/l2tp/l2tp_core.h
> @@ -7,6 +7,7 @@
>   * it under the terms of the GNU General Public License version 2 as
>   * published by the Free Software Foundation.
>   */
> +#include <linux/refcount.h>
>
>  #ifndef _L2TP_CORE_H_
>  #define _L2TP_CORE_H_
> @@ -98,7 +99,7 @@ struct l2tp_session {
>         int                     nr_oos_count;   /* For OOS recovery */
>         int                     nr_oos_count_max;
>         struct hlist_node       hlist;          /* Hash list node */
> -       atomic_t                ref_count;
> +       refcount_t              ref_count;
>
>         char                    name[32];       /* for logging */
>         char                    ifname[IFNAMSIZ];
> @@ -177,7 +178,7 @@ struct l2tp_tunnel {
>         struct list_head        list;           /* Keep a list of all tunnels */
>         struct net              *l2tp_net;      /* the net we belong to */
>
> -       atomic_t                ref_count;
> +       refcount_t              ref_count;
>  #ifdef CONFIG_DEBUG_FS
>         void (*show)(struct seq_file *m, void *arg);
>  #endif
> @@ -269,12 +270,12 @@ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
>   */
>  static inline void l2tp_session_inc_refcount_1(struct l2tp_session *session)
>  {
> -       atomic_inc(&session->ref_count);
> +       refcount_inc(&session->ref_count);
>  }
>
>  static inline void l2tp_session_dec_refcount_1(struct l2tp_session *session)
>  {
> -       if (atomic_dec_and_test(&session->ref_count))
> +       if (refcount_dec_and_test(&session->ref_count))
>                 l2tp_session_free(session);
>  }
>
> @@ -283,14 +284,14 @@ static inline void l2tp_session_dec_refcount_1(struct l2tp_session *session)
>  do {                                                                   \
>         pr_debug("l2tp_session_inc_refcount: %s:%d %s: cnt=%d\n",       \
>                  __func__, __LINE__, (_s)->name,                        \
> -                atomic_read(&_s->ref_count));                          \
> +                refcount_read(&_s->ref_count));                        \
>         l2tp_session_inc_refcount_1(_s);                                \
>  } while (0)
>  #define l2tp_session_dec_refcount(_s)                                  \
>  do {                                                                   \
>         pr_debug("l2tp_session_dec_refcount: %s:%d %s: cnt=%d\n",       \
>                  __func__, __LINE__, (_s)->name,                        \
> -                atomic_read(&_s->ref_count));                          \
> +                refcount_read(&_s->ref_count));                        \
>         l2tp_session_dec_refcount_1(_s);                                \
>  } while (0)
>  #else
> diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
> index 2d6760a..812ae61 100644
> --- a/net/l2tp/l2tp_debugfs.c
> +++ b/net/l2tp/l2tp_debugfs.c
> @@ -144,8 +144,8 @@ static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)
>                    tunnel->encap == L2TP_ENCAPTYPE_IP ? "IP" :
>                    "");
>         seq_printf(m, " %d sessions, refcnt %d/%d\n", session_count,
> -                  tunnel->sock ? atomic_read(&tunnel->sock->sk_refcnt) : 0,
> -                  atomic_read(&tunnel->ref_count));
> +                  tunnel->sock ? refcount_read(&tunnel->sock->sk_refcnt) : 0,
> +                  refcount_read(&tunnel->ref_count));
>
>         seq_printf(m, " %08x rx %ld/%ld/%ld rx %ld/%ld/%ld\n",
>                    tunnel->debug,
> @@ -171,7 +171,7 @@ static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
>                    "");
>         if (session->send_seq || session->recv_seq)
>                 seq_printf(m, "   nr %hu, ns %hu\n", session->nr, session->ns);
> -       seq_printf(m, "   refcnt %d\n", atomic_read(&session->ref_count));
> +       seq_printf(m, "   refcnt %d\n", refcount_read(&session->ref_count));
>         seq_printf(m, "   config %d/%d/%c/%c/%s/%s %08x %u\n",
>                    session->mtu, session->mru,
>                    session->recv_seq ? 'R' : '-',
> diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
> index 36cc56f..eb1a85a 100644
> --- a/net/l2tp/l2tp_ppp.c
> +++ b/net/l2tp/l2tp_ppp.c
> @@ -1607,7 +1607,7 @@ static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
>         seq_printf(m, "\nTUNNEL '%s', %c %d\n",
>                    tunnel->name,
>                    (tunnel == tunnel->sock->sk_user_data) ? 'Y' : 'N',
> -                  atomic_read(&tunnel->ref_count) - 1);
> +                  refcount_read(&tunnel->ref_count) - 1);
>         seq_printf(m, " %08x %ld/%ld/%ld %ld/%ld/%ld\n",
>                    tunnel->debug,
>                    atomic_long_read(&tunnel->stats.tx_packets),
> diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
> index b50b64a..e15314e 100644
> --- a/net/lapb/lapb_iface.c
> +++ b/net/lapb/lapb_iface.c
> @@ -54,12 +54,12 @@ static void lapb_free_cb(struct lapb_cb *lapb)
>
>  static __inline__ void lapb_hold(struct lapb_cb *lapb)
>  {
> -       atomic_inc(&lapb->refcnt);
> +       refcount_inc(&lapb->refcnt);
>  }
>
>  static __inline__ void lapb_put(struct lapb_cb *lapb)
>  {
> -       if (atomic_dec_and_test(&lapb->refcnt))
> +       if (refcount_dec_and_test(&lapb->refcnt))
>                 lapb_free_cb(lapb);
>  }
>
> @@ -136,7 +136,7 @@ static struct lapb_cb *lapb_create_cb(void)
>         lapb->mode    = LAPB_DEFAULT_MODE;
>         lapb->window  = LAPB_DEFAULT_WINDOW;
>         lapb->state   = LAPB_STATE_0;
> -       atomic_set(&lapb->refcnt, 1);
> +       refcount_set(&lapb->refcnt, 1);
>  out:
>         return lapb;
>  }
> diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
> index 3e821da..9227bdf 100644
> --- a/net/llc/llc_conn.c
> +++ b/net/llc/llc_conn.c
> @@ -507,7 +507,7 @@ static struct sock *__llc_lookup_established(struct llc_sap *sap,
>         sk_nulls_for_each_rcu(rc, node, laddr_hb) {
>                 if (llc_estab_match(sap, daddr, laddr, rc)) {
>                         /* Extra checks required by SLAB_DESTROY_BY_RCU */
> -                       if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
> +                       if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
>                                 goto again;
>                         if (unlikely(llc_sk(rc)->sap != sap ||
>                                      !llc_estab_match(sap, daddr, laddr, rc))) {
> @@ -566,7 +566,7 @@ static struct sock *__llc_lookup_listener(struct llc_sap *sap,
>         sk_nulls_for_each_rcu(rc, node, laddr_hb) {
>                 if (llc_listener_match(sap, laddr, rc)) {
>                         /* Extra checks required by SLAB_DESTROY_BY_RCU */
> -                       if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
> +                       if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
>                                 goto again;
>                         if (unlikely(llc_sk(rc)->sap != sap ||
>                                      !llc_listener_match(sap, laddr, rc))) {
> @@ -970,9 +970,9 @@ void llc_sk_free(struct sock *sk)
>         skb_queue_purge(&sk->sk_write_queue);
>         skb_queue_purge(&llc->pdu_unack_q);
>  #ifdef LLC_REFCNT_DEBUG
> -       if (atomic_read(&sk->sk_refcnt) != 1) {
> +       if (refcount_read(&sk->sk_refcnt) != 1) {
>                 printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
> -                       sk, __func__, atomic_read(&sk->sk_refcnt));
> +                       sk, __func__, refcount_read(&sk->sk_refcnt));
>                 printk(KERN_DEBUG "%d LLC sockets are still alive\n",
>                         atomic_read(&llc_sock_nr));
>         } else {
> diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
> index 842851c..8904126 100644
> --- a/net/llc/llc_core.c
> +++ b/net/llc/llc_core.c
> @@ -41,7 +41,7 @@ static struct llc_sap *llc_sap_alloc(void)
>                 spin_lock_init(&sap->sk_lock);
>                 for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++)
>                         INIT_HLIST_NULLS_HEAD(&sap->sk_laddr_hash[i], i);
> -               atomic_set(&sap->refcnt, 1);
> +               refcount_set(&sap->refcnt, 1);
>         }
>         return sap;
>  }
> diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
> index d0e1e80..0471114 100644
> --- a/net/llc/llc_sap.c
> +++ b/net/llc/llc_sap.c
> @@ -326,7 +326,7 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap,
>         sk_nulls_for_each_rcu(rc, node, laddr_hb) {
>                 if (llc_dgram_match(sap, laddr, rc)) {
>                         /* Extra checks required by SLAB_DESTROY_BY_RCU */
> -                       if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
> +                       if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
>                                 goto again;
>                         if (unlikely(llc_sk(rc)->sap != sap ||
>                                      !llc_dgram_match(sap, laddr, rc))) {
> diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
> index 1b05d4a..b4af509 100644
> --- a/net/netfilter/ipset/ip_set_hash_gen.h
> +++ b/net/netfilter/ipset/ip_set_hash_gen.h
> @@ -11,6 +11,7 @@
>  #include <linux/rcupdate.h>
>  #include <linux/jhash.h>
>  #include <linux/types.h>
> +#include <linux/refcount.h>
>  #include <linux/netfilter/ipset/ip_set_timeout.h>
>
>  #define __ipset_dereference_protected(p, c)    rcu_dereference_protected(p, c)
> @@ -78,8 +79,8 @@ struct hbucket {
>
>  /* The hash table: the table size stored here in order to make resizing easy */
>  struct htable {
> -       atomic_t ref;           /* References for resizing */
> -       atomic_t uref;          /* References for dumping */
> +       refcount_t ref;         /* References for resizing */
> +       refcount_t uref;                /* References for dumping */
>         u8 htable_bits;         /* size of hash table == 2^htable_bits */
>         struct hbucket __rcu *bucket[0]; /* hashtable buckets */
>  };
> @@ -591,8 +592,8 @@ mtype_resize(struct ip_set *set, bool retried)
>         spin_lock_bh(&set->lock);
>         orig = __ipset_dereference_protected(h->table, 1);
>         /* There can't be another parallel resizing, but dumping is possible */
> -       atomic_set(&orig->ref, 1);
> -       atomic_inc(&orig->uref);
> +       refcount_set(&orig->ref, 1);
> +       refcount_inc(&orig->uref);
>         extsize = 0;
>         pr_debug("attempt to resize set %s from %u to %u, t %p\n",
>                  set->name, orig->htable_bits, htable_bits, orig);
> @@ -668,7 +669,7 @@ mtype_resize(struct ip_set *set, bool retried)
>         pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
>                  orig->htable_bits, orig, t->htable_bits, t);
>         /* If there's nobody else dumping the table, destroy it */
> -       if (atomic_dec_and_test(&orig->uref)) {
> +       if (refcount_dec_and_test(&orig->uref)) {
>                 pr_debug("Table destroy by resize %p\n", orig);
>                 mtype_ahash_destroy(set, orig, false);
>         }
> @@ -680,8 +681,8 @@ mtype_resize(struct ip_set *set, bool retried)
>         return ret;
>
>  cleanup:
> -       atomic_set(&orig->ref, 0);
> -       atomic_dec(&orig->uref);
> +       refcount_set(&orig->ref, 0);
> +       refcount_dec(&orig->uref);
>         spin_unlock_bh(&set->lock);
>         mtype_ahash_destroy(set, t, false);
>         if (ret == -EAGAIN)
> @@ -1092,12 +1093,12 @@ mtype_uref(struct ip_set *set, struct netlink_callback *cb, bool start)
>         if (start) {
>                 rcu_read_lock_bh();
>                 t = rcu_dereference_bh_nfnl(h->table);
> -               atomic_inc(&t->uref);
> +               refcount_inc(&t->uref);
>                 cb->args[IPSET_CB_PRIVATE] = (unsigned long)t;
>                 rcu_read_unlock_bh();
>         } else if (cb->args[IPSET_CB_PRIVATE]) {
>                 t = (struct htable *)cb->args[IPSET_CB_PRIVATE];
> -               if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
> +               if (refcount_dec_and_test(&t->uref) && refcount_read(&t->ref)) {
>                         /* Resizing didn't destroy the hash table */
>                         pr_debug("Table destroy by dump: %p\n", t);
>                         mtype_ahash_destroy(set, t, false);
> diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
> index 096a451..04e78d4 100644
> --- a/net/netfilter/ipvs/ip_vs_conn.c
> +++ b/net/netfilter/ipvs/ip_vs_conn.c
> @@ -181,7 +181,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
>
>         if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
>                 cp->flags |= IP_VS_CONN_F_HASHED;
> -               atomic_inc(&cp->refcnt);
> +               refcount_inc(&cp->refcnt);
>                 hlist_add_head_rcu(&cp->c_list, &ip_vs_conn_tab[hash]);
>                 ret = 1;
>         } else {
> @@ -215,7 +215,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
>         if (cp->flags & IP_VS_CONN_F_HASHED) {
>                 hlist_del_rcu(&cp->c_list);
>                 cp->flags &= ~IP_VS_CONN_F_HASHED;
> -               atomic_dec(&cp->refcnt);
> +               refcount_dec(&cp->refcnt);
>                 ret = 1;
>         } else
>                 ret = 0;
> @@ -242,13 +242,13 @@ static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
>         if (cp->flags & IP_VS_CONN_F_HASHED) {
>                 ret = false;
>                 /* Decrease refcnt and unlink conn only if we are last user */
> -               if (atomic_cmpxchg(&cp->refcnt, 1, 0) == 1) {
> +               if (refcount_dec_if_one(&cp->refcnt)) {
>                         hlist_del_rcu(&cp->c_list);
>                         cp->flags &= ~IP_VS_CONN_F_HASHED;
>                         ret = true;
>                 }
>         } else
> -               ret = atomic_read(&cp->refcnt) ? false : true;
> +               ret = refcount_read(&cp->refcnt) ? false : true;
>
>         spin_unlock(&cp->lock);
>         ct_write_unlock_bh(hash);
> @@ -475,7 +475,7 @@ static void __ip_vs_conn_put_timer(struct ip_vs_conn *cp)
>  void ip_vs_conn_put(struct ip_vs_conn *cp)
>  {
>         if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) &&
> -           (atomic_read(&cp->refcnt) == 1) &&
> +           (refcount_read(&cp->refcnt) == 1) &&
>             !timer_pending(&cp->timer))
>                 /* expire connection immediately */
>                 __ip_vs_conn_put_notimer(cp);
> @@ -617,8 +617,8 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
>                       IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
>                       IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
>                       ip_vs_fwd_tag(cp), cp->state,
> -                     cp->flags, atomic_read(&cp->refcnt),
> -                     atomic_read(&dest->refcnt));
> +                     cp->flags, refcount_read(&cp->refcnt),
> +                     refcount_read(&dest->refcnt));
>
>         /* Update the connection counters */
>         if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
> @@ -714,8 +714,8 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
>                       IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
>                       IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
>                       ip_vs_fwd_tag(cp), cp->state,
> -                     cp->flags, atomic_read(&cp->refcnt),
> -                     atomic_read(&dest->refcnt));
> +                     cp->flags, refcount_read(&cp->refcnt),
> +                     refcount_read(&dest->refcnt));
>
>         /* Update the connection counters */
>         if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
> @@ -863,10 +863,10 @@ static void ip_vs_conn_expire(unsigned long data)
>
>    expire_later:
>         IP_VS_DBG(7, "delayed: conn->refcnt=%d conn->n_control=%d\n",
> -                 atomic_read(&cp->refcnt),
> +                 refcount_read(&cp->refcnt),
>                   atomic_read(&cp->n_control));
>
> -       atomic_inc(&cp->refcnt);
> +       refcount_inc(&cp->refcnt);
>         cp->timeout = 60*HZ;
>
>         if (ipvs->sync_state & IP_VS_STATE_MASTER)
> @@ -941,7 +941,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
>          * it in the table, so that other thread run ip_vs_random_dropentry
>          * but cannot drop this entry.
>          */
> -       atomic_set(&cp->refcnt, 1);
> +       refcount_set(&cp->refcnt, 1);
>
>         cp->control = NULL;
>         atomic_set(&cp->n_control, 0);
> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> index db40050..a3e1b9c 100644
> --- a/net/netfilter/ipvs/ip_vs_core.c
> +++ b/net/netfilter/ipvs/ip_vs_core.c
> @@ -542,7 +542,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
>                       IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
>                       IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
>                       IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
> -                     cp->flags, atomic_read(&cp->refcnt));
> +                     cp->flags, refcount_read(&cp->refcnt));
>
>         ip_vs_conn_stats(cp, svc);
>         return cp;
> @@ -1193,7 +1193,7 @@ struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc,
>                       IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
>                       IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
>                       IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport),
> -                     cp->flags, atomic_read(&cp->refcnt));
> +                     cp->flags, refcount_read(&cp->refcnt));
>         LeaveFunction(12);
>         return cp;
>  }
> diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
> index 55e0169..3e6bb33 100644
> --- a/net/netfilter/ipvs/ip_vs_ctl.c
> +++ b/net/netfilter/ipvs/ip_vs_ctl.c
> @@ -322,7 +322,7 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
>
>         svc->flags |= IP_VS_SVC_F_HASHED;
>         /* increase its refcnt because it is referenced by the svc table */
> -       atomic_inc(&svc->refcnt);
> +       refcount_inc(&svc->refcnt);
>         return 1;
>  }
>
> @@ -348,7 +348,7 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
>         }
>
>         svc->flags &= ~IP_VS_SVC_F_HASHED;
> -       atomic_dec(&svc->refcnt);
> +       refcount_dec(&svc->refcnt);
>         return 1;
>  }
>
> @@ -458,7 +458,7 @@ ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol
>  static inline void
>  __ip_vs_bind_svc(struct ip_vs_dest *dest, struct ip_vs_service *svc)
>  {
> -       atomic_inc(&svc->refcnt);
> +       refcount_inc(&svc->refcnt);
>         rcu_assign_pointer(dest->svc, svc);
>  }
>
> @@ -478,7 +478,7 @@ static void ip_vs_service_rcu_free(struct rcu_head *head)
>
>  static void __ip_vs_svc_put(struct ip_vs_service *svc, bool do_delay)
>  {
> -       if (atomic_dec_and_test(&svc->refcnt)) {
> +       if (refcount_dec_and_test(&svc->refcnt)) {
>                 IP_VS_DBG_BUF(3, "Removing service %u/%s:%u\n",
>                               svc->fwmark,
>                               IP_VS_DBG_ADDR(svc->af, &svc->addr),
> @@ -700,7 +700,7 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, int dest_af,
>                               dest->vfwmark,
>                               IP_VS_DBG_ADDR(dest->af, &dest->addr),
>                               ntohs(dest->port),
> -                             atomic_read(&dest->refcnt));
> +                             refcount_read(&dest->refcnt));
>                 if (dest->af == dest_af &&
>                     ip_vs_addr_equal(dest_af, &dest->addr, daddr) &&
>                     dest->port == dport &&
> @@ -936,7 +936,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
>         atomic_set(&dest->activeconns, 0);
>         atomic_set(&dest->inactconns, 0);
>         atomic_set(&dest->persistconns, 0);
> -       atomic_set(&dest->refcnt, 1);
> +       refcount_set(&dest->refcnt, 1);
>
>         INIT_HLIST_NODE(&dest->d_list);
>         spin_lock_init(&dest->dst_lock);
> @@ -1000,7 +1000,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
>                 IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, "
>                               "dest->refcnt=%d, service %u/%s:%u\n",
>                               IP_VS_DBG_ADDR(udest->af, &daddr), ntohs(dport),
> -                             atomic_read(&dest->refcnt),
> +                             refcount_read(&dest->refcnt),
>                               dest->vfwmark,
>                               IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
>                               ntohs(dest->vport));
> @@ -1076,7 +1076,7 @@ static void __ip_vs_del_dest(struct netns_ipvs *ipvs, struct ip_vs_dest *dest,
>         spin_lock_bh(&ipvs->dest_trash_lock);
>         IP_VS_DBG_BUF(3, "Moving dest %s:%u into trash, dest->refcnt=%d\n",
>                       IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
> -                     atomic_read(&dest->refcnt));
> +                     refcount_read(&dest->refcnt));
>         if (list_empty(&ipvs->dest_trash) && !cleanup)
>                 mod_timer(&ipvs->dest_trash_timer,
>                           jiffies + (IP_VS_DEST_TRASH_PERIOD >> 1));
> @@ -1160,7 +1160,7 @@ static void ip_vs_dest_trash_expire(unsigned long data)
>
>         spin_lock(&ipvs->dest_trash_lock);
>         list_for_each_entry_safe(dest, next, &ipvs->dest_trash, t_list) {
> -               if (atomic_read(&dest->refcnt) > 0)
> +               if (refcount_read(&dest->refcnt) > 0)
>                         continue;
>                 if (dest->idle_start) {
>                         if (time_before(now, dest->idle_start +
> @@ -1250,7 +1250,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
>
>
>         /* I'm the first user of the service */
> -       atomic_set(&svc->refcnt, 0);
> +       refcount_set(&svc->refcnt, 0);
>
>         svc->af = u->af;
>         svc->protocol = u->protocol;
> @@ -1465,7 +1465,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
>  static void ip_vs_unlink_service(struct ip_vs_service *svc, bool cleanup)
>  {
>         /* Hold svc to avoid double release from dest_trash */
> -       atomic_inc(&svc->refcnt);
> +       refcount_inc(&svc->refcnt);
>         /*
>          * Unhash it from the service table
>          */
> @@ -1548,7 +1548,7 @@ ip_vs_forget_dev(struct ip_vs_dest *dest, struct net_device *dev)
>                               dev->name,
>                               IP_VS_DBG_ADDR(dest->af, &dest->addr),
>                               ntohs(dest->port),
> -                             atomic_read(&dest->refcnt));
> +                             refcount_read(&dest->refcnt));
>                 __ip_vs_dst_cache_reset(dest);
>         }
>         spin_unlock_bh(&dest->dst_lock);
> diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
> index 6be5c53..6e31531 100644
> --- a/net/netfilter/ipvs/ip_vs_dh.c
> +++ b/net/netfilter/ipvs/ip_vs_dh.c
> @@ -247,7 +247,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>  static struct ip_vs_scheduler ip_vs_dh_scheduler =
>  {
>         .name =                 "dh",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_dh_scheduler.n_list),
>         .init_service =         ip_vs_dh_init_svc,
> diff --git a/net/netfilter/ipvs/ip_vs_fo.c b/net/netfilter/ipvs/ip_vs_fo.c
> index e09874d..211078e 100644
> --- a/net/netfilter/ipvs/ip_vs_fo.c
> +++ b/net/netfilter/ipvs/ip_vs_fo.c
> @@ -57,7 +57,7 @@ ip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>
>  static struct ip_vs_scheduler ip_vs_fo_scheduler = {
>         .name =                 "fo",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list),
>         .schedule =             ip_vs_fo_schedule,
> diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
> index cccf4d6..71898d8 100644
> --- a/net/netfilter/ipvs/ip_vs_lblc.c
> +++ b/net/netfilter/ipvs/ip_vs_lblc.c
> @@ -448,7 +448,7 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc)
>                       IP_VS_DBG_ADDR(least->af, &least->addr),
>                       ntohs(least->port),
>                       atomic_read(&least->activeconns),
> -                     atomic_read(&least->refcnt),
> +                     refcount_read(&least->refcnt),
>                       atomic_read(&least->weight), loh);
>
>         return least;
> @@ -537,7 +537,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>   */
>  static struct ip_vs_scheduler ip_vs_lblc_scheduler = {
>         .name =                 "lblc",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_lblc_scheduler.n_list),
>         .init_service =         ip_vs_lblc_init_svc,
> diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
> index 796d70e..64fb222 100644
> --- a/net/netfilter/ipvs/ip_vs_lblcr.c
> +++ b/net/netfilter/ipvs/ip_vs_lblcr.c
> @@ -204,7 +204,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
>                       IP_VS_DBG_ADDR(least->af, &least->addr),
>                       ntohs(least->port),
>                       atomic_read(&least->activeconns),
> -                     atomic_read(&least->refcnt),
> +                     refcount_read(&least->refcnt),
>                       atomic_read(&least->weight), loh);
>         return least;
>  }
> @@ -249,7 +249,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
>                       __func__,
>                       IP_VS_DBG_ADDR(most->af, &most->addr), ntohs(most->port),
>                       atomic_read(&most->activeconns),
> -                     atomic_read(&most->refcnt),
> +                     refcount_read(&most->refcnt),
>                       atomic_read(&most->weight), moh);
>         return most;
>  }
> @@ -612,7 +612,7 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc)
>                       IP_VS_DBG_ADDR(least->af, &least->addr),
>                       ntohs(least->port),
>                       atomic_read(&least->activeconns),
> -                     atomic_read(&least->refcnt),
> +                     refcount_read(&least->refcnt),
>                       atomic_read(&least->weight), loh);
>
>         return least;
> @@ -723,7 +723,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>  static struct ip_vs_scheduler ip_vs_lblcr_scheduler =
>  {
>         .name =                 "lblcr",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_lblcr_scheduler.n_list),
>         .init_service =         ip_vs_lblcr_init_svc,
> diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c
> index 19a0769..5fb3bb9 100644
> --- a/net/netfilter/ipvs/ip_vs_lc.c
> +++ b/net/netfilter/ipvs/ip_vs_lc.c
> @@ -70,7 +70,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>
>  static struct ip_vs_scheduler ip_vs_lc_scheduler = {
>         .name =                 "lc",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_lc_scheduler.n_list),
>         .schedule =             ip_vs_lc_schedule,
> diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c
> index a8b6340..9ec9cd0 100644
> --- a/net/netfilter/ipvs/ip_vs_nq.c
> +++ b/net/netfilter/ipvs/ip_vs_nq.c
> @@ -110,7 +110,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>                       IP_VS_DBG_ADDR(least->af, &least->addr),
>                       ntohs(least->port),
>                       atomic_read(&least->activeconns),
> -                     atomic_read(&least->refcnt),
> +                     refcount_read(&least->refcnt),
>                       atomic_read(&least->weight), loh);
>
>         return least;
> @@ -120,7 +120,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>  static struct ip_vs_scheduler ip_vs_nq_scheduler =
>  {
>         .name =                 "nq",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_nq_scheduler.n_list),
>         .schedule =             ip_vs_nq_schedule,
> diff --git a/net/netfilter/ipvs/ip_vs_ovf.c b/net/netfilter/ipvs/ip_vs_ovf.c
> index f7d62c3..fbcd826 100644
> --- a/net/netfilter/ipvs/ip_vs_ovf.c
> +++ b/net/netfilter/ipvs/ip_vs_ovf.c
> @@ -64,7 +64,7 @@ ip_vs_ovf_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>
>  static struct ip_vs_scheduler ip_vs_ovf_scheduler = {
>         .name =                 "ovf",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_ovf_scheduler.n_list),
>         .schedule =             ip_vs_ovf_schedule,
> diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
> index d07ef9e..364156b 100644
> --- a/net/netfilter/ipvs/ip_vs_pe_sip.c
> +++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
> @@ -160,7 +160,7 @@ ip_vs_sip_conn_out(struct ip_vs_service *svc,
>  static struct ip_vs_pe ip_vs_sip_pe =
>  {
>         .name =                 "sip",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_sip_pe.n_list),
>         .fill_param =           ip_vs_sip_fill_param,
> diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
> index d952d67..56f8e4b 100644
> --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
> +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
> @@ -447,7 +447,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
>                                 ntohs(cp->cport),
>                                 sctp_state_name(cp->state),
>                                 sctp_state_name(next_state),
> -                               atomic_read(&cp->refcnt));
> +                               refcount_read(&cp->refcnt));
>                 if (dest) {
>                         if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
>                                 (next_state != IP_VS_SCTP_S_ESTABLISHED)) {
> diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
> index 5117bcb..12dc8d5 100644
> --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
> +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
> @@ -557,7 +557,7 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
>                               ntohs(cp->cport),
>                               tcp_state_name(cp->state),
>                               tcp_state_name(new_state),
> -                             atomic_read(&cp->refcnt));
> +                             refcount_read(&cp->refcnt));
>
>                 if (dest) {
>                         if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
> diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c
> index 58bacfc..7d8f6cb 100644
> --- a/net/netfilter/ipvs/ip_vs_rr.c
> +++ b/net/netfilter/ipvs/ip_vs_rr.c
> @@ -97,7 +97,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>                       "activeconns %d refcnt %d weight %d\n",
>                       IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
>                       atomic_read(&dest->activeconns),
> -                     atomic_read(&dest->refcnt), atomic_read(&dest->weight));
> +                     refcount_read(&dest->refcnt), atomic_read(&dest->weight));
>
>         return dest;
>  }
> @@ -105,7 +105,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>
>  static struct ip_vs_scheduler ip_vs_rr_scheduler = {
>         .name =                 "rr",                   /* name */
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_rr_scheduler.n_list),
>         .init_service =         ip_vs_rr_init_svc,
> diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c
> index f8e2d00..9a1bdc0 100644
> --- a/net/netfilter/ipvs/ip_vs_sed.c
> +++ b/net/netfilter/ipvs/ip_vs_sed.c
> @@ -111,7 +111,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>                       IP_VS_DBG_ADDR(least->af, &least->addr),
>                       ntohs(least->port),
>                       atomic_read(&least->activeconns),
> -                     atomic_read(&least->refcnt),
> +                     refcount_read(&least->refcnt),
>                       atomic_read(&least->weight), loh);
>
>         return least;
> @@ -121,7 +121,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>  static struct ip_vs_scheduler ip_vs_sed_scheduler =
>  {
>         .name =                 "sed",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_sed_scheduler.n_list),
>         .schedule =             ip_vs_sed_schedule,
> diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
> index 1e373a5..b7330cf 100644
> --- a/net/netfilter/ipvs/ip_vs_sh.c
> +++ b/net/netfilter/ipvs/ip_vs_sh.c
> @@ -352,7 +352,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>  static struct ip_vs_scheduler ip_vs_sh_scheduler =
>  {
>         .name =                 "sh",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list  =              LIST_HEAD_INIT(ip_vs_sh_scheduler.n_list),
>         .init_service =         ip_vs_sh_init_svc,
> diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c
> index 6b366fd..3c19dac 100644
> --- a/net/netfilter/ipvs/ip_vs_wlc.c
> +++ b/net/netfilter/ipvs/ip_vs_wlc.c
> @@ -83,7 +83,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>                       IP_VS_DBG_ADDR(least->af, &least->addr),
>                       ntohs(least->port),
>                       atomic_read(&least->activeconns),
> -                     atomic_read(&least->refcnt),
> +                     refcount_read(&least->refcnt),
>                       atomic_read(&least->weight), loh);
>
>         return least;
> @@ -93,7 +93,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>  static struct ip_vs_scheduler ip_vs_wlc_scheduler =
>  {
>         .name =                 "wlc",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_wlc_scheduler.n_list),
>         .schedule =             ip_vs_wlc_schedule,
> diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c
> index 17e6d44..0704af3 100644
> --- a/net/netfilter/ipvs/ip_vs_wrr.c
> +++ b/net/netfilter/ipvs/ip_vs_wrr.c
> @@ -218,7 +218,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>                       "activeconns %d refcnt %d weight %d\n",
>                       IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
>                       atomic_read(&dest->activeconns),
> -                     atomic_read(&dest->refcnt),
> +                     refcount_read(&dest->refcnt),
>                       atomic_read(&dest->weight));
>         mark->cl = dest;
>
> @@ -243,7 +243,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
>
>  static struct ip_vs_scheduler ip_vs_wrr_scheduler = {
>         .name =                 "wrr",
> -       .refcnt =               ATOMIC_INIT(0),
> +       .refcnt =               REFCOUNT_INIT(0),
>         .module =               THIS_MODULE,
>         .n_list =               LIST_HEAD_INIT(ip_vs_wrr_scheduler.n_list),
>         .init_service =         ip_vs_wrr_init_svc,
> diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
> index 3a073cd..04d5c7ec 100644
> --- a/net/netfilter/nf_conntrack_core.c
> +++ b/net/netfilter/nf_conntrack_core.c
> @@ -364,7 +364,7 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
>         tmpl->status = IPS_TEMPLATE;
>         write_pnet(&tmpl->ct_net, net);
>         nf_ct_zone_add(tmpl, zone);
> -       atomic_set(&tmpl->ct_general.use, 0);
> +       refcount_set(&tmpl->ct_general.use, 0);
>
>         return tmpl;
>  }
> @@ -385,7 +385,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
>         struct nf_conntrack_l4proto *l4proto;
>
>         pr_debug("destroy_conntrack(%p)\n", ct);
> -       NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
> +       NF_CT_ASSERT(refcount_read(&nfct->use) == 0);
>
>         if (unlikely(nf_ct_is_template(ct))) {
>                 nf_ct_tmpl_free(ct);
> @@ -490,7 +490,7 @@ nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,
>  /* caller must hold rcu readlock and none of the nf_conntrack_locks */
>  static void nf_ct_gc_expired(struct nf_conn *ct)
>  {
> -       if (!atomic_inc_not_zero(&ct->ct_general.use))
> +       if (!refcount_inc_not_zero(&ct->ct_general.use))
>                 return;
>
>         if (nf_ct_should_gc(ct))
> @@ -559,7 +559,7 @@ __nf_conntrack_find_get(struct net *net, const struct nf_conntrack_zone *zone,
>         if (h) {
>                 ct = nf_ct_tuplehash_to_ctrack(h);
>                 if (unlikely(nf_ct_is_dying(ct) ||
> -                            !atomic_inc_not_zero(&ct->ct_general.use)))
> +                            !refcount_inc_not_zero(&ct->ct_general.use)))
>                         h = NULL;
>                 else {
>                         if (unlikely(!nf_ct_key_equal(h, tuple, zone, net))) {
> @@ -626,7 +626,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
>
>         smp_wmb();
>         /* The caller holds a reference to this object */
> -       atomic_set(&ct->ct_general.use, 2);
> +       refcount_set(&ct->ct_general.use, 2);
>         __nf_conntrack_hash_insert(ct, hash, reply_hash);
>         nf_conntrack_double_unlock(hash, reply_hash);
>         NF_CT_STAT_INC(net, insert);
> @@ -685,7 +685,7 @@ static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
>         if (l4proto->allow_clash &&
>             !nfct_nat(ct) &&
>             !nf_ct_is_dying(ct) &&
> -           atomic_inc_not_zero(&ct->ct_general.use)) {
> +           refcount_inc_not_zero(&ct->ct_general.use)) {
>                 nf_ct_acct_merge(ct, ctinfo, (struct nf_conn *)skb->nfct);
>                 nf_conntrack_put(skb->nfct);
>                 /* Assign conntrack already in hashes to this skbuff. Don't
> @@ -777,7 +777,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
>            setting time, otherwise we'd get timer wrap in
>            weird delay cases. */
>         ct->timeout += nfct_time_stamp;
> -       atomic_inc(&ct->ct_general.use);
> +       refcount_inc(&ct->ct_general.use);
>         ct->status |= IPS_CONFIRMED;
>
>         /* set conntrack timestamp, if enabled. */
> @@ -891,7 +891,7 @@ static unsigned int early_drop_list(struct net *net,
>                     nf_ct_is_dying(tmp))
>                         continue;
>
> -               if (!atomic_inc_not_zero(&tmp->ct_general.use))
> +               if (!refcount_inc_not_zero(&tmp->ct_general.use))
>                         continue;
>
>                 /* kill only if still in same netns -- might have moved due to
> @@ -1075,7 +1075,7 @@ __nf_conntrack_alloc(struct net *net,
>         /* Because we use RCU lookups, we set ct_general.use to zero before
>          * this is inserted in any list.
>          */
> -       atomic_set(&ct->ct_general.use, 0);
> +       refcount_set(&ct->ct_general.use, 0);
>         return ct;
>  out:
>         atomic_dec(&net->ct.count);
> @@ -1099,7 +1099,7 @@ void nf_conntrack_free(struct nf_conn *ct)
>         /* A freed object has refcnt == 0, that's
>          * the golden rule for SLAB_DESTROY_BY_RCU
>          */
> -       NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0);
> +       NF_CT_ASSERT(refcount_read(&ct->ct_general.use) == 0);
>
>         nf_ct_ext_destroy(ct);
>         nf_ct_ext_free(ct);
> @@ -1573,7 +1573,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
>         }
>         return NULL;
>  found:
> -       atomic_inc(&ct->ct_general.use);
> +       refcount_inc(&ct->ct_general.use);
>         spin_unlock(lockp);
>         local_bh_enable();
>         return ct;
> @@ -1623,7 +1623,7 @@ static int untrack_refs(void)
>         for_each_possible_cpu(cpu) {
>                 struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu);
>
> -               cnt += atomic_read(&ct->ct_general.use) - 1;
> +               cnt += refcount_read(&ct->ct_general.use) - 1;
>         }
>         return cnt;
>  }
> @@ -1911,7 +1911,7 @@ int nf_conntrack_init_start(void)
>         for_each_possible_cpu(cpu) {
>                 struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu);
>                 write_pnet(&ct->ct_net, &init_net);
> -               atomic_set(&ct->ct_general.use, 1);
> +               refcount_set(&ct->ct_general.use, 1);
>         }
>         /*  - and look it like as a confirmed connection */
>         nf_ct_untracked_status_or(IPS_CONFIRMED | IPS_UNTRACKED);
> diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
> index f8dbacf..5b2448f 100644
> --- a/net/netfilter/nf_conntrack_expect.c
> +++ b/net/netfilter/nf_conntrack_expect.c
> @@ -133,7 +133,7 @@ nf_ct_expect_find_get(struct net *net,
>
>         rcu_read_lock();
>         i = __nf_ct_expect_find(net, zone, tuple);
> -       if (i && !atomic_inc_not_zero(&i->use))
> +       if (i && !refcount_inc_not_zero(&i->use))
>                 i = NULL;
>         rcu_read_unlock();
>
> @@ -182,11 +182,11 @@ nf_ct_find_expectation(struct net *net,
>          * can be sure the ct cannot disappear underneath.
>          */
>         if (unlikely(nf_ct_is_dying(exp->master) ||
> -                    !atomic_inc_not_zero(&exp->master->ct_general.use)))
> +                    !refcount_inc_not_zero(&exp->master->ct_general.use)))
>                 return NULL;
>
>         if (exp->flags & NF_CT_EXPECT_PERMANENT) {
> -               atomic_inc(&exp->use);
> +               refcount_inc(&exp->use);
>                 return exp;
>         } else if (del_timer(&exp->timeout)) {
>                 nf_ct_unlink_expect(exp);
> @@ -275,7 +275,7 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
>                 return NULL;
>
>         new->master = me;
> -       atomic_set(&new->use, 1);
> +       refcount_set(&new->use, 1);
>         return new;
>  }
>  EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
> @@ -348,7 +348,7 @@ static void nf_ct_expect_free_rcu(struct rcu_head *head)
>
>  void nf_ct_expect_put(struct nf_conntrack_expect *exp)
>  {
> -       if (atomic_dec_and_test(&exp->use))
> +       if (refcount_dec_and_test(&exp->use))
>                 call_rcu(&exp->rcu, nf_ct_expect_free_rcu);
>  }
>  EXPORT_SYMBOL_GPL(nf_ct_expect_put);
> @@ -361,7 +361,7 @@ static int nf_ct_expect_insert(struct nf_conntrack_expect *exp)
>         unsigned int h = nf_ct_expect_dst_hash(net, &exp->tuple);
>
>         /* two references : one for hash insert, one for the timer */
> -       atomic_add(2, &exp->use);
> +       refcount_add(2, &exp->use);
>
>         hlist_add_head(&exp->lnode, &master_help->expectations);
>         master_help->expecting[exp->class]++;
> diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
> index 2754045..7a7012a 100644
> --- a/net/netfilter/nf_conntrack_netlink.c
> +++ b/net/netfilter/nf_conntrack_netlink.c
> @@ -449,7 +449,7 @@ static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
>
>  static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
>  {
> -       if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use))))
> +       if (nla_put_be32(skb, CTA_USE, htonl(refcount_read(&ct->ct_general.use))))
>                 goto nla_put_failure;
>         return 0;
>
> @@ -845,7 +845,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
>                         ct = nf_ct_tuplehash_to_ctrack(h);
>                         if (nf_ct_is_expired(ct)) {
>                                 if (i < ARRAY_SIZE(nf_ct_evict) &&
> -                                   atomic_inc_not_zero(&ct->ct_general.use))
> +                                   refcount_inc_not_zero(&ct->ct_general.use))
>                                         nf_ct_evict[i++] = ct;
>                                 continue;
>                         }
> @@ -1306,7 +1306,7 @@ ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying
>                                                   ct);
>                         rcu_read_unlock();
>                         if (res < 0) {
> -                               if (!atomic_inc_not_zero(&ct->ct_general.use))
> +                               if (!refcount_inc_not_zero(&ct->ct_general.use))
>                                         continue;
>                                 cb->args[0] = cpu;
>                                 cb->args[1] = (unsigned long)ct;
> @@ -2660,7 +2660,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
>                                                     cb->nlh->nlmsg_seq,
>                                                     IPCTNL_MSG_EXP_NEW,
>                                                     exp) < 0) {
> -                               if (!atomic_inc_not_zero(&exp->use))
> +                               if (!refcount_inc_not_zero(&exp->use))
>                                         continue;
>                                 cb->args[1] = (unsigned long)exp;
>                                 goto out;
> @@ -2706,7 +2706,7 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
>                                             cb->nlh->nlmsg_seq,
>                                             IPCTNL_MSG_EXP_NEW,
>                                             exp) < 0) {
> -                       if (!atomic_inc_not_zero(&exp->use))
> +                       if (!refcount_inc_not_zero(&exp->use))
>                                 continue;
>                         cb->args[1] = (unsigned long)exp;
>                         goto out;
> diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
> index d009ae6..c0a278f 100644
> --- a/net/netfilter/nf_conntrack_standalone.c
> +++ b/net/netfilter/nf_conntrack_standalone.c
> @@ -209,7 +209,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
>         int ret = 0;
>
>         NF_CT_ASSERT(ct);
> -       if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
> +       if (unlikely(!refcount_inc_not_zero(&ct->ct_general.use)))
>                 return 0;
>
>         if (nf_ct_should_gc(ct)) {
> @@ -274,7 +274,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
>         ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR);
>         ct_show_delta_time(s, ct);
>
> -       seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use));
> +       seq_printf(s, "use=%u\n", refcount_read(&ct->ct_general.use));
>
>         if (seq_has_overflowed(s))
>                 goto release;
> diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
> index d44d89b..f44cbd3 100644
> --- a/net/netfilter/nfnetlink_acct.c
> +++ b/net/netfilter/nfnetlink_acct.c
> @@ -11,6 +11,7 @@
>  #include <linux/kernel.h>
>  #include <linux/skbuff.h>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/netlink.h>
>  #include <linux/rculist.h>
>  #include <linux/slab.h>
> @@ -32,7 +33,7 @@ struct nf_acct {
>         atomic64_t              bytes;
>         unsigned long           flags;
>         struct list_head        head;
> -       atomic_t                refcnt;
> +       refcount_t              refcnt;
>         char                    name[NFACCT_NAME_MAX];
>         struct rcu_head         rcu_head;
>         char                    data[0];
> @@ -123,7 +124,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
>                 atomic64_set(&nfacct->pkts,
>                              be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS])));
>         }
> -       atomic_set(&nfacct->refcnt, 1);
> +       refcount_set(&nfacct->refcnt, 1);
>         list_add_tail_rcu(&nfacct->head, &net->nfnl_acct_list);
>         return 0;
>  }
> @@ -166,7 +167,7 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
>                          NFACCT_PAD) ||
>             nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes),
>                          NFACCT_PAD) ||
> -           nla_put_be32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt))))
> +           nla_put_be32(skb, NFACCT_USE, htonl(refcount_read(&acct->refcnt))))
>                 goto nla_put_failure;
>         if (acct->flags & NFACCT_F_QUOTA) {
>                 u64 *quota = (u64 *)acct->data;
> @@ -325,11 +326,12 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
>  static int nfnl_acct_try_del(struct nf_acct *cur)
>  {
>         int ret = 0;
> +       unsigned int refcount;
>
>         /* We want to avoid races with nfnl_acct_put. So only when the current
>          * refcnt is 1, we decrease it to 0.
>          */
> -       if (atomic_cmpxchg(&cur->refcnt, 1, 0) == 1) {
> +       if (refcount_dec_if_one(&cur->refcnt)) {
>                 /* We are protected by nfnl mutex. */
>                 list_del_rcu(&cur->head);
>                 kfree_rcu(cur, rcu_head);
> @@ -413,7 +415,7 @@ struct nf_acct *nfnl_acct_find_get(struct net *net, const char *acct_name)
>                 if (!try_module_get(THIS_MODULE))
>                         goto err;
>
> -               if (!atomic_inc_not_zero(&cur->refcnt)) {
> +               if (!refcount_inc_not_zero(&cur->refcnt)) {
>                         module_put(THIS_MODULE);
>                         goto err;
>                 }
> @@ -429,7 +431,7 @@ EXPORT_SYMBOL_GPL(nfnl_acct_find_get);
>
>  void nfnl_acct_put(struct nf_acct *acct)
>  {
> -       if (atomic_dec_and_test(&acct->refcnt))
> +       if (refcount_dec_and_test(&acct->refcnt))
>                 kfree_rcu(acct, rcu_head);
>
>         module_put(THIS_MODULE);
> @@ -502,7 +504,7 @@ static void __net_exit nfnl_acct_net_exit(struct net *net)
>         list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head) {
>                 list_del_rcu(&cur->head);
>
> -               if (atomic_dec_and_test(&cur->refcnt))
> +               if (refcount_dec_and_test(&cur->refcnt))
>                         kfree_rcu(cur, rcu_head);
>         }
>  }
> diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
> index 139e086..baa75f3 100644
> --- a/net/netfilter/nfnetlink_cttimeout.c
> +++ b/net/netfilter/nfnetlink_cttimeout.c
> @@ -138,7 +138,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
>         strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
>         timeout->l3num = l3num;
>         timeout->l4proto = l4proto;
> -       atomic_set(&timeout->refcnt, 1);
> +       refcount_set(&timeout->refcnt, 1);
>         list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
>
>         return 0;
> @@ -172,7 +172,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
>             nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) ||
>             nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
>             nla_put_be32(skb, CTA_TIMEOUT_USE,
> -                        htonl(atomic_read(&timeout->refcnt))))
> +                        htonl(refcount_read(&timeout->refcnt))))
>                 goto nla_put_failure;
>
>         if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
> @@ -339,7 +339,7 @@ static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
>         /* We want to avoid races with ctnl_timeout_put. So only when the
>          * current refcnt is 1, we decrease it to 0.
>          */
> -       if (atomic_cmpxchg(&timeout->refcnt, 1, 0) == 1) {
> +       if (refcount_dec_if_one(&timeout->refcnt)) {
>                 /* We are protected by nfnl mutex. */
>                 list_del_rcu(&timeout->head);
>                 nf_ct_l4proto_put(timeout->l4proto);
> @@ -536,7 +536,7 @@ ctnl_timeout_find_get(struct net *net, const char *name)
>                 if (!try_module_get(THIS_MODULE))
>                         goto err;
>
> -               if (!atomic_inc_not_zero(&timeout->refcnt)) {
> +               if (!refcount_inc_not_zero(&timeout->refcnt)) {
>                         module_put(THIS_MODULE);
>                         goto err;
>                 }
> @@ -550,7 +550,7 @@ ctnl_timeout_find_get(struct net *net, const char *name)
>
>  static void ctnl_timeout_put(struct ctnl_timeout *timeout)
>  {
> -       if (atomic_dec_and_test(&timeout->refcnt))
> +       if (refcount_dec_and_test(&timeout->refcnt))
>                 kfree_rcu(timeout, rcu_head);
>
>         module_put(THIS_MODULE);
> @@ -601,7 +601,7 @@ static void __net_exit cttimeout_net_exit(struct net *net)
>                 list_del_rcu(&cur->head);
>                 nf_ct_l4proto_put(cur->l4proto);
>
> -               if (atomic_dec_and_test(&cur->refcnt))
> +               if (refcount_dec_and_test(&cur->refcnt))
>                         kfree_rcu(cur, rcu_head);
>         }
>  }
> diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
> index 08247bf..ecd857b 100644
> --- a/net/netfilter/nfnetlink_log.c
> +++ b/net/netfilter/nfnetlink_log.c
> @@ -40,6 +40,8 @@
>  #include <net/netfilter/nfnetlink_log.h>
>
>  #include <linux/atomic.h>
> +#include <linux/refcount.h>
> +
>
>  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
>  #include "../bridge/br_private.h"
> @@ -57,7 +59,7 @@
>  struct nfulnl_instance {
>         struct hlist_node hlist;        /* global list of instances */
>         spinlock_t lock;
> -       atomic_t use;                   /* use count */
> +       refcount_t use;                 /* use count */
>
>         unsigned int qlen;              /* number of nlmsgs in skb */
>         struct sk_buff *skb;            /* pre-allocatd skb */
> @@ -115,7 +117,7 @@ __instance_lookup(struct nfnl_log_net *log, u_int16_t group_num)
>  static inline void
>  instance_get(struct nfulnl_instance *inst)
>  {
> -       atomic_inc(&inst->use);
> +       refcount_inc(&inst->use);
>  }
>
>  static struct nfulnl_instance *
> @@ -125,7 +127,7 @@ instance_lookup_get(struct nfnl_log_net *log, u_int16_t group_num)
>
>         rcu_read_lock_bh();
>         inst = __instance_lookup(log, group_num);
> -       if (inst && !atomic_inc_not_zero(&inst->use))
> +       if (inst && !refcount_inc_not_zero(&inst->use))
>                 inst = NULL;
>         rcu_read_unlock_bh();
>
> @@ -145,7 +147,7 @@ static void nfulnl_instance_free_rcu(struct rcu_head *head)
>  static void
>  instance_put(struct nfulnl_instance *inst)
>  {
> -       if (inst && atomic_dec_and_test(&inst->use))
> +       if (inst && refcount_dec_and_test(&inst->use))
>                 call_rcu_bh(&inst->rcu, nfulnl_instance_free_rcu);
>  }
>
> @@ -180,7 +182,7 @@ instance_create(struct net *net, u_int16_t group_num,
>         INIT_HLIST_NODE(&inst->hlist);
>         spin_lock_init(&inst->lock);
>         /* needs to be two, since we _put() after creation */
> -       atomic_set(&inst->use, 2);
> +       refcount_set(&inst->use, 2);
>
>         setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst);
>
> @@ -1031,7 +1033,7 @@ static int seq_show(struct seq_file *s, void *v)
>                    inst->group_num,
>                    inst->peer_portid, inst->qlen,
>                    inst->copy_mode, inst->copy_range,
> -                  inst->flushtimeout, atomic_read(&inst->use));
> +                  inst->flushtimeout, refcount_read(&inst->use));
>
>         return 0;
>  }
> diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
> index e6baeae..07ab24d 100644
> --- a/net/netfilter/nft_ct.c
> +++ b/net/netfilter/nft_ct.c
> @@ -533,7 +533,7 @@ static void nft_notrack_eval(const struct nft_expr *expr,
>                 return;
>
>         ct = nf_ct_untracked_get();
> -       atomic_inc(&ct->ct_general.use);
> +       refcount_inc(&ct->ct_general.use);
>         skb->nfct = &ct->ct_general;
>         skb->nfctinfo = IP_CT_NEW;
>  }
> diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
> index 95c7503..cc4a08f 100644
> --- a/net/netfilter/xt_CT.c
> +++ b/net/netfilter/xt_CT.c
> @@ -29,7 +29,7 @@ static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
>         /* special case the untracked ct : we want the percpu object */
>         if (!ct)
>                 ct = nf_ct_untracked_get();
> -       atomic_inc(&ct->ct_general.use);
> +       refcount_inc(&ct->ct_general.use);
>         skb->nfct = &ct->ct_general;
>         skb->nfctinfo = IP_CT_NEW;
>
> diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
> index 80cb7ba..d51f1e8 100644
> --- a/net/netfilter/xt_TPROXY.c
> +++ b/net/netfilter/xt_TPROXY.c
> @@ -127,7 +127,7 @@ nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp,
>                                                     daddr, dport,
>                                                     in->ifindex);
>
> -                       if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
> +                       if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
>                                 sk = NULL;
>                         /* NOTE: we return listeners even if bound to
>                          * 0.0.0.0, those are filtered out in
> @@ -197,7 +197,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
>                                                    daddr, ntohs(dport),
>                                                    in->ifindex);
>
> -                       if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
> +                       if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
>                                 sk = NULL;
>                         /* NOTE: we return listeners even if bound to
>                          * 0.0.0.0, those are filtered out in
> diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
> index 161b628..ed7c2fa 100644
> --- a/net/netlink/af_netlink.c
> +++ b/net/netlink/af_netlink.c
> @@ -341,7 +341,7 @@ static void netlink_sock_destruct(struct sock *sk)
>         }
>
>         WARN_ON(atomic_read(&sk->sk_rmem_alloc));
> -       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
> +       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
>         WARN_ON(nlk_sk(sk)->groups);
>  }
>
> @@ -544,7 +544,7 @@ static void netlink_remove(struct sock *sk)
>         table = &nl_table[sk->sk_protocol];
>         if (!rhashtable_remove_fast(&table->hash, &nlk_sk(sk)->node,
>                                     netlink_rhashtable_params)) {
> -               WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
> +               WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
>                 __sock_put(sk);
>         }
>
> @@ -657,7 +657,7 @@ static void deferred_put_nlk_sk(struct rcu_head *head)
>         struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu);
>         struct sock *sk = &nlk->sk;
>
> -       if (!atomic_dec_and_test(&sk->sk_refcnt))
> +       if (!refcount_dec_and_test(&sk->sk_refcnt))
>                 return;
>
>         if (nlk->cb_running && nlk->cb.done) {
> @@ -1797,7 +1797,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
>         }
>
>         if (dst_group) {
> -               atomic_inc(&skb->users);
> +               refcount_inc(&skb->users);
>                 netlink_broadcast(sk, skb, dst_portid, dst_group, GFP_KERNEL);
>         }
>         err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
> @@ -2175,7 +2175,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
>         struct netlink_sock *nlk;
>         int ret;
>
> -       atomic_inc(&skb->users);
> +       refcount_inc(&skb->users);
>
>         sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid);
>         if (sk == NULL) {
> @@ -2332,7 +2332,7 @@ int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
>                 int exclude_portid = 0;
>
>                 if (report) {
> -                       atomic_inc(&skb->users);
> +                       refcount_inc(&skb->users);
>                         exclude_portid = portid;
>                 }
>
> @@ -2469,7 +2469,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
>                            sk_rmem_alloc_get(s),
>                            sk_wmem_alloc_get(s),
>                            nlk->cb_running,
> -                          atomic_read(&s->sk_refcnt),
> +                          refcount_read(&s->sk_refcnt),
>                            atomic_read(&s->sk_drops),
>                            sock_i_ino(s)
>                         );
> diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
> index d72a4f1..0c59354 100644
> --- a/net/netrom/nr_route.c
> +++ b/net/netrom/nr_route.c
> @@ -149,7 +149,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
>                 nr_neigh->count    = 0;
>                 nr_neigh->number   = nr_neigh_no++;
>                 nr_neigh->failed   = 0;
> -               atomic_set(&nr_neigh->refcount, 1);
> +               refcount_set(&nr_neigh->refcount, 1);
>
>                 if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
>                         nr_neigh->digipeat = kmemdup(ax25_digi,
> @@ -184,7 +184,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
>
>                 nr_node->which = 0;
>                 nr_node->count = 1;
> -               atomic_set(&nr_node->refcount, 1);
> +               refcount_set(&nr_node->refcount, 1);
>                 spin_lock_init(&nr_node->node_lock);
>
>                 nr_node->routes[0].quality   = quality;
> @@ -431,7 +431,7 @@ static int __must_check nr_add_neigh(ax25_address *callsign,
>         nr_neigh->count    = 0;
>         nr_neigh->number   = nr_neigh_no++;
>         nr_neigh->failed   = 0;
> -       atomic_set(&nr_neigh->refcount, 1);
> +       refcount_set(&nr_neigh->refcount, 1);
>
>         if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
>                 nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> index b9e1a13..e543e59 100644
> --- a/net/packet/af_packet.c
> +++ b/net/packet/af_packet.c
> @@ -1312,7 +1312,7 @@ static void packet_sock_destruct(struct sock *sk)
>         skb_queue_purge(&sk->sk_error_queue);
>
>         WARN_ON(atomic_read(&sk->sk_rmem_alloc));
> -       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
> +       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
>
>         if (!sock_flag(sk, SOCK_DEAD)) {
>                 pr_err("Attempt to release alive packet socket: %p\n", sk);
> @@ -1680,7 +1680,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
>                 match->flags = flags;
>                 INIT_LIST_HEAD(&match->list);
>                 spin_lock_init(&match->lock);
> -               atomic_set(&match->sk_ref, 0);
> +               refcount_set(&match->sk_ref, 0);
>                 fanout_init_data(match);
>                 match->prot_hook.type = po->prot_hook.type;
>                 match->prot_hook.dev = po->prot_hook.dev;
> @@ -1695,10 +1695,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
>             match->prot_hook.type == po->prot_hook.type &&
>             match->prot_hook.dev == po->prot_hook.dev) {
>                 err = -ENOSPC;
> -               if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
> +               if (refcount_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
>                         __dev_remove_pack(&po->prot_hook);
>                         po->fanout = match;
> -                       atomic_inc(&match->sk_ref);
> +                       refcount_inc(&match->sk_ref);
>                         __fanout_link(sk, po);
>                         err = 0;
>                 }
> @@ -1724,7 +1724,7 @@ static void fanout_release(struct sock *sk)
>         mutex_lock(&fanout_mutex);
>         po->fanout = NULL;
>
> -       if (atomic_dec_and_test(&f->sk_ref)) {
> +       if (refcount_dec_and_test(&f->sk_ref)) {
>                 list_del(&f->list);
>                 dev_remove_pack(&f->prot_hook);
>                 fanout_release_data(f);
> @@ -2461,7 +2461,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
>         skb->data_len = to_write;
>         skb->len += to_write;
>         skb->truesize += to_write;
> -       atomic_add(to_write, &po->sk.sk_wmem_alloc);
> +       refcount_add(to_write, &po->sk.sk_wmem_alloc);
>
>         while (likely(to_write)) {
>                 nr_frags = skb_shinfo(skb)->nr_frags;
> @@ -4401,7 +4401,7 @@ static int packet_seq_show(struct seq_file *seq, void *v)
>                 seq_printf(seq,
>                            "%pK %-6d %-4d %04x   %-5d %1d %-6u %-6u %-6lu\n",
>                            s,
> -                          atomic_read(&s->sk_refcnt),
> +                          refcount_read(&s->sk_refcnt),
>                            s->sk_type,
>                            ntohs(po->num),
>                            po->ifindex,
> diff --git a/net/packet/internal.h b/net/packet/internal.h
> index 9ee4631..94d1d40 100644
> --- a/net/packet/internal.h
> +++ b/net/packet/internal.h
> @@ -1,6 +1,8 @@
>  #ifndef __PACKET_INTERNAL_H__
>  #define __PACKET_INTERNAL_H__
>
> +#include <linux/refcount.h>
> +
>  struct packet_mclist {
>         struct packet_mclist    *next;
>         int                     ifindex;
> @@ -86,7 +88,7 @@ struct packet_fanout {
>         struct list_head        list;
>         struct sock             *arr[PACKET_FANOUT_MAX];
>         spinlock_t              lock;
> -       atomic_t                sk_ref;
> +       refcount_t              sk_ref;
>         struct packet_type      prot_hook ____cacheline_aligned_in_smp;
>  };
>
> diff --git a/net/phonet/socket.c b/net/phonet/socket.c
> index ffd5f22..bf95d74 100644
> --- a/net/phonet/socket.c
> +++ b/net/phonet/socket.c
> @@ -358,7 +358,7 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
>                 return POLLHUP;
>
>         if (sk->sk_state == TCP_ESTABLISHED &&
> -               atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf &&
> +               refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf &&
>                 atomic_read(&pn->tx_credits))
>                 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
>
> @@ -612,7 +612,7 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v)
>                         sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
>                         from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
>                         sock_i_ino(sk),
> -                       atomic_read(&sk->sk_refcnt), sk,
> +                       refcount_read(&sk->sk_refcnt), sk,
>                         atomic_read(&sk->sk_drops));
>         }
>         seq_pad(seq, '\n');
> diff --git a/net/rds/ib.c b/net/rds/ib.c
> index 5680d90..fd8ec93 100644
> --- a/net/rds/ib.c
> +++ b/net/rds/ib.c
> @@ -116,8 +116,8 @@ static void rds_ib_dev_free(struct work_struct *work)
>
>  void rds_ib_dev_put(struct rds_ib_device *rds_ibdev)
>  {
> -       BUG_ON(atomic_read(&rds_ibdev->refcount) <= 0);
> -       if (atomic_dec_and_test(&rds_ibdev->refcount))
> +       BUG_ON(refcount_read(&rds_ibdev->refcount) == 0);
> +       if (refcount_dec_and_test(&rds_ibdev->refcount))
>                 queue_work(rds_wq, &rds_ibdev->free_work);
>  }
>
> @@ -135,7 +135,7 @@ static void rds_ib_add_one(struct ib_device *device)
>                 return;
>
>         spin_lock_init(&rds_ibdev->spinlock);
> -       atomic_set(&rds_ibdev->refcount, 1);
> +       refcount_set(&rds_ibdev->refcount, 1);
>         INIT_WORK(&rds_ibdev->free_work, rds_ib_dev_free);
>
>         rds_ibdev->max_wrs = device->attrs.max_qp_wr;
> @@ -195,10 +195,10 @@ static void rds_ib_add_one(struct ib_device *device)
>         down_write(&rds_ib_devices_lock);
>         list_add_tail_rcu(&rds_ibdev->list, &rds_ib_devices);
>         up_write(&rds_ib_devices_lock);
> -       atomic_inc(&rds_ibdev->refcount);
> +       refcount_inc(&rds_ibdev->refcount);
>
>         ib_set_client_data(device, &rds_ib_client, rds_ibdev);
> -       atomic_inc(&rds_ibdev->refcount);
> +       refcount_inc(&rds_ibdev->refcount);
>
>         rds_ib_nodev_connect();
>
> @@ -229,7 +229,7 @@ struct rds_ib_device *rds_ib_get_client_data(struct ib_device *device)
>         rcu_read_lock();
>         rds_ibdev = ib_get_client_data(device, &rds_ib_client);
>         if (rds_ibdev)
> -               atomic_inc(&rds_ibdev->refcount);
> +               refcount_inc(&rds_ibdev->refcount);
>         rcu_read_unlock();
>         return rds_ibdev;
>  }
> diff --git a/net/rds/ib.h b/net/rds/ib.h
> index 45ac8e8..ddc97d7 100644
> --- a/net/rds/ib.h
> +++ b/net/rds/ib.h
> @@ -219,7 +219,7 @@ struct rds_ib_device {
>         unsigned int            max_initiator_depth;
>         unsigned int            max_responder_resources;
>         spinlock_t              spinlock;       /* protect the above */
> -       atomic_t                refcount;
> +       refcount_t              refcount;
>         struct work_struct      free_work;
>  };
>
> diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
> index 977f698..9a3c54e 100644
> --- a/net/rds/ib_rdma.c
> +++ b/net/rds/ib_rdma.c
> @@ -52,7 +52,7 @@ static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
>         list_for_each_entry_rcu(rds_ibdev, &rds_ib_devices, list) {
>                 list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
>                         if (i_ipaddr->ipaddr == ipaddr) {
> -                               atomic_inc(&rds_ibdev->refcount);
> +                               refcount_inc(&rds_ibdev->refcount);
>                                 rcu_read_unlock();
>                                 return rds_ibdev;
>                         }
> @@ -134,7 +134,7 @@ void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *con
>         spin_unlock_irq(&ib_nodev_conns_lock);
>
>         ic->rds_ibdev = rds_ibdev;
> -       atomic_inc(&rds_ibdev->refcount);
> +       refcount_inc(&rds_ibdev->refcount);
>  }
>
>  void rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn)
> diff --git a/net/rds/message.c b/net/rds/message.c
> index 49bfb51..4318cc9 100644
> --- a/net/rds/message.c
> +++ b/net/rds/message.c
> @@ -48,8 +48,8 @@ static unsigned int   rds_exthdr_size[__RDS_EXTHDR_MAX] = {
>
>  void rds_message_addref(struct rds_message *rm)
>  {
> -       rdsdebug("addref rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
> -       atomic_inc(&rm->m_refcount);
> +       rdsdebug("addref rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
> +       refcount_inc(&rm->m_refcount);
>  }
>  EXPORT_SYMBOL_GPL(rds_message_addref);
>
> @@ -83,9 +83,9 @@ static void rds_message_purge(struct rds_message *rm)
>
>  void rds_message_put(struct rds_message *rm)
>  {
> -       rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
> -       WARN(!atomic_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
> -       if (atomic_dec_and_test(&rm->m_refcount)) {
> +       rdsdebug("put rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
> +       WARN(!refcount_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
> +       if (refcount_dec_and_test(&rm->m_refcount)) {
>                 BUG_ON(!list_empty(&rm->m_sock_item));
>                 BUG_ON(!list_empty(&rm->m_conn_item));
>                 rds_message_purge(rm);
> @@ -206,7 +206,7 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)
>         rm->m_used_sgs = 0;
>         rm->m_total_sgs = extra_len / sizeof(struct scatterlist);
>
> -       atomic_set(&rm->m_refcount, 1);
> +       refcount_set(&rm->m_refcount, 1);
>         INIT_LIST_HEAD(&rm->m_sock_item);
>         INIT_LIST_HEAD(&rm->m_conn_item);
>         spin_lock_init(&rm->m_rs_lock);
> diff --git a/net/rds/rdma.c b/net/rds/rdma.c
> index ea96114..1325c20 100644
> --- a/net/rds/rdma.c
> +++ b/net/rds/rdma.c
> @@ -85,7 +85,7 @@ static struct rds_mr *rds_mr_tree_walk(struct rb_root *root, u64 key,
>         if (insert) {
>                 rb_link_node(&insert->r_rb_node, parent, p);
>                 rb_insert_color(&insert->r_rb_node, root);
> -               atomic_inc(&insert->r_refcount);
> +               refcount_inc(&insert->r_refcount);
>         }
>         return NULL;
>  }
> @@ -100,7 +100,7 @@ static void rds_destroy_mr(struct rds_mr *mr)
>         unsigned long flags;
>
>         rdsdebug("RDS: destroy mr key is %x refcnt %u\n",
> -                       mr->r_key, atomic_read(&mr->r_refcount));
> +                       mr->r_key, refcount_read(&mr->r_refcount));
>
>         if (test_and_set_bit(RDS_MR_DEAD, &mr->r_state))
>                 return;
> @@ -216,7 +216,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
>                 goto out;
>         }
>
> -       atomic_set(&mr->r_refcount, 1);
> +       refcount_set(&mr->r_refcount, 1);
>         RB_CLEAR_NODE(&mr->r_rb_node);
>         mr->r_trans = rs->rs_transport;
>         mr->r_sock = rs;
> @@ -300,7 +300,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
>
>         rdsdebug("RDS: get_mr key is %x\n", mr->r_key);
>         if (mr_ret) {
> -               atomic_inc(&mr->r_refcount);
> +               refcount_inc(&mr->r_refcount);
>                 *mr_ret = mr;
>         }
>
> @@ -738,7 +738,7 @@ int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
>         if (!mr)
>                 err = -EINVAL;  /* invalid r_key */
>         else
> -               atomic_inc(&mr->r_refcount);
> +               refcount_inc(&mr->r_refcount);
>         spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
>
>         if (mr) {
> diff --git a/net/rds/rds.h b/net/rds/rds.h
> index ebbf909..3e410cd 100644
> --- a/net/rds/rds.h
> +++ b/net/rds/rds.h
> @@ -8,6 +8,7 @@
>  #include <linux/mutex.h>
>  #include <linux/rds.h>
>  #include <linux/rhashtable.h>
> +#include <linux/refcount.h>
>
>  #include "info.h"
>
> @@ -252,7 +253,7 @@ struct rds_ext_header_rdma_dest {
>  #define __RDS_EXTHDR_MAX       16 /* for now */
>
>  struct rds_incoming {
> -       atomic_t                i_refcount;
> +       refcount_t              i_refcount;
>         struct list_head        i_item;
>         struct rds_connection   *i_conn;
>         struct rds_conn_path    *i_conn_path;
> @@ -266,7 +267,7 @@ struct rds_incoming {
>
>  struct rds_mr {
>         struct rb_node          r_rb_node;
> -       atomic_t                r_refcount;
> +       refcount_t              r_refcount;
>         u32                     r_key;
>
>         /* A copy of the creation flags */
> @@ -345,7 +346,7 @@ static inline u32 rds_rdma_cookie_offset(rds_rdma_cookie_t cookie)
>  #define RDS_MSG_FLUSH          8
>
>  struct rds_message {
> -       atomic_t                m_refcount;
> +       refcount_t              m_refcount;
>         struct list_head        m_sock_item;
>         struct list_head        m_conn_item;
>         struct rds_incoming     m_inc;
> @@ -844,7 +845,7 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
>  void __rds_put_mr_final(struct rds_mr *mr);
>  static inline void rds_mr_put(struct rds_mr *mr)
>  {
> -       if (atomic_dec_and_test(&mr->r_refcount))
> +       if (refcount_dec_and_test(&mr->r_refcount))
>                 __rds_put_mr_final(mr);
>  }
>
> diff --git a/net/rds/recv.c b/net/rds/recv.c
> index 9d0666e..6858b71 100644
> --- a/net/rds/recv.c
> +++ b/net/rds/recv.c
> @@ -43,7 +43,7 @@
>  void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
>                   __be32 saddr)
>  {
> -       atomic_set(&inc->i_refcount, 1);
> +       refcount_set(&inc->i_refcount, 1);
>         INIT_LIST_HEAD(&inc->i_item);
>         inc->i_conn = conn;
>         inc->i_saddr = saddr;
> @@ -56,7 +56,7 @@ EXPORT_SYMBOL_GPL(rds_inc_init);
>  void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp,
>                        __be32 saddr)
>  {
> -       atomic_set(&inc->i_refcount, 1);
> +       refcount_set(&inc->i_refcount, 1);
>         INIT_LIST_HEAD(&inc->i_item);
>         inc->i_conn = cp->cp_conn;
>         inc->i_conn_path = cp;
> @@ -69,14 +69,14 @@ EXPORT_SYMBOL_GPL(rds_inc_path_init);
>
>  static void rds_inc_addref(struct rds_incoming *inc)
>  {
> -       rdsdebug("addref inc %p ref %d\n", inc, atomic_read(&inc->i_refcount));
> -       atomic_inc(&inc->i_refcount);
> +       rdsdebug("addref inc %p ref %d\n", inc, refcount_read(&inc->i_refcount));
> +       refcount_inc(&inc->i_refcount);
>  }
>
>  void rds_inc_put(struct rds_incoming *inc)
>  {
> -       rdsdebug("put inc %p ref %d\n", inc, atomic_read(&inc->i_refcount));
> -       if (atomic_dec_and_test(&inc->i_refcount)) {
> +       rdsdebug("put inc %p ref %d\n", inc, refcount_read(&inc->i_refcount));
> +       if (refcount_dec_and_test(&inc->i_refcount)) {
>                 BUG_ON(!list_empty(&inc->i_item));
>
>                 inc->i_conn->c_trans->inc_free(inc);
> diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c
> index dcf4742..592e68b 100644
> --- a/net/rds/tcp_send.c
> +++ b/net/rds/tcp_send.c
> @@ -208,7 +208,7 @@ void rds_tcp_write_space(struct sock *sk)
>         tc->t_last_seen_una = rds_tcp_snd_una(tc);
>         rds_send_path_drop_acked(cp, rds_tcp_snd_una(tc), rds_tcp_is_acked);
>
> -       if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf)
> +       if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf)
>                 queue_delayed_work(rds_wq, &cp->cp_send_w, 0);
>
>  out:
> diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
> index 5f63f6d..c3990e9 100644
> --- a/net/rxrpc/af_rxrpc.c
> +++ b/net/rxrpc/af_rxrpc.c
> @@ -56,7 +56,7 @@ static void rxrpc_sock_destructor(struct sock *);
>   */
>  static inline int rxrpc_writable(struct sock *sk)
>  {
> -       return atomic_read(&sk->sk_wmem_alloc) < (size_t) sk->sk_sndbuf;
> +       return refcount_read(&sk->sk_wmem_alloc) < (size_t) sk->sk_sndbuf;
>  }
>
>  /*
> @@ -651,7 +651,7 @@ static void rxrpc_sock_destructor(struct sock *sk)
>
>         rxrpc_purge_queue(&sk->sk_receive_queue);
>
> -       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
> +       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
>         WARN_ON(!sk_unhashed(sk));
>         WARN_ON(sk->sk_socket);
>
> @@ -668,7 +668,7 @@ static int rxrpc_release_sock(struct sock *sk)
>  {
>         struct rxrpc_sock *rx = rxrpc_sk(sk);
>
> -       _enter("%p{%d,%d}", sk, sk->sk_state, atomic_read(&sk->sk_refcnt));
> +       _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
>
>         /* declare the socket closed for business */
>         sock_orphan(sk);
> diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
> index 67b02c4..b8985d0 100644
> --- a/net/rxrpc/skbuff.c
> +++ b/net/rxrpc/skbuff.c
> @@ -27,7 +27,7 @@ void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
>  {
>         const void *here = __builtin_return_address(0);
>         int n = atomic_inc_return(select_skb_count(op));
> -       trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
> +       trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
>  }
>
>  /*
> @@ -38,7 +38,7 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
>         const void *here = __builtin_return_address(0);
>         if (skb) {
>                 int n = atomic_read(select_skb_count(op));
> -               trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
> +               trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
>         }
>  }
>
> @@ -49,7 +49,7 @@ void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
>  {
>         const void *here = __builtin_return_address(0);
>         int n = atomic_inc_return(select_skb_count(op));
> -       trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
> +       trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
>         skb_get(skb);
>  }
>
> @@ -63,7 +63,7 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
>                 int n;
>                 CHECK_SLAB_OKAY(&skb->users);
>                 n = atomic_dec_return(select_skb_count(op));
> -               trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
> +               trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
>                 kfree_skb(skb);
>         }
>  }
> @@ -78,7 +78,7 @@ void rxrpc_lose_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
>                 int n;
>                 CHECK_SLAB_OKAY(&skb->users);
>                 n = atomic_dec_return(select_skb_count(op));
> -               trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
> +               trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
>                 kfree_skb(skb);
>         }
>  }
> @@ -93,7 +93,7 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
>         while ((skb = skb_dequeue((list))) != NULL) {
>                 int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged));
>                 trace_rxrpc_skb(skb, rxrpc_skb_rx_purged,
> -                               atomic_read(&skb->users), n, here);
> +                               refcount_read(&skb->users), n, here);
>                 kfree_skb(skb);
>         }
>  }
> diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
> index 41c80b6..47ac782 100644
> --- a/net/sched/em_meta.c
> +++ b/net/sched/em_meta.c
> @@ -339,7 +339,7 @@ META_COLLECTOR(int_sk_refcnt)
>                 *err = -1;
>                 return;
>         }
> -       dst->value = atomic_read(&skb->sk->sk_refcnt);
> +       dst->value = refcount_read(&skb->sk->sk_refcnt);
>  }
>
>  META_COLLECTOR(int_sk_rcvbuf)
> diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
> index d7b9342..5b49bb6 100644
> --- a/net/sched/sch_api.c
> +++ b/net/sched/sch_api.c
> @@ -840,7 +840,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
>
>                         old = dev_graft_qdisc(dev_queue, new);
>                         if (new && i > 0)
> -                               atomic_inc(&new->refcnt);
> +                               refcount_inc(&new->refcnt);
>
>                         if (!ingress)
>                                 qdisc_destroy(old);
> @@ -851,7 +851,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
>                         notify_and_destroy(net, skb, n, classid,
>                                            dev->qdisc, new);
>                         if (new && !new->ops->attach)
> -                               atomic_inc(&new->refcnt);
> +                               refcount_inc(&new->refcnt);
>                         dev->qdisc = new ? : &noop_qdisc;
>
>                         if (new && new->ops->attach)
> @@ -1255,7 +1255,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
>                                 if (q == p ||
>                                     (p && check_loop(q, p, 0)))
>                                         return -ELOOP;
> -                               atomic_inc(&q->refcnt);
> +                               refcount_inc(&q->refcnt);
>                                 goto graft;
>                         } else {
>                                 if (!q)
> @@ -1370,7 +1370,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
>         tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
>         tcm->tcm_parent = clid;
>         tcm->tcm_handle = q->handle;
> -       tcm->tcm_info = atomic_read(&q->refcnt);
> +       tcm->tcm_info = refcount_read(&q->refcnt);
>         if (nla_put_string(skb, TCA_KIND, q->ops->id))
>                 goto nla_put_failure;
>         if (q->ops->dump && q->ops->dump(q, skb) < 0)
> diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
> index 481e4f1..e99494e 100644
> --- a/net/sched/sch_atm.c
> +++ b/net/sched/sch_atm.c
> @@ -490,7 +490,7 @@ static void sch_atm_dequeue(unsigned long data)
>                         ATM_SKB(skb)->vcc = flow->vcc;
>                         memcpy(skb_push(skb, flow->hdr_len), flow->hdr,
>                                flow->hdr_len);
> -                       atomic_add(skb->truesize,
> +                       refcount_add(skb->truesize,
>                                    &sk_atm(flow->vcc)->sk_wmem_alloc);
>                         /* atm.atm_options are already set by atm_tc_enqueue */
>                         flow->vcc->send(flow->vcc, skb);
> diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
> index 6eb9c8e..6a75581 100644
> --- a/net/sched/sch_generic.c
> +++ b/net/sched/sch_generic.c
> @@ -633,7 +633,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
>         sch->dequeue = ops->dequeue;
>         sch->dev_queue = dev_queue;
>         dev_hold(dev);
> -       atomic_set(&sch->refcnt, 1);
> +       refcount_set(&sch->refcnt, 1);
>
>         return sch;
>  errout:
> @@ -701,7 +701,7 @@ void qdisc_destroy(struct Qdisc *qdisc)
>         const struct Qdisc_ops  *ops = qdisc->ops;
>
>         if (qdisc->flags & TCQ_F_BUILTIN ||
> -           !atomic_dec_and_test(&qdisc->refcnt))
> +           !refcount_dec_and_test(&qdisc->refcnt))
>                 return;
>
>  #ifdef CONFIG_NET_SCHED
> @@ -739,7 +739,7 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
>         spin_lock_bh(root_lock);
>
>         /* Prune old scheduler */
> -       if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
> +       if (oqdisc && refcount_read(&oqdisc->refcnt) <= 1)
>                 qdisc_reset(oqdisc);
>
>         /* ... and graft new one */
> @@ -785,7 +785,7 @@ static void attach_default_qdiscs(struct net_device *dev)
>             dev->priv_flags & IFF_NO_QUEUE) {
>                 netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);
>                 dev->qdisc = txq->qdisc_sleeping;
> -               atomic_inc(&dev->qdisc->refcnt);
> +               refcount_inc(&dev->qdisc->refcnt);
>         } else {
>                 qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT);
>                 if (qdisc) {
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index d3cc30c..10ff17a 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -89,7 +89,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
>         asoc->base.type = SCTP_EP_TYPE_ASSOCIATION;
>
>         /* Initialize the object handling fields.  */
> -       atomic_set(&asoc->base.refcnt, 1);
> +       refcount_set(&asoc->base.refcnt, 1);
>
>         /* Initialize the bind addr area.  */
>         sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
> @@ -858,7 +858,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
>  /* Hold a reference to an association. */
>  void sctp_association_hold(struct sctp_association *asoc)
>  {
> -       atomic_inc(&asoc->base.refcnt);
> +       refcount_inc(&asoc->base.refcnt);
>  }
>
>  /* Release a reference to an association and cleanup
> @@ -866,7 +866,7 @@ void sctp_association_hold(struct sctp_association *asoc)
>   */
>  void sctp_association_put(struct sctp_association *asoc)
>  {
> -       if (atomic_dec_and_test(&asoc->base.refcnt))
> +       if (refcount_dec_and_test(&asoc->base.refcnt))
>                 sctp_association_destroy(asoc);
>  }
>
> diff --git a/net/sctp/auth.c b/net/sctp/auth.c
> index f99d485..b6c98fe 100644
> --- a/net/sctp/auth.c
> +++ b/net/sctp/auth.c
> @@ -63,7 +63,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key)
>         if (!key)
>                 return;
>
> -       if (atomic_dec_and_test(&key->refcnt)) {
> +       if (refcount_dec_and_test(&key->refcnt)) {
>                 kzfree(key);
>                 SCTP_DBG_OBJCNT_DEC(keys);
>         }
> @@ -84,7 +84,7 @@ static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp)
>                 return NULL;
>
>         key->len = key_len;
> -       atomic_set(&key->refcnt, 1);
> +       refcount_set(&key->refcnt, 1);
>         SCTP_DBG_OBJCNT_INC(keys);
>
>         return key;
> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
> index 615f0dd..6c8087a 100644
> --- a/net/sctp/chunk.c
> +++ b/net/sctp/chunk.c
> @@ -49,7 +49,7 @@
>  /* Initialize datamsg from memory. */
>  static void sctp_datamsg_init(struct sctp_datamsg *msg)
>  {
> -       atomic_set(&msg->refcnt, 1);
> +       refcount_set(&msg->refcnt, 1);
>         msg->send_failed = 0;
>         msg->send_error = 0;
>         msg->can_delay = 1;
> @@ -136,13 +136,13 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
>  /* Hold a reference. */
>  static void sctp_datamsg_hold(struct sctp_datamsg *msg)
>  {
> -       atomic_inc(&msg->refcnt);
> +       refcount_inc(&msg->refcnt);
>  }
>
>  /* Release a reference. */
>  void sctp_datamsg_put(struct sctp_datamsg *msg)
>  {
> -       if (atomic_dec_and_test(&msg->refcnt))
> +       if (refcount_dec_and_test(&msg->refcnt))
>                 sctp_datamsg_destroy(msg);
>  }
>
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 410ddc1..019fe78 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -113,7 +113,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
>         ep->base.type = SCTP_EP_TYPE_SOCKET;
>
>         /* Initialize the basic object fields. */
> -       atomic_set(&ep->base.refcnt, 1);
> +       refcount_set(&ep->base.refcnt, 1);
>         ep->base.dead = false;
>
>         /* Create an input queue.  */
> @@ -284,7 +284,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
>  /* Hold a reference to an endpoint. */
>  void sctp_endpoint_hold(struct sctp_endpoint *ep)
>  {
> -       atomic_inc(&ep->base.refcnt);
> +       refcount_inc(&ep->base.refcnt);
>  }
>
>  /* Release a reference to an endpoint and clean up if there are
> @@ -292,7 +292,7 @@ void sctp_endpoint_hold(struct sctp_endpoint *ep)
>   */
>  void sctp_endpoint_put(struct sctp_endpoint *ep)
>  {
> -       if (atomic_dec_and_test(&ep->base.refcnt))
> +       if (refcount_dec_and_test(&ep->base.refcnt))
>                 sctp_endpoint_destroy(ep);
>  }
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index f5320a8..53210b5 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -396,7 +396,7 @@ static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
>          * therefore only reserve a single byte to keep socket around until
>          * the packet has been transmitted.
>          */
> -       atomic_inc(&sk->sk_wmem_alloc);
> +       refcount_inc(&sk->sk_wmem_alloc);
>  }
>
>  static int sctp_packet_pack(struct sctp_packet *packet,
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index e540826..e8ae4a1 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -1081,7 +1081,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
>                                  sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) :
>                                  "illegal chunk", ntohl(chunk->subh.data_hdr->tsn),
>                                  chunk->skb ? chunk->skb->head : NULL, chunk->skb ?
> -                                atomic_read(&chunk->skb->users) : -1);
> +                                refcount_read(&chunk->skb->users) : -1);
>
>                         /* Add the chunk to the packet.  */
>                         status = sctp_packet_transmit_chunk(packet, chunk, 0, gfp);
> diff --git a/net/sctp/proc.c b/net/sctp/proc.c
> index 206377f..25cd840 100644
> --- a/net/sctp/proc.c
> +++ b/net/sctp/proc.c
> @@ -365,7 +365,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
>                 assoc->c.sinit_num_ostreams, assoc->max_retrans,
>                 assoc->init_retries, assoc->shutdown_retries,
>                 assoc->rtx_data_chunks,
> -               atomic_read(&sk->sk_wmem_alloc),
> +               refcount_read(&sk->sk_wmem_alloc),
>                 sk->sk_wmem_queued,
>                 sk->sk_sndbuf,
>                 sk->sk_rcvbuf);
> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
> index 9e9690b..7eac4e9 100644
> --- a/net/sctp/sm_make_chunk.c
> +++ b/net/sctp/sm_make_chunk.c
> @@ -1336,7 +1336,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
>         INIT_LIST_HEAD(&retval->transmitted_list);
>         INIT_LIST_HEAD(&retval->frag_list);
>         SCTP_DBG_OBJCNT_INC(chunk);
> -       atomic_set(&retval->refcnt, 1);
> +       refcount_set(&retval->refcnt, 1);
>
>  nodata:
>         return retval;
> @@ -1449,13 +1449,13 @@ void sctp_chunk_free(struct sctp_chunk *chunk)
>  /* Grab a reference to the chunk. */
>  void sctp_chunk_hold(struct sctp_chunk *ch)
>  {
> -       atomic_inc(&ch->refcnt);
> +       refcount_inc(&ch->refcnt);
>  }
>
>  /* Release a reference to the chunk. */
>  void sctp_chunk_put(struct sctp_chunk *ch)
>  {
> -       if (atomic_dec_and_test(&ch->refcnt))
> +       if (refcount_dec_and_test(&ch->refcnt))
>                 sctp_chunk_destroy(ch);
>  }
>
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 318c678..73a545b 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -163,7 +163,7 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
>                                 sizeof(struct sk_buff) +
>                                 sizeof(struct sctp_chunk);
>
> -       atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
> +       refcount_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
>         sk->sk_wmem_queued += chunk->skb->truesize;
>         sk_mem_charge(sk, chunk->skb->truesize);
>  }
> @@ -7237,7 +7237,7 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
>                 if (flags & MSG_PEEK) {
>                         skb = skb_peek(&sk->sk_receive_queue);
>                         if (skb)
> -                               atomic_inc(&skb->users);
> +                               refcount_inc(&skb->users);
>                 } else {
>                         skb = __skb_dequeue(&sk->sk_receive_queue);
>                 }
> @@ -7355,7 +7355,7 @@ static void sctp_wfree(struct sk_buff *skb)
>                                 sizeof(struct sk_buff) +
>                                 sizeof(struct sctp_chunk);
>
> -       atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
> +       WARN_ON(refcount_sub_and_test(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc));
>
>         /*
>          * This undoes what is done via sctp_set_owner_w and sk_mem_charge
> diff --git a/net/sctp/transport.c b/net/sctp/transport.c
> index a1652ab..a082cd2 100644
> --- a/net/sctp/transport.c
> +++ b/net/sctp/transport.c
> @@ -97,7 +97,7 @@ static struct sctp_transport *sctp_transport_init(struct net *net,
>         /* Initialize the 64-bit random nonce sent with heartbeat. */
>         get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
>
> -       atomic_set(&peer->refcnt, 1);
> +       refcount_set(&peer->refcnt, 1);
>
>         return peer;
>  }
> @@ -167,7 +167,7 @@ static void sctp_transport_destroy_rcu(struct rcu_head *head)
>   */
>  static void sctp_transport_destroy(struct sctp_transport *transport)
>  {
> -       if (unlikely(atomic_read(&transport->refcnt))) {
> +       if (unlikely(refcount_read(&transport->refcnt))) {
>                 WARN(1, "Attempt to destroy undead transport %p!\n", transport);
>                 return;
>         }
> @@ -303,7 +303,7 @@ void sctp_transport_route(struct sctp_transport *transport,
>  /* Hold a reference to a transport.  */
>  int sctp_transport_hold(struct sctp_transport *transport)
>  {
> -       return atomic_add_unless(&transport->refcnt, 1, 0);
> +       return refcount_inc_not_zero(&transport->refcnt);
>  }
>
>  /* Release a reference to a transport and clean up
> @@ -311,7 +311,7 @@ int sctp_transport_hold(struct sctp_transport *transport)
>   */
>  void sctp_transport_put(struct sctp_transport *transport)
>  {
> -       if (atomic_dec_and_test(&transport->refcnt))
> +       if (refcount_dec_and_test(&transport->refcnt))
>                 sctp_transport_destroy(transport);
>  }
>
> diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
> index 2bff63a..b6439b9 100644
> --- a/net/sunrpc/auth.c
> +++ b/net/sunrpc/auth.c
> @@ -310,7 +310,7 @@ rpcauth_unhash_cred(struct rpc_cred *cred)
>
>         cache_lock = &cred->cr_auth->au_credcache->lock;
>         spin_lock(cache_lock);
> -       ret = atomic_read(&cred->cr_count) == 0;
> +       ret = refcount_read(&cred->cr_count) == 0;
>         if (ret)
>                 rpcauth_unhash_cred_locked(cred);
>         spin_unlock(cache_lock);
> @@ -470,12 +470,12 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
>                 list_del_init(&cred->cr_lru);
>                 number_cred_unused--;
>                 freed++;
> -               if (atomic_read(&cred->cr_count) != 0)
> +               if (refcount_read(&cred->cr_count) != 0)
>                         continue;
>
>                 cache_lock = &cred->cr_auth->au_credcache->lock;
>                 spin_lock(cache_lock);
> -               if (atomic_read(&cred->cr_count) == 0) {
> +               if (refcount_read(&cred->cr_count) == 0) {
>                         get_rpccred(cred);
>                         list_add_tail(&cred->cr_lru, free);
>                         rpcauth_unhash_cred_locked(cred);
> @@ -642,7 +642,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
>  {
>         INIT_HLIST_NODE(&cred->cr_hash);
>         INIT_LIST_HEAD(&cred->cr_lru);
> -       atomic_set(&cred->cr_count, 1);
> +       refcount_set(&cred->cr_count, 1);
>         cred->cr_auth = auth;
>         cred->cr_ops = ops;
>         cred->cr_expire = jiffies;
> @@ -715,12 +715,12 @@ put_rpccred(struct rpc_cred *cred)
>                 return;
>         /* Fast path for unhashed credentials */
>         if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
> -               if (atomic_dec_and_test(&cred->cr_count))
> +               if (refcount_dec_and_test(&cred->cr_count))
>                         cred->cr_ops->crdestroy(cred);
>                 return;
>         }
>
> -       if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
> +       if (!refcount_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
>                 return;
>         if (!list_empty(&cred->cr_lru)) {
>                 number_cred_unused--;
> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
> index cdeb1d8..59b5860 100644
> --- a/net/sunrpc/auth_gss/auth_gss.c
> +++ b/net/sunrpc/auth_gss/auth_gss.c
> @@ -52,6 +52,7 @@
>  #include <linux/sunrpc/gss_api.h>
>  #include <linux/uaccess.h>
>  #include <linux/hashtable.h>
> +#include <linux/refcount.h>
>
>  #include "../netns.h"
>
> @@ -117,14 +118,14 @@ static const struct rpc_pipe_ops gss_upcall_ops_v1;
>  static inline struct gss_cl_ctx *
>  gss_get_ctx(struct gss_cl_ctx *ctx)
>  {
> -       atomic_inc(&ctx->count);
> +       refcount_inc(&ctx->count);
>         return ctx;
>  }
>
>  static inline void
>  gss_put_ctx(struct gss_cl_ctx *ctx)
>  {
> -       if (atomic_dec_and_test(&ctx->count))
> +       if (refcount_dec_and_test(&ctx->count))
>                 gss_free_ctx(ctx);
>  }
>
> @@ -200,7 +201,7 @@ gss_alloc_context(void)
>                 ctx->gc_proc = RPC_GSS_PROC_DATA;
>                 ctx->gc_seq = 1;        /* NetApp 6.4R1 doesn't accept seq. no. 0 */
>                 spin_lock_init(&ctx->gc_seq_lock);
> -               atomic_set(&ctx->count,1);
> +               refcount_set(&ctx->count,1);
>         }
>         return ctx;
>  }
> @@ -287,7 +288,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
>  #define UPCALL_BUF_LEN 128
>
>  struct gss_upcall_msg {
> -       atomic_t count;
> +       refcount_t count;
>         kuid_t  uid;
>         struct rpc_pipe_msg msg;
>         struct list_head list;
> @@ -328,7 +329,7 @@ static void
>  gss_release_msg(struct gss_upcall_msg *gss_msg)
>  {
>         struct net *net = gss_msg->auth->net;
> -       if (!atomic_dec_and_test(&gss_msg->count))
> +       if (!refcount_dec_and_test(&gss_msg->count))
>                 return;
>         put_pipe_version(net);
>         BUG_ON(!list_empty(&gss_msg->list));
> @@ -348,7 +349,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth
>                         continue;
>                 if (auth && pos->auth->service != auth->service)
>                         continue;
> -               atomic_inc(&pos->count);
> +               refcount_inc(&pos->count);
>                 dprintk("RPC:       %s found msg %p\n", __func__, pos);
>                 return pos;
>         }
> @@ -369,7 +370,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg)
>         spin_lock(&pipe->lock);
>         old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth);
>         if (old == NULL) {
> -               atomic_inc(&gss_msg->count);
> +               refcount_inc(&gss_msg->count);
>                 list_add(&gss_msg->list, &pipe->in_downcall);
>         } else
>                 gss_msg = old;
> @@ -383,7 +384,7 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
>         list_del_init(&gss_msg->list);
>         rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
>         wake_up_all(&gss_msg->waitqueue);
> -       atomic_dec(&gss_msg->count);
> +       WARN_ON(refcount_dec_and_test(&gss_msg->count));
>  }
>
>  static void
> @@ -506,7 +507,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
>         INIT_LIST_HEAD(&gss_msg->list);
>         rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
>         init_waitqueue_head(&gss_msg->waitqueue);
> -       atomic_set(&gss_msg->count, 1);
> +       refcount_set(&gss_msg->count, 1);
>         gss_msg->uid = uid;
>         gss_msg->auth = gss_auth;
>         switch (vers) {
> @@ -542,11 +543,11 @@ gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred)
>         gss_msg = gss_add_msg(gss_new);
>         if (gss_msg == gss_new) {
>                 int res;
> -               atomic_inc(&gss_msg->count);
> +               refcount_inc(&gss_msg->count);
>                 res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg);
>                 if (res) {
>                         gss_unhash_msg(gss_new);
> -                       atomic_dec(&gss_msg->count);
> +                       refcount_dec(&gss_msg->count);
>                         gss_release_msg(gss_new);
>                         gss_msg = ERR_PTR(res);
>                 }
> @@ -595,7 +596,7 @@ gss_refresh_upcall(struct rpc_task *task)
>                 task->tk_timeout = 0;
>                 gss_cred->gc_upcall = gss_msg;
>                 /* gss_upcall_callback will release the reference to gss_upcall_msg */
> -               atomic_inc(&gss_msg->count);
> +               refcount_inc(&gss_msg->count);
>                 rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
>         } else {
>                 gss_handle_downcall_result(gss_cred, gss_msg);
> @@ -815,7 +816,7 @@ gss_pipe_release(struct inode *inode)
>                 if (!list_empty(&gss_msg->msg.list))
>                         continue;
>                 gss_msg->msg.errno = -EPIPE;
> -               atomic_inc(&gss_msg->count);
> +               refcount_inc(&gss_msg->count);
>                 __gss_unhash_msg(gss_msg);
>                 spin_unlock(&pipe->lock);
>                 gss_release_msg(gss_msg);
> @@ -834,7 +835,7 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
>         if (msg->errno < 0) {
>                 dprintk("RPC:       %s releasing msg %p\n",
>                         __func__, gss_msg);
> -               atomic_inc(&gss_msg->count);
> +               refcount_inc(&gss_msg->count);
>                 gss_unhash_msg(gss_msg);
>                 if (msg->errno == -ETIMEDOUT)
>                         warn_gssd();
> diff --git a/net/tipc/socket.c b/net/tipc/socket.c
> index 800caaa..2189667 100644
> --- a/net/tipc/socket.c
> +++ b/net/tipc/socket.c
> @@ -2332,7 +2332,7 @@ static void tipc_sk_remove(struct tipc_sock *tsk)
>         struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id);
>
>         if (!rhashtable_remove_fast(&tn->sk_rht, &tsk->node, tsk_rht_params)) {
> -               WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
> +               WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
>                 __sock_put(sk);
>         }
>  }
> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index 127656e..3a3223c 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -211,7 +211,7 @@ EXPORT_SYMBOL_GPL(unix_peer_get);
>
>  static inline void unix_release_addr(struct unix_address *addr)
>  {
> -       if (atomic_dec_and_test(&addr->refcnt))
> +       if (refcount_dec_and_test(&addr->refcnt))
>                 kfree(addr);
>  }
>
> @@ -441,7 +441,7 @@ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
>  static int unix_writable(const struct sock *sk)
>  {
>         return sk->sk_state != TCP_LISTEN &&
> -              (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
> +              (refcount_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
>  }
>
>  static void unix_write_space(struct sock *sk)
> @@ -486,7 +486,7 @@ static void unix_sock_destructor(struct sock *sk)
>
>         skb_queue_purge(&sk->sk_receive_queue);
>
> -       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
> +       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
>         WARN_ON(!sk_unhashed(sk));
>         WARN_ON(sk->sk_socket);
>         if (!sock_flag(sk, SOCK_DEAD)) {
> @@ -863,7 +863,7 @@ static int unix_autobind(struct socket *sock)
>                 goto out;
>
>         addr->name->sun_family = AF_UNIX;
> -       atomic_set(&addr->refcnt, 1);
> +       refcount_set(&addr->refcnt, 1);
>
>  retry:
>         addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
> @@ -1026,7 +1026,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
>         memcpy(addr->name, sunaddr, addr_len);
>         addr->len = addr_len;
>         addr->hash = hash ^ sk->sk_type;
> -       atomic_set(&addr->refcnt, 1);
> +       refcount_set(&addr->refcnt, 1);
>
>         if (sun_path[0]) {
>                 struct path path;
> @@ -1324,7 +1324,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
>
>         /* copy address information from listening to new sock*/
>         if (otheru->addr) {
> -               atomic_inc(&otheru->addr->refcnt);
> +               refcount_inc(&otheru->addr->refcnt);
>                 newu->addr = otheru->addr;
>         }
>         if (otheru->path.dentry) {
> @@ -2021,7 +2021,7 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page,
>         skb->len += size;
>         skb->data_len += size;
>         skb->truesize += size;
> -       atomic_add(size, &sk->sk_wmem_alloc);
> +       refcount_add(size, &sk->sk_wmem_alloc);
>
>         if (newskb) {
>                 err = unix_scm_to_skb(&scm, skb, false);
> @@ -2795,7 +2795,7 @@ static int unix_seq_show(struct seq_file *seq, void *v)
>
>                 seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
>                         s,
> -                       atomic_read(&s->sk_refcnt),
> +                       refcount_read(&s->sk_refcnt),
>                         0,
>                         s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
>                         s->sk_type,
> diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c
> index 4596115..472dce0 100644
> --- a/net/wireless/lib80211.c
> +++ b/net/wireless/lib80211.c
> @@ -92,7 +92,7 @@ static void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info,
>
>         spin_lock_irqsave(info->lock, flags);
>         list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) {
> -               if (atomic_read(&entry->refcnt) != 0 && !force)
> +               if (refcount_read(&entry->refcnt) != 0 && !force)
>                         continue;
>
>                 list_del(&entry->list);
> diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
> index bcaa180..e0cd04d 100644
> --- a/net/x25/x25_link.c
> +++ b/net/x25/x25_link.c
> @@ -266,7 +266,7 @@ void x25_link_device_up(struct net_device *dev)
>                                        X25_MASK_PACKET_SIZE |
>                                        X25_MASK_WINDOW_SIZE;
>         nb->t20      = sysctl_x25_restart_request_timeout;
> -       atomic_set(&nb->refcnt, 1);
> +       refcount_set(&nb->refcnt, 1);
>
>         write_lock_bh(&x25_neigh_list_lock);
>         list_add(&nb->node, &x25_neigh_list);
> diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c
> index 277c8d2..b85b889 100644
> --- a/net/x25/x25_route.c
> +++ b/net/x25/x25_route.c
> @@ -55,7 +55,7 @@ static int x25_add_route(struct x25_address *address, unsigned int sigdigits,
>
>         rt->sigdigits = sigdigits;
>         rt->dev       = dev;
> -       atomic_set(&rt->refcnt, 1);
> +       refcount_set(&rt->refcnt, 1);
>
>         list_add(&rt->node, &x25_route_list);
>         rc = 0;
> diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
> index 6e3f025..25f9939 100644
> --- a/net/xfrm/xfrm_input.c
> +++ b/net/xfrm/xfrm_input.c
> @@ -118,7 +118,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
>                 for (i = 0; i < sp->len; i++)
>                         xfrm_state_hold(sp->xvec[i]);
>         }
> -       atomic_set(&sp->refcnt, 1);
> +       refcount_set(&sp->refcnt, 1);
>         return sp;
>  }
>  EXPORT_SYMBOL(secpath_dup);
> @@ -219,7 +219,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
>         }
>
>         /* Allocate new secpath or COW existing one. */
> -       if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
> +       if (!skb->sp || refcount_read(&skb->sp->refcnt) != 1) {
>                 struct sec_path *sp;
>
>                 sp = secpath_dup(skb->sp);
> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> index 177e208..bc39de5 100644
> --- a/net/xfrm/xfrm_policy.c
> +++ b/net/xfrm/xfrm_policy.c
> @@ -62,7 +62,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
>
>  static inline bool xfrm_pol_hold_rcu(struct xfrm_policy *policy)
>  {
> -       return atomic_inc_not_zero(&policy->refcnt);
> +       return refcount_inc_not_zero(&policy->refcnt);
>  }
>
>  static inline bool
> @@ -297,7 +297,7 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
>                 INIT_HLIST_NODE(&policy->bydst);
>                 INIT_HLIST_NODE(&policy->byidx);
>                 rwlock_init(&policy->lock);
> -               atomic_set(&policy->refcnt, 1);
> +               refcount_set(&policy->refcnt, 1);
>                 skb_queue_head_init(&policy->polq.hold_queue);
>                 setup_timer(&policy->timer, xfrm_policy_timer,
>                                 (unsigned long)policy);
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index 64e3c82..e9732c8 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -48,7 +48,7 @@ static HLIST_HEAD(xfrm_state_gc_list);
>
>  static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x)
>  {
> -       return atomic_inc_not_zero(&x->refcnt);
> +       return refcount_inc_not_zero(&x->refcnt);
>  }
>
>  static inline unsigned int xfrm_dst_hash(struct net *net,
> @@ -485,7 +485,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
>
>         if (x) {
>                 write_pnet(&x->xs_net, net);
> -               atomic_set(&x->refcnt, 1);
> +               refcount_set(&x->refcnt, 1);
>                 atomic_set(&x->tunnel_users, 0);
>                 INIT_LIST_HEAD(&x->km.all);
>                 INIT_HLIST_NODE(&x->bydst);
> --
> 2.7.4
>

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

* [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18 10:30 ` [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage Greg KH
@ 2017-01-18 20:06   ` Kees Cook
  2017-01-18 20:35     ` Greg KH
  2017-01-23  7:52   ` [kernel-hardening] " Reshetova, Elena
  1 sibling, 1 reply; 46+ messages in thread
From: Kees Cook @ 2017-01-18 20:06 UTC (permalink / raw)
  To: Greg KH
  Cc: Elena Reshetova, kernel-hardening, Arnd Bergmann,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Peter Zijlstra,
	Will Deacon, David Windsor

On Wed, Jan 18, 2017 at 2:30 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Wed, Jan 18, 2017 at 11:11:29AM +0200, Elena Reshetova wrote:
>> Changes since v1:
>>  - kref INIT fixes are moved to a proper separate commit
>>  - Peter's commits are now properly integrated into series
>>  - various small fixes are incorporated based on testing
>>    results and feedback
>>
>> This patch series is build on top of Peter's Zijlstra patches
>> that provide refcount_t type and API definition.
>> The rest of patches convert various places of kernel subsystems
>> where atomic_t was used for reference counting to new refcount_t type and API.
>> By doing this, we make sure that underflows and overflows
>> cannot occur in these places and therefore no use-after-free situation
>> can be created and misused by an attacker.
>
> Your first 7 patches are fine, and most of them are already in the tip
> tree and getting use in linux-next now.  I'd recommend submitting the

Where do you see this? I haven't seen refcount_t land in -next yet.

Should I carry these in the KSPP tree, or who should take them?

-Kees

-- 
Kees Cook
Nexus Security

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

* [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18 20:06   ` Kees Cook
@ 2017-01-18 20:35     ` Greg KH
  2017-01-18 20:57       ` Kees Cook
  2017-01-19  8:52       ` Peter Zijlstra
  0 siblings, 2 replies; 46+ messages in thread
From: Greg KH @ 2017-01-18 20:35 UTC (permalink / raw)
  To: Kees Cook
  Cc: Elena Reshetova, kernel-hardening, Arnd Bergmann,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Peter Zijlstra,
	Will Deacon, David Windsor

On Wed, Jan 18, 2017 at 12:06:19PM -0800, Kees Cook wrote:
> On Wed, Jan 18, 2017 at 2:30 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
> > On Wed, Jan 18, 2017 at 11:11:29AM +0200, Elena Reshetova wrote:
> >> Changes since v1:
> >>  - kref INIT fixes are moved to a proper separate commit
> >>  - Peter's commits are now properly integrated into series
> >>  - various small fixes are incorporated based on testing
> >>    results and feedback
> >>
> >> This patch series is build on top of Peter's Zijlstra patches
> >> that provide refcount_t type and API definition.
> >> The rest of patches convert various places of kernel subsystems
> >> where atomic_t was used for reference counting to new refcount_t type and API.
> >> By doing this, we make sure that underflows and overflows
> >> cannot occur in these places and therefore no use-after-free situation
> >> can be created and misused by an attacker.
> >
> > Your first 7 patches are fine, and most of them are already in the tip
> > tree and getting use in linux-next now.  I'd recommend submitting the
> 
> Where do you see this? I haven't seen refcount_t land in -next yet.

The patches leading up to refcount_t are in the tip tree.

> Should I carry these in the KSPP tree, or who should take them?

I think the refcount_t patch should also go to tip given it depends on
the kref patches.  But that's up to Peter, he would know best...

thanks,

greg k-h

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

* [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18 20:35     ` Greg KH
@ 2017-01-18 20:57       ` Kees Cook
  2017-01-19  8:52       ` Peter Zijlstra
  1 sibling, 0 replies; 46+ messages in thread
From: Kees Cook @ 2017-01-18 20:57 UTC (permalink / raw)
  To: Greg KH, Peter Zijlstra
  Cc: Elena Reshetova, kernel-hardening, Arnd Bergmann,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Will Deacon,
	David Windsor

On Wed, Jan 18, 2017 at 12:35 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Wed, Jan 18, 2017 at 12:06:19PM -0800, Kees Cook wrote:
>> On Wed, Jan 18, 2017 at 2:30 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
>> > On Wed, Jan 18, 2017 at 11:11:29AM +0200, Elena Reshetova wrote:
>> >> Changes since v1:
>> >>  - kref INIT fixes are moved to a proper separate commit
>> >>  - Peter's commits are now properly integrated into series
>> >>  - various small fixes are incorporated based on testing
>> >>    results and feedback
>> >>
>> >> This patch series is build on top of Peter's Zijlstra patches
>> >> that provide refcount_t type and API definition.
>> >> The rest of patches convert various places of kernel subsystems
>> >> where atomic_t was used for reference counting to new refcount_t type and API.
>> >> By doing this, we make sure that underflows and overflows
>> >> cannot occur in these places and therefore no use-after-free situation
>> >> can be created and misused by an attacker.
>> >
>> > Your first 7 patches are fine, and most of them are already in the tip
>> > tree and getting use in linux-next now.  I'd recommend submitting the
>>
>> Where do you see this? I haven't seen refcount_t land in -next yet.
>
> The patches leading up to refcount_t are in the tip tree.

Ah, I see it here:

http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/?h=locking/core

I wonder why it hasn't appeared in -next.

>> Should I carry these in the KSPP tree, or who should take them?
>
> I think the refcount_t patch should also go to tip given it depends on
> the kref patches.  But that's up to Peter, he would know best...

Yeah, agreed. Peter, can you add that to tip? Then we can base more work off it.

Thanks!

-Kees

-- 
Kees Cook
Nexus Security

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
                   ` (18 preceding siblings ...)
  2017-01-18 10:30 ` [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage Greg KH
@ 2017-01-18 21:52 ` Eric Biggers
  2017-01-19  8:31   ` Reshetova, Elena
  2017-01-19  9:19   ` Peter Zijlstra
  19 siblings, 2 replies; 46+ messages in thread
From: Eric Biggers @ 2017-01-18 21:52 UTC (permalink / raw)
  To: kernel-hardening
  Cc: keescook, arnd, tglx, mingo, h.peter.anvin, peterz, will.deacon,
	dwindsor, gregkh, Elena Reshetova

On Wed, Jan 18, 2017 at 11:11:29AM +0200, Elena Reshetova wrote:
> Changes since v1:
>  - kref INIT fixes are moved to a proper separate commit
>  - Peter's commits are now properly integrated into series 
>  - various small fixes are incorporated based on testing
>    results and feedback
> 
> This patch series is build on top of Peter's Zijlstra patches
> that provide refcount_t type and API definition.

Hi Elena,

There seems to be a lot of focus on converting things to use refcount_t but much
less focus on providing a refcount_t implementation that actually meets the
performance and security goals of the feature.  Notably, the proposed patchset
provides no information about why the proposed implementation was chosen over
the PaX implementation (note that I'm talking about the actual implementation of
safe reference counts, not the atomic_t/atomic_unchecked_t division) which as
I've already mentioned is much more efficient (less bloated and faster) while
still meeting the security goal.  I'm especially worried that people will be put
in a position where they need to take performance concerns into account when
deciding whether to use refcount_t or not.  And the patch even still includes
the "don't allow incrementing a zero refcount" check which AFAICS is bogus from
a security perspective.

Even if you and Peter disagree with the comments that I and also PaX Team have
made, the patch must at least explain the design decisions made.

I also find it strange that the actual refcount_t implementation is hidden in
patch 7/18 in the series and has subject "kref: ...", when in fact it's actually
the most important patch and will affect much more than kref.

Thanks,

Eric

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

* [kernel-hardening] Re: [RFCv2 PATCH 09/18] net: convert from atomic_t to refcount_t
  2017-01-18 18:39   ` [kernel-hardening] " David Windsor
@ 2017-01-19  1:11     ` Kees Cook
  2017-01-19  3:29       ` David Windsor
  0 siblings, 1 reply; 46+ messages in thread
From: Kees Cook @ 2017-01-19  1:11 UTC (permalink / raw)
  To: David Windsor
  Cc: Elena Reshetova, kernel-hardening, Arnd Bergmann,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Peter Zijlstra,
	Will Deacon, Greg KH, Hans Liljestrand

On Wed, Jan 18, 2017 at 10:39 AM, David Windsor <dwindsor@gmail.com> wrote:
> The relevant part of the patch has been cut off, but it appears that
> you've fixed some of the issues we identified earlier as corner cases
> as to reference counting in net/.  In particular, inetpeer.c has its
> own garbage collection system in place which frees shared objects when
> their reference count became -1 (rather than 0).  The proposed
> solution was to do a global +1 on this refcounting scheme, then
> replace unsupported atomic_*() functions with appropriate refcount_*()
> calls.
>
> When submitting this to netdev, it may make sense to separate out
> these changes: first, do a global +1 (while still using atomic_t),
> then convert to refcount_t.  I'm already working on this now, but I
> didn't know if you wanted to follow this approach or not.

David, if you've got the global +1 patches ready, let's start feeding
those to netdev ASAP. We can convert them to refcount_t more easily
after that.

-Kees

-- 
Kees Cook
Nexus Security

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

* [kernel-hardening] Re: [RFCv2 PATCH 09/18] net: convert from atomic_t to refcount_t
  2017-01-19  1:11     ` Kees Cook
@ 2017-01-19  3:29       ` David Windsor
  2017-01-19  7:48         ` Reshetova, Elena
  0 siblings, 1 reply; 46+ messages in thread
From: David Windsor @ 2017-01-19  3:29 UTC (permalink / raw)
  To: Kees Cook
  Cc: Elena Reshetova, kernel-hardening, Arnd Bergmann,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Peter Zijlstra,
	Will Deacon, Greg KH, Hans Liljestrand

On Wed, Jan 18, 2017 at 8:11 PM, Kees Cook <keescook@chromium.org> wrote:
> On Wed, Jan 18, 2017 at 10:39 AM, David Windsor <dwindsor@gmail.com> wrote:
>> The relevant part of the patch has been cut off, but it appears that
>> you've fixed some of the issues we identified earlier as corner cases
>> as to reference counting in net/.  In particular, inetpeer.c has its
>> own garbage collection system in place which frees shared objects when
>> their reference count became -1 (rather than 0).  The proposed
>> solution was to do a global +1 on this refcounting scheme, then
>> replace unsupported atomic_*() functions with appropriate refcount_*()
>> calls.
>>
>> When submitting this to netdev, it may make sense to separate out
>> these changes: first, do a global +1 (while still using atomic_t),
>> then convert to refcount_t.  I'm already working on this now, but I
>> didn't know if you wanted to follow this approach or not.
>
> David, if you've got the global +1 patches ready, let's start feeding
> those to netdev ASAP. We can convert them to refcount_t more easily
> after that.
>

Alright, let me get them in order and I'll submit them to netdev.  I
just wanted to make sure that an alternate approach hadn't been
decided upon.

Thanks,
David

> -Kees
>
> --
> Kees Cook
> Nexus Security

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

* RE: [kernel-hardening] Re: [RFCv2 PATCH 09/18] net: convert from atomic_t to refcount_t
  2017-01-19  3:29       ` David Windsor
@ 2017-01-19  7:48         ` Reshetova, Elena
  2017-01-19 15:08           ` David Windsor
  0 siblings, 1 reply; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-19  7:48 UTC (permalink / raw)
  To: kernel-hardening, Kees Cook
  Cc: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Anvin, H Peter,
	Peter Zijlstra, Will Deacon, Greg KH, Hans Liljestrand

> On Wed, Jan 18, 2017 at 8:11 PM, Kees Cook <keescook@chromium.org> wrote:
> > On Wed, Jan 18, 2017 at 10:39 AM, David Windsor <dwindsor@gmail.com>
> wrote:
> >> The relevant part of the patch has been cut off, but it appears that
> >> you've fixed some of the issues we identified earlier as corner cases
> >> as to reference counting in net/.  In particular, inetpeer.c has its
> >> own garbage collection system in place which frees shared objects when
> >> their reference count became -1 (rather than 0).  The proposed
> >> solution was to do a global +1 on this refcounting scheme, then
> >> replace unsupported atomic_*() functions with appropriate refcount_*()
> >> calls.
> >>
> >> When submitting this to netdev, it may make sense to separate out
> >> these changes: first, do a global +1 (while still using atomic_t),
> >> then convert to refcount_t.  I'm already working on this now, but I
> >> didn't know if you wanted to follow this approach or not.
> >
> > David, if you've got the global +1 patches ready, let's start feeding
> > those to netdev ASAP. We can convert them to refcount_t more easily
> > after that.
> >
> 
> Alright, let me get them in order and I'll submit them to netdev.  I
> just wanted to make sure that an alternate approach hadn't been
> decided upon.
> 

No, we haven't decided on that. 
We had only some +1s, but not for all of it, so if you have a global +1, then it is even better!
Then we can drop +1 parts. 

And what do you mean by " The relevant part of the patch has been cut off " ? It is one huge
patch but I got it in full mailed via list. Do you see it corrupted or? 

Best Regards,
Elena

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

* RE: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18 21:52 ` [kernel-hardening] " Eric Biggers
@ 2017-01-19  8:31   ` Reshetova, Elena
  2017-01-19  9:19   ` Peter Zijlstra
  1 sibling, 0 replies; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-19  8:31 UTC (permalink / raw)
  To: Eric Biggers, kernel-hardening
  Cc: keescook, arnd, tglx, mingo, Anvin, H Peter, peterz, will.deacon,
	dwindsor, gregkh

> On Wed, Jan 18, 2017 at 11:11:29AM +0200, Elena Reshetova wrote:
> > Changes since v1:
> >  - kref INIT fixes are moved to a proper separate commit
> >  - Peter's commits are now properly integrated into series
> >  - various small fixes are incorporated based on testing
> >    results and feedback
> >
> > This patch series is build on top of Peter's Zijlstra patches
> > that provide refcount_t type and API definition.
> 
> Hi Elena,

Hi Erik,

To be honest this is all tricky and I will have to explain at least some of our reasoning below.
I guess some of us (me included) would prefer the PaX/grsecurity implementation for the main reason that 
it was providing security by default to atomic_t type. That's why we first took PaX patches and did the porting
and etc. However, that approach was strongly objected and it seemed that we need to change the approach
if we want at least to start somewhere. I guess it is classical example of "disagree and commit" principle in action :)
We all afterall want a better kernel security, so small steps better than no steps. 
As for this and earlier discussions I think some of your questions with regards to the initial 7 patches in the series should be answered by Peter.

> There seems to be a lot of focus on converting things to use refcount_t but much
> less focus on providing a refcount_t implementation that actually meets the
> performance and security goals of the feature.  

Together with Hans we spent a lot of time working on conversions and looking on what code needs API-wise.
We haven't really put our attention to the insides of interface since Peter was behind that work and he simply
has more knowledge on the subsystem. 

Notably, the proposed patchset
> provides no information about why the proposed implementation was chosen over
> the PaX implementation (note that I'm talking about the actual implementation of
> safe reference counts, not the atomic_t/atomic_unchecked_t division) which as
> I've already mentioned is much more efficient (less bloated and faster) while
> still meeting the security goal.  I'm especially worried that people will be put
> in a position where they need to take performance concerns into account when
> deciding whether to use refcount_t or not.  

We were initially thinking that these are just RFCs that we keep testing and polishing, so I 
think maybe that's why Peter had a very short description on it. However, it does seem that it is already in linux-next now...
I guess maybe now it should be added to the documentation section? I agree that it is important to explain these things
Otherwise people either get it wrong or simply don't use refcount_t at all. 

And the patch even still includes
> the "don't allow incrementing a zero refcount" check which AFAICS is bogus from
> a security perspective.

Again, we mentioned this before and I am especially worried about this part also from
practical point of view: it is such a big change that kernel might not be ready for and it 
would keep coming with bugs after. 

> 
> Even if you and Peter disagree with the comments that I and also PaX Team have
> made, the patch must at least explain the design decisions made.

I personally don't disagree with some comments, but you are right we need more documentation provided. 

Peter given that your patches are already in linux-next, where should documentation/reasoning land? 
Including it to the subsystem patches doesn't seem to make any sense to me...

Best Regards,
Elena.

> 
> I also find it strange that the actual refcount_t implementation is hidden in
> patch 7/18 in the series and has subject "kref: ...", when in fact it's actually
> the most important patch and will affect much more than kref.
> 
> Thanks,
> 
> Eric

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

* [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18 20:35     ` Greg KH
  2017-01-18 20:57       ` Kees Cook
@ 2017-01-19  8:52       ` Peter Zijlstra
  1 sibling, 0 replies; 46+ messages in thread
From: Peter Zijlstra @ 2017-01-19  8:52 UTC (permalink / raw)
  To: Greg KH
  Cc: Kees Cook, Elena Reshetova, kernel-hardening, Arnd Bergmann,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Will Deacon,
	David Windsor

On Wed, Jan 18, 2017 at 09:35:34PM +0100, Greg KH wrote:
> I think the refcount_t patch should also go to tip given it depends on
> the kref patches.  But that's up to Peter, he would know best...

Yeah, so I held back on that and the kref conversion, because I wanted
to get the kref fixup thingies in first. If there's no fallout from that
I can stuff in the refcount_t bits.

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18 21:52 ` [kernel-hardening] " Eric Biggers
  2017-01-19  8:31   ` Reshetova, Elena
@ 2017-01-19  9:19   ` Peter Zijlstra
  2017-01-19 10:22     ` Reshetova, Elena
                       ` (2 more replies)
  1 sibling, 3 replies; 46+ messages in thread
From: Peter Zijlstra @ 2017-01-19  9:19 UTC (permalink / raw)
  To: Eric Biggers
  Cc: kernel-hardening, keescook, arnd, tglx, mingo, h.peter.anvin,
	will.deacon, dwindsor, gregkh, Elena Reshetova

On Wed, Jan 18, 2017 at 01:52:47PM -0800, Eric Biggers wrote:
> There seems to be a lot of focus on converting things to use refcount_t but much
> less focus on providing a refcount_t implementation that actually meets the
> performance and security goals of the feature.

And here you go again... :-(

The refcount_t implementation does meet the security goals afaict, it
has full saturation semantics, which means an overflow bug gets turned
into a resource leak.

That covers the entirely of the security goal. If there is more, you'll
need to spell it out.

As for performance, you didn't reply to my earlier email on the subject.

> Notably, the proposed patchset
> provides no information about why the proposed implementation was chosen over
> the PaX implementation (note that I'm talking about the actual implementation of
> safe reference counts, not the atomic_t/atomic_unchecked_t division) which as
> I've already mentioned is much more efficient (less bloated and faster) while
> still meeting the security goal.

You again failed to reply to my last email on the subject. The initial
PaX thing was broken as heck, only later did you mention it got fixed. I
told you we could change to that for x86 if it could be proven to be
equivalent.

If you want to expedite matters, provide said proof.

The scheme does not make sense for LL/SC based architectures though, so
its not something that belongs in generic code.

> I'm especially worried that people will be put
> in a position where they need to take performance concerns into account when
> deciding whether to use refcount_t or not.

First show a place where refcounting is performance critical, then we
can see how much effort is required.

> And the patch even still includes
> the "don't allow incrementing a zero refcount" check which AFAICS is bogus from
> a security perspective.

Because use-after-free isn't a security problem, right? Reference
counting semantics are fairly clear that 0 means it is, or is going to
be, free()'ed. How does allowing to increment at that point make any
sense?

> Even if you and Peter disagree with the comments that I and also PaX Team have
> made, the patch must at least explain the design decisions made.

It was constructed as a generic atomic with saturation semantics because
what was said PaX had was broken as hell (note, I have myself never
looked at PaX code and have only seen what was sent me as derived code).
If that later got fixed, or the derived code was buggy or whatever, your
earlier email was the first I heard of that, and that was well after I
wrote refcount_t.

So the design decision was broken vs not-broken.

Also, refcount_t is written using generic primitives (not arch
specific), to avoid arch dependencies and provide a common
implementation to determine semantics. That does not mean architectures
cannot implement their own later on (matching semantics).

Also, I agree GCC does a very poor job generating code from it. But
again, I've not had a report where refcounting is performance critical.
I've also been very busy with other work and haven't spend much if any
time on this since your last email.

If you want something done, contribute.

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

* RE: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-19  9:19   ` Peter Zijlstra
@ 2017-01-19 10:22     ` Reshetova, Elena
  2017-01-19 12:52       ` Peter Zijlstra
  2017-01-19 15:20     ` [kernel-hardening] " David Windsor
  2017-01-19 19:18     ` [kernel-hardening] " Eric Biggers
  2 siblings, 1 reply; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-19 10:22 UTC (permalink / raw)
  To: Peter Zijlstra, Eric Biggers
  Cc: kernel-hardening, keescook, arnd, tglx, mingo, Anvin, H Peter,
	will.deacon, dwindsor, gregkh

> You again failed to reply to my last email on the subject. The initial
> PaX thing was broken as heck, only later did you mention it got fixed. I
> told you we could change to that for x86 if it could be proven to be
> equivalent.

I am confused on what is referred here as a fix.. Do you mean the earlier proposal
to use cmpxchg instead of addl in the x86 assembly code? If yes, that indeed removes
races, but when performance measurements were done, it was dismissed as being too
costly to enforce on atomic by default. 

This had numbers on addl vs. cmpxchg:
http://www.openwall.com/lists/kernel-hardening/2016/10/04/10

Best Regards,
Elena.

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-19 10:22     ` Reshetova, Elena
@ 2017-01-19 12:52       ` Peter Zijlstra
  2017-01-19 14:15         ` Reshetova, Elena
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Zijlstra @ 2017-01-19 12:52 UTC (permalink / raw)
  To: Reshetova, Elena
  Cc: Eric Biggers, kernel-hardening, keescook, arnd, tglx, mingo,
	Anvin, H Peter, will.deacon, dwindsor, gregkh

On Thu, Jan 19, 2017 at 10:22:28AM +0000, Reshetova, Elena wrote:
> > You again failed to reply to my last email on the subject. The initial
> > PaX thing was broken as heck, only later did you mention it got fixed. I
> > told you we could change to that for x86 if it could be proven to be
> > equivalent.
> 
> I am confused on what is referred here as a fix.. 

>From http://lkml.kernel.org/r/20161230010627.GA9882@zzz where Eric said:

"I do see they used to use a slightly different approach that did a decrement
instead of setting the counter to INT_MAX.  And that was clearly racy because
two concurrent increments could circumvent the overflow protection."

> This had numbers on addl vs. cmpxchg:
> http://www.openwall.com/lists/kernel-hardening/2016/10/04/10

http://lkml.kernel.org/r/20161111102913.GE3117@twins.programming.kicks-ass.net

does too, sure cmpxchg is a bit slower uncontended, but I'm not sure we
should worry about that much. And refcounts really should not be heavily
contended, if they are there's design level issues that ought to be
looked at.

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

* RE: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-19 12:52       ` Peter Zijlstra
@ 2017-01-19 14:15         ` Reshetova, Elena
  0 siblings, 0 replies; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-19 14:15 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Eric Biggers, kernel-hardening, keescook, arnd, tglx, mingo,
	Anvin, H Peter, will.deacon, dwindsor, gregkh


> On Thu, Jan 19, 2017 at 10:22:28AM +0000, Reshetova, Elena wrote:
> > > You again failed to reply to my last email on the subject. The initial
> > > PaX thing was broken as heck, only later did you mention it got fixed. I
> > > told you we could change to that for x86 if it could be proven to be
> > > equivalent.
> >
> > I am confused on what is referred here as a fix..
> 
> From http://lkml.kernel.org/r/20161230010627.GA9882@zzz where Eric said:
> 
> "I do see they used to use a slightly different approach that did a decrement
> instead of setting the counter to INT_MAX.  And that was clearly racy because
> two concurrent increments could circumvent the overflow protection."

Oh, now I understand. I somehow missed this in the previous discussion, sorry about this. 
Thanks for explaining!
So, yes, I guess this is a cheap (performance wise) way to fix the race without using cmpxchg, but
I guess this has the same issue you didn't like in it before: it ends up being not atomic when protection kicks in. 
Whenever this a real issue or not, I am not so sure... 

Best Regards,
Elena.

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

* [kernel-hardening] Re: [RFCv2 PATCH 09/18] net: convert from atomic_t to refcount_t
  2017-01-19  7:48         ` Reshetova, Elena
@ 2017-01-19 15:08           ` David Windsor
  0 siblings, 0 replies; 46+ messages in thread
From: David Windsor @ 2017-01-19 15:08 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Anvin,
	H Peter, Peter Zijlstra, Will Deacon, Greg KH, Hans Liljestrand

[-- Attachment #1: Type: text/plain, Size: 1839 bytes --]

It might be my mail client: Gmail won't display the entire patch inline.

On Thursday, January 19, 2017, Reshetova, Elena <elena.reshetova@intel.com>
wrote:
>> On Wed, Jan 18, 2017 at 8:11 PM, Kees Cook <keescook@chromium.org> wrote:
>> > On Wed, Jan 18, 2017 at 10:39 AM, David Windsor <dwindsor@gmail.com>
>> wrote:
>> >> The relevant part of the patch has been cut off, but it appears that
>> >> you've fixed some of the issues we identified earlier as corner cases
>> >> as to reference counting in net/.  In particular, inetpeer.c has its
>> >> own garbage collection system in place which frees shared objects when
>> >> their reference count became -1 (rather than 0).  The proposed
>> >> solution was to do a global +1 on this refcounting scheme, then
>> >> replace unsupported atomic_*() functions with appropriate refcount_*()
>> >> calls.
>> >>
>> >> When submitting this to netdev, it may make sense to separate out
>> >> these changes: first, do a global +1 (while still using atomic_t),
>> >> then convert to refcount_t.  I'm already working on this now, but I
>> >> didn't know if you wanted to follow this approach or not.
>> >
>> > David, if you've got the global +1 patches ready, let's start feeding
>> > those to netdev ASAP. We can convert them to refcount_t more easily
>> > after that.
>> >
>>
>> Alright, let me get them in order and I'll submit them to netdev.  I
>> just wanted to make sure that an alternate approach hadn't been
>> decided upon.
>>
>
> No, we haven't decided on that.
> We had only some +1s, but not for all of it, so if you have a global +1,
then it is even better!
> Then we can drop +1 parts.
>
> And what do you mean by " The relevant part of the patch has been cut off
" ? It is one huge
> patch but I got it in full mailed via list. Do you see it corrupted or?
>
> Best Regards,
> Elena
>

[-- Attachment #2: Type: text/html, Size: 2440 bytes --]

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

* [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-19  9:19   ` Peter Zijlstra
  2017-01-19 10:22     ` Reshetova, Elena
@ 2017-01-19 15:20     ` David Windsor
  2017-01-19 16:00       ` [kernel-hardening] " Reshetova, Elena
  2017-01-19 19:18     ` [kernel-hardening] " Eric Biggers
  2 siblings, 1 reply; 46+ messages in thread
From: David Windsor @ 2017-01-19 15:20 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Eric Biggers, kernel-hardening, keescook, arnd, tglx, mingo,
	h.peter.anvin, will.deacon, gregkh, Elena Reshetova

[-- Attachment #1: Type: text/plain, Size: 4100 bytes --]

On Thursday, January 19, 2017, Peter Zijlstra <peterz@infradead.org> wrote:
> On Wed, Jan 18, 2017 at 01:52:47PM -0800, Eric Biggers wrote:
>> There seems to be a lot of focus on converting things to use refcount_t
but much
>> less focus on providing a refcount_t implementation that actually meets
the
>> performance and security goals of the feature.
>
> And here you go again... :-(
>
> The refcount_t implementation does meet the security goals afaict, it
> has full saturation semantics, which means an overflow bug gets turned
> into a resource leak.
>
> That covers the entirely of the security goal. If there is more, you'll
> need to spell it out.
>
> As for performance, you didn't reply to my earlier email on the subject.
>
>> Notably, the proposed patchset
>> provides no information about why the proposed implementation was chosen
over
>> the PaX implementation (note that I'm talking about the actual
implementation of
>> safe reference counts, not the atomic_t/atomic_unchecked_t division)
which as
>> I've already mentioned is much more efficient (less bloated and faster)
while
>> still meeting the security goal.
>
> You again failed to reply to my last email on the subject. The initial
> PaX thing was broken as heck, only later did you mention it got fixed. I
> told you we could change to that for x86 if it could be proven to be
> equivalent.
>
> If you want to expedite matters, provide said proof.
>
> The scheme does not make sense for LL/SC based architectures though, so
> its not something that belongs in generic code.
>
>> I'm especially worried that people will be put
>> in a position where they need to take performance concerns into account
when
>> deciding whether to use refcount_t or not.
>
> First show a place where refcounting is performance critical, then we
> can see how much effort is required.
>
>> And the patch even still includes
>> the "don't allow incrementing a zero refcount" check which AFAICS is
bogus from
>> a security perspective.
>
> Because use-after-free isn't a security problem, right? Reference
> counting semantics are fairly clear that 0 means it is, or is going to
> be, free()'ed. How does allowing to increment at that point make any
> sense?
>
>> Even if you and Peter disagree with the comments that I and also PaX
Team have
>> made, the patch must at least explain the design decisions made.
>
> It was constructed as a generic atomic with saturation semantics because
> what was said PaX had was broken as hell (note, I have myself never
> looked at PaX code and have only seen what was sent me as derived code).
> If that later got fixed, or the derived code was buggy or whatever, your
> earlier email was the first I heard of that, and that was well after I
> wrote refcount_t.
>
> So the design decision was broken vs not-broken.
>
> Also, refcount_t is written using generic primitives (not arch
> specific), to avoid arch dependencies and provide a common
> implementation to determine semantics. That does not mean architectures
> cannot implement their own later on (matching semantics).
>

I think it's important to emphasize this: the generic refcount_t
implementation you provided is the default, arch-independent
implementation. The original PaX code had a similar system in which
default, arch-independent implementations were provided (defined in
include/asm-generic/atomic*.h, if memory serves). Individual architectures
overrode those definitions with their own, possibly optimized, versions.

Note that figuring out how this system of overridden implementations works
was pretty difficult, so we may want to investigate whether or not there's
an easier way to do what we want, or at least document where/how these
types' definitions are resolved. I have notes on this, and I bet Elena and
Hans do as well.

> Also, I agree GCC does a very poor job generating code from it. But
> again, I've not had a report where refcounting is performance critical.
> I've also been very busy with other work and haven't spend much if any
> time on this since your last email.
>
> If you want something done, contribute.
>

[-- Attachment #2: Type: text/html, Size: 4730 bytes --]

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

* [kernel-hardening] RE: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-19 15:20     ` [kernel-hardening] " David Windsor
@ 2017-01-19 16:00       ` Reshetova, Elena
  0 siblings, 0 replies; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-19 16:00 UTC (permalink / raw)
  To: David Windsor, Peter Zijlstra
  Cc: Eric Biggers, kernel-hardening, keescook, arnd, tglx, mingo,
	Anvin, H Peter, will.deacon, gregkh

On Thursday, January 19, 2017, Peter Zijlstra <peterz@infradead.org> wrote:
> On Wed, Jan 18, 2017 at 01:52:47PM -0800, Eric Biggers wrote:
>> There seems to be a lot of focus on converting things to use refcount_t but much
>> less focus on providing a refcount_t implementation that actually meets the
>> performance and security goals of the feature.
>
> And here you go again... :-(
>
> The refcount_t implementation does meet the security goals afaict, it
> has full saturation semantics, which means an overflow bug gets turned
> into a resource leak.
>
> That covers the entirely of the security goal. If there is more, you'll
> need to spell it out.
>
> As for performance, you didn't reply to my earlier email on the subject.
>
>> Notably, the proposed patchset
>> provides no information about why the proposed implementation was chosen over
>> the PaX implementation (note that I'm talking about the actual implementation of
>> safe reference counts, not the atomic_t/atomic_unchecked_t division) which as
>> I've already mentioned is much more efficient (less bloated and faster) while
>> still meeting the security goal.
>
> You again failed to reply to my last email on the subject. The initial
> PaX thing was broken as heck, only later did you mention it got fixed. I
> told you we could change to that for x86 if it could be proven to be
> equivalent.
>
> If you want to expedite matters, provide said proof.
>
> The scheme does not make sense for LL/SC based architectures though, so
> its not something that belongs in generic code.
>
>> I'm especially worried that people will be put
>> in a position where they need to take performance concerns into account when
>> deciding whether to use refcount_t or not.
>
> First show a place where refcounting is performance critical, then we
> can see how much effort is required.
>
>> And the patch even still includes
>> the "don't allow incrementing a zero refcount" check which AFAICS is bogus from
>> a security perspective.
>
> Because use-after-free isn't a security problem, right? Reference
> counting semantics are fairly clear that 0 means it is, or is going to
> be, free()'ed. How does allowing to increment at that point make any
> sense?
>
>> Even if you and Peter disagree with the comments that I and also PaX Team have
>> made, the patch must at least explain the design decisions made.
>
> It was constructed as a generic atomic with saturation semantics because
> what was said PaX had was broken as hell (note, I have myself never
> looked at PaX code and have only seen what was sent me as derived code).
> If that later got fixed, or the derived code was buggy or whatever, your
> earlier email was the first I heard of that, and that was well after I
> wrote refcount_t.
>
> So the design decision was broken vs not-broken.
>
> Also, refcount_t is written using generic primitives (not arch
> specific), to avoid arch dependencies and provide a common
> implementation to determine semantics. That does not mean architectures
> cannot implement their own later on (matching semantics).
>

>I think it's important to emphasize this: the generic refcount_t implementation you provided is the default, arch-independent implementation. The original PaX code had a similar system in which default, arch-independent implementations were provided >(defined in include/asm-generic/atomic*.h, if memory serves). Individual architectures overrode those definitions with their own, possibly optimized, versions.  

>Note that figuring out how this system of overridden implementations works was pretty difficult, so we may want to investigate whether or not there's an easier way to do what we want, or at least document where/how these types' definitions are >resolved. I have notes on this, and I bet Elena and Hans do as well.

If we go this path, I think it would be easier than before since we need to provide only a small subset of functions. 
Also, the biggest headaches were actually atomic64_t and local_t but since we haven't found any use cases for them for refcount_t,
it is really much easier without.  

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-19  9:19   ` Peter Zijlstra
  2017-01-19 10:22     ` Reshetova, Elena
  2017-01-19 15:20     ` [kernel-hardening] " David Windsor
@ 2017-01-19 19:18     ` Eric Biggers
  2017-01-20  8:36       ` Peter Zijlstra
  2 siblings, 1 reply; 46+ messages in thread
From: Eric Biggers @ 2017-01-19 19:18 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: kernel-hardening, keescook, arnd, tglx, mingo, h.peter.anvin,
	will.deacon, dwindsor, gregkh, Elena Reshetova

On Thu, Jan 19, 2017 at 10:19:52AM +0100, Peter Zijlstra wrote:
> On Wed, Jan 18, 2017 at 01:52:47PM -0800, Eric Biggers wrote:
> > There seems to be a lot of focus on converting things to use refcount_t but much
> > less focus on providing a refcount_t implementation that actually meets the
> > performance and security goals of the feature.
> 
> And here you go again... :-(
> 
> The refcount_t implementation does meet the security goals afaict, it
> has full saturation semantics, which means an overflow bug gets turned
> into a resource leak.
> 
> That covers the entirely of the security goal. If there is more, you'll
> need to spell it out.
> 
> As for performance, you didn't reply to my earlier email on the subject.
> 
> > Notably, the proposed patchset
> > provides no information about why the proposed implementation was chosen over
> > the PaX implementation (note that I'm talking about the actual implementation of
> > safe reference counts, not the atomic_t/atomic_unchecked_t division) which as
> > I've already mentioned is much more efficient (less bloated and faster) while
> > still meeting the security goal.
> 
> You again failed to reply to my last email on the subject. The initial
> PaX thing was broken as heck, only later did you mention it got fixed. I
> told you we could change to that for x86 if it could be proven to be
> equivalent.
> 
> If you want to expedite matters, provide said proof.
> 
> The scheme does not make sense for LL/SC based architectures though, so
> its not something that belongs in generic code.
> 
> > I'm especially worried that people will be put
> > in a position where they need to take performance concerns into account when
> > deciding whether to use refcount_t or not.
> 
> First show a place where refcounting is performance critical, then we
> can see how much effort is required.
> 
> > And the patch even still includes
> > the "don't allow incrementing a zero refcount" check which AFAICS is bogus from
> > a security perspective.
> 
> Because use-after-free isn't a security problem, right? Reference
> counting semantics are fairly clear that 0 means it is, or is going to
> be, free()'ed. How does allowing to increment at that point make any
> sense?
> 
> > Even if you and Peter disagree with the comments that I and also PaX Team have
> > made, the patch must at least explain the design decisions made.
> 
> It was constructed as a generic atomic with saturation semantics because
> what was said PaX had was broken as hell (note, I have myself never
> looked at PaX code and have only seen what was sent me as derived code).
> If that later got fixed, or the derived code was buggy or whatever, your
> earlier email was the first I heard of that, and that was well after I
> wrote refcount_t.
> 
> So the design decision was broken vs not-broken.
> 
> Also, refcount_t is written using generic primitives (not arch
> specific), to avoid arch dependencies and provide a common
> implementation to determine semantics. That does not mean architectures
> cannot implement their own later on (matching semantics).
> 
> Also, I agree GCC does a very poor job generating code from it. But
> again, I've not had a report where refcounting is performance critical.
> I've also been very busy with other work and haven't spend much if any
> time on this since your last email.
> 
> If you want something done, contribute.

First of all if you are going to complain about not replying to emails, much
more important is the fact that you didn't reply to PaX Team, who as I hope
you're aware is the author of the grsecurity/PaX feature this whole thing is
based on, and therefore has far more experience with it than anyone else here
(and yes people really do use grsecurity).  And since PaX Team doesn't usually
contribute to "upstream" discussions, people really should listen when he
does.

This was already covered by both me and PaX Team, but forbidding incrementing a
0 refcount does not provide any real security benefit because it does not
prevent use-after-frees; it only detects them after they have already occurred
and had the opportunity to be exploited.  Of course, it's a nice-to-have for
debugging purposes.  But it's not part of the exploit mitigation and is not
free, so it shouldn't really be on by default.  Again this is supposed to be a
security feature, not a debugging feature.

Also I already explained how the latest PaX solution does not appear to be racy,
at least not in a way that defeats the mitigation.  I am suggesting that this
solution be considered, and it does not help if by your own admission you refuse
to even read the PaX code.  Note that there documentation for PAX_REFCOUNT,
which I strongly suggest that people read (though a couple parts are
out-of-date): https://forums.grsecurity.net/viewtopic.php?f=7&t=4173

With regards to performance and bloat, the important thing is not really
benchmarking of this one feature, but rather the general approach that is taken
with these exploit mitigations.  Checked reference counts is only one potential
mitigation of many.  While it prevents an important class of use-after-free
bugs, the vast majority of bugs that it does not prevent, and there are many
other different kinds of mitigations that can be implemented, each with their
own performance impact.  Take a look at the kinds of things that are in
grsecurity for some examples.  The problem is that the performance cost and code
bloat adds up for all these mitigations, and if they are not implemented
efficiently then we quickly get a point where people start disabling, rejecting,
or patching out mitigations to get their performance back, which defeats the
point.

(I also find it amusing that as soon as I try to contribute, I get accused of
not contributing!  Anyway, Elena already seems to be working on driving the
patches forward, and review is what I have time for now.  And note that this is
already implemented in grsecurity, so in my opinion the lack of code isn't
really the problem here...)

Eric

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-19 19:18     ` [kernel-hardening] " Eric Biggers
@ 2017-01-20  8:36       ` Peter Zijlstra
  2017-01-20  9:20         ` Reshetova, Elena
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Zijlstra @ 2017-01-20  8:36 UTC (permalink / raw)
  To: Eric Biggers
  Cc: kernel-hardening, keescook, arnd, tglx, mingo, h.peter.anvin,
	will.deacon, dwindsor, gregkh, Elena Reshetova

On Thu, Jan 19, 2017 at 11:18:28AM -0800, Eric Biggers wrote:
> First of all if you are going to complain about not replying to emails, much
> more important is the fact that you didn't reply to PaX Team

There are a grand total of exactly 0 emails from PaX team on this
subject in my inbox.

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

* RE: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-20  8:36       ` Peter Zijlstra
@ 2017-01-20  9:20         ` Reshetova, Elena
  2017-01-20 10:23           ` gregkh
  2017-01-20 10:44           ` Solar Designer
  0 siblings, 2 replies; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-20  9:20 UTC (permalink / raw)
  To: Peter Zijlstra, Eric Biggers
  Cc: kernel-hardening, keescook, arnd, tglx, mingo, Anvin, H Peter,
	will.deacon, dwindsor, gregkh

> On Thu, Jan 19, 2017 at 11:18:28AM -0800, Eric Biggers wrote:
> > First of all if you are going to complain about not replying to emails, much
> > more important is the fact that you didn't reply to PaX Team
> 
> There are a grand total of exactly 0 emails from PaX team on this
> subject in my inbox.

Really wonder how it happened that Peter was dropped out of that thread and all other mails were correct.
Anyway, here was the mail:

http://www.openwall.com/lists/kernel-hardening/2017/01/05/19

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-20  9:20         ` Reshetova, Elena
@ 2017-01-20 10:23           ` gregkh
  2017-01-20 10:44           ` Solar Designer
  1 sibling, 0 replies; 46+ messages in thread
From: gregkh @ 2017-01-20 10:23 UTC (permalink / raw)
  To: Reshetova, Elena
  Cc: Peter Zijlstra, Eric Biggers, kernel-hardening, keescook, arnd,
	tglx, mingo, Anvin, H Peter, will.deacon, dwindsor

On Fri, Jan 20, 2017 at 09:20:08AM +0000, Reshetova, Elena wrote:
> > On Thu, Jan 19, 2017 at 11:18:28AM -0800, Eric Biggers wrote:
> > > First of all if you are going to complain about not replying to emails, much
> > > more important is the fact that you didn't reply to PaX Team
> > 
> > There are a grand total of exactly 0 emails from PaX team on this
> > subject in my inbox.
> 
> Really wonder how it happened that Peter was dropped out of that thread and all other mails were correct.
> Anyway, here was the mail:
> 
> http://www.openwall.com/lists/kernel-hardening/2017/01/05/19
> 

Oops, I missed that too, will go respond to it...

thanks,

greg k-h

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-20  9:20         ` Reshetova, Elena
  2017-01-20 10:23           ` gregkh
@ 2017-01-20 10:44           ` Solar Designer
  2017-01-20 17:52             ` Eric Biggers
  1 sibling, 1 reply; 46+ messages in thread
From: Solar Designer @ 2017-01-20 10:44 UTC (permalink / raw)
  To: kernel-hardening

I dropped all CC's since this sub-thread is only relevant to those
receiving this via the kernel-hardening mailing list.

On Fri, Jan 20, 2017 at 09:20:08AM +0000, Reshetova, Elena wrote:
> Really wonder how it happened that Peter was dropped out of that thread and all other mails were correct.
> Anyway, here was the mail:
> 
> http://www.openwall.com/lists/kernel-hardening/2017/01/05/19

I'm afraid the kernel-hardening mailing list setup may be at fault.
On this list, as well as on most others at Openwall, we introduce the
Reply-To header pointing to the list.  This is meant to keep discussions
on the list, avoiding inadvertent off-list responses.  However, this has
a well-known unfortunate side-effect: many MUAs will then only use this
Reply-To address and not the previous message's From address when doing
a reply-to-all.  This will keep everyone from the previous message's CC,
but the From person may be missing from the reply.  In Mutt, after
pressing "g" for group-reply, to keep the From person on the reply one
has to answer "n" to the "Reply to kernel-hardening@lists.openwall.com?
([yes]/no)" question, in which case the reply is also sent to the list,
but via a CC.  This is counter-intuitive.

With this list's practice (inherited from LKML) to CC lots of people and
other relevant lists on almost every posting, and with many people
actively participating in discussions not being subscriber to this very
list, perhaps we should reconsider and drop the forced Reply-To header.

In fact, I've just made this change.  Please let me know if you think I
shouldn't have - that is, that we should reintroduce the forced Reply-To.

Alexander

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

* Re: [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-20 10:44           ` Solar Designer
@ 2017-01-20 17:52             ` Eric Biggers
  0 siblings, 0 replies; 46+ messages in thread
From: Eric Biggers @ 2017-01-20 17:52 UTC (permalink / raw)
  To: Solar Designer; +Cc: kernel-hardening

On Fri, Jan 20, 2017 at 11:44:30AM +0100, Solar Designer wrote:
> I dropped all CC's since this sub-thread is only relevant to those
> receiving this via the kernel-hardening mailing list.
> 
> On Fri, Jan 20, 2017 at 09:20:08AM +0000, Reshetova, Elena wrote:
> > Really wonder how it happened that Peter was dropped out of that thread and all other mails were correct.
> > Anyway, here was the mail:
> > 
> > http://www.openwall.com/lists/kernel-hardening/2017/01/05/19
> 
> I'm afraid the kernel-hardening mailing list setup may be at fault.
> On this list, as well as on most others at Openwall, we introduce the
> Reply-To header pointing to the list.  This is meant to keep discussions
> on the list, avoiding inadvertent off-list responses.  However, this has
> a well-known unfortunate side-effect: many MUAs will then only use this
> Reply-To address and not the previous message's From address when doing
> a reply-to-all.  This will keep everyone from the previous message's CC,
> but the From person may be missing from the reply.  In Mutt, after
> pressing "g" for group-reply, to keep the From person on the reply one
> has to answer "n" to the "Reply to kernel-hardening@lists.openwall.com?
> ([yes]/no)" question, in which case the reply is also sent to the list,
> but via a CC.  This is counter-intuitive.
> 
> With this list's practice (inherited from LKML) to CC lots of people and
> other relevant lists on almost every posting, and with many people
> actively participating in discussions not being subscriber to this very
> list, perhaps we should reconsider and drop the forced Reply-To header.
> 
> In fact, I've just made this change.  Please let me know if you think I
> shouldn't have - that is, that we should reintroduce the forced Reply-To.
> 
> Alexander

Yes that is probably what happened.  In fact it happened to me on a different
thread last month: http://www.openwall.com/lists/kernel-hardening/2016/12/10/8.
I agree with dropping the forced Reply-To, to be consistent with other LKML
mailing lists.  Thanks for fixing it!

Eric

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

* [kernel-hardening] RE: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-18 10:30 ` [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage Greg KH
  2017-01-18 20:06   ` Kees Cook
@ 2017-01-23  7:52   ` Reshetova, Elena
  2017-01-23  8:36     ` [kernel-hardening] " Greg KH
  1 sibling, 1 reply; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-23  7:52 UTC (permalink / raw)
  To: Greg KH, keescook
  Cc: kernel-hardening, arnd, tglx, mingo, Anvin, H Peter, peterz,
	will.deacon, dwindsor

> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Wednesday, January 18, 2017 12:31 PM
> To: Reshetova, Elena <elena.reshetova@intel.com>
> Cc: kernel-hardening@lists.openwall.com; keescook@chromium.org;
> arnd@arndb.de; tglx@linutronix.de; mingo@redhat.com; Anvin, H Peter
> <h.peter.anvin@intel.com>; peterz@infradead.org; will.deacon@arm.com;
> dwindsor@gmail.com
> Subject: Re: [RFCv2 PATCH 00/18] refcount_t API + usage
> 
> On Wed, Jan 18, 2017 at 11:11:29AM +0200, Elena Reshetova wrote:
> > Changes since v1:
> >  - kref INIT fixes are moved to a proper separate commit
> >  - Peter's commits are now properly integrated into series
> >  - various small fixes are incorporated based on testing
> >    results and feedback
> >
> > This patch series is build on top of Peter's Zijlstra patches
> > that provide refcount_t type and API definition.
> > The rest of patches convert various places of kernel subsystems
> > where atomic_t was used for reference counting to new refcount_t type and
> API.
> > By doing this, we make sure that underflows and overflows
> > cannot occur in these places and therefore no use-after-free situation
> > can be created and misused by an attacker.
> 
> Your first 7 patches are fine, and most of them are already in the tip
> tree and getting use in linux-next now.  I'd recommend submitting the
> remaining one(s?) that are not there yet to be included, that will get
> refcount_t into 4.11-rc1.

Ok, so then I assume that I don't have to worry about the first 7 patches and
I just wait for them to show up. 

> 
> Then comes the real work :)
> 
> You will need to break up the remaining patches into "one-per-type" and
> start submitting them to the various submaintainers for inclusion.  

Could you please elaborate more on "one-per-type"? Sorry if the question is
too basic, but I could not find any proper explanations anywhere now. 
If I run get_maintainer.pl, it sometimes produces rather big list (like it was the
case with atomic changes for example) and for a big patch like for example networking
it might not be straightforward to determine how to break it up properly. 

If there any BKMs or generic heuristics that people use in this case? 
Does it help to send it to a general subsystem maintainer and mailing list first
for a look and ask how they prefer it to be broken up?


>You
> can do that once 4.11-rc1 is out.  That's going to be a lot of different
> patches, and your patch-maintaince skills are going to be tested here...
> 
> With those submissions, lots of them will start to trickly into
> linux-next and start to show up in 4.12-rc1.  You'll then need to
> refresh your patchset, drop the ones that were accepted, and do it all
> over again.  If some maintainers are just ignoring you, you'll have to
> go through some other tree for them (I can take the driver ones through
> my driver tree.)
> 
> It's going to be work, but is totally doable.  I recommend setting up a
> separate git or quilt tree that can get included into linux-next and
> kbuild for testing and refreshing as the patches start to flow upstream.

Kees do you have preference on how to do this? Can we setup a builder on our
github tree or is it better to do on your kernel.org tree? If latter, then I guess 
we would need to have rights to manage it all the time.

I would prefer git-managed tree since I feel more familiar with git than quilt.  

> 
> Kernel development isn't always a lot of coding, it's primarily dealing
> with stuff like this, welcome to the club :)

Thanks :)


Best Regards,
Elena.

> 
> hope this helps,
> 
> greg k-h

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

* [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-23  7:52   ` [kernel-hardening] " Reshetova, Elena
@ 2017-01-23  8:36     ` Greg KH
  2017-01-23  8:52       ` [kernel-hardening] " Reshetova, Elena
  0 siblings, 1 reply; 46+ messages in thread
From: Greg KH @ 2017-01-23  8:36 UTC (permalink / raw)
  To: Reshetova, Elena
  Cc: keescook, kernel-hardening, arnd, tglx, mingo, Anvin, H Peter,
	peterz, will.deacon, dwindsor

On Mon, Jan 23, 2017 at 07:52:17AM +0000, Reshetova, Elena wrote:
> > Then comes the real work :)
> > 
> > You will need to break up the remaining patches into "one-per-type" and
> > start submitting them to the various submaintainers for inclusion.  
> 
> Could you please elaborate more on "one-per-type"? Sorry if the question is
> too basic, but I could not find any proper explanations anywhere now. 

One patch per atomic_t variable that you change to refcount_t.

> If I run get_maintainer.pl, it sometimes produces rather big list (like it was the
> case with atomic changes for example) and for a big patch like for example networking
> it might not be straightforward to determine how to break it up properly. 

I doubt that you will have a "touch the whole network stack" patch if
you break it up into one-per-variable, but I don't really know.  See
what it looks like when you are done.

> If there any BKMs or generic heuristics that people use in this case? 

"BKM"?  What's that

> Does it help to send it to a general subsystem maintainer and mailing list first
> for a look and ask how they prefer it to be broken up?

Again, one per variable should be fine.  Then send all of the patches
for a specific subsystem (i.e. wireless drivers) to that list and
maintainer for the subsystem and individual driver authors.  I'm sure
that others at Intel can help you out with this, it should be documented
pretty well somewhere in your internal system :)

good luck!

greg k-h

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

* [kernel-hardening] RE: [RFCv2 PATCH 00/18] refcount_t API + usage
  2017-01-23  8:36     ` [kernel-hardening] " Greg KH
@ 2017-01-23  8:52       ` Reshetova, Elena
  0 siblings, 0 replies; 46+ messages in thread
From: Reshetova, Elena @ 2017-01-23  8:52 UTC (permalink / raw)
  To: Greg KH
  Cc: keescook, kernel-hardening, arnd, tglx, mingo, Anvin, H Peter,
	peterz, will.deacon, dwindsor

> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Monday, January 23, 2017 10:36 AM
> To: Reshetova, Elena <elena.reshetova@intel.com>
> Cc: keescook@chromium.org; kernel-hardening@lists.openwall.com;
> arnd@arndb.de; tglx@linutronix.de; mingo@redhat.com; Anvin, H Peter
> <h.peter.anvin@intel.com>; peterz@infradead.org; will.deacon@arm.com;
> dwindsor@gmail.com
> Subject: Re: [RFCv2 PATCH 00/18] refcount_t API + usage
> 
> On Mon, Jan 23, 2017 at 07:52:17AM +0000, Reshetova, Elena wrote:
> > > Then comes the real work :)
> > >
> > > You will need to break up the remaining patches into "one-per-type" and
> > > start submitting them to the various submaintainers for inclusion.
> >
> > Could you please elaborate more on "one-per-type"? Sorry if the question is
> > too basic, but I could not find any proper explanations anywhere now.
> 
> One patch per atomic_t variable that you change to refcount_t.

Oh, I didn't understand you meant this granularity, yes now it is clear and actually pretty easy
to break down :)

> 
> > If I run get_maintainer.pl, it sometimes produces rather big list (like it was the
> > case with atomic changes for example) and for a big patch like for example
> networking
> > it might not be straightforward to determine how to break it up properly.
> 
> I doubt that you will have a "touch the whole network stack" patch if
> you break it up into one-per-variable, but I don't really know.  See
> what it looks like when you are done.
> 
> > If there any BKMs or generic heuristics that people use in this case?
> 
> "BKM"?  What's that

Sorry, I was thinking it is a general English-speakers acronym (Best Known Method). 

> 
> > Does it help to send it to a general subsystem maintainer and mailing list first
> > for a look and ask how they prefer it to be broken up?
> 
> Again, one per variable should be fine.  Then send all of the patches
> for a specific subsystem (i.e. wireless drivers) to that list and
> maintainer for the subsystem and individual driver authors.  I'm sure
> that others at Intel can help you out with this, it should be documented
> pretty well somewhere in your internal system :)

Sure, this makes sense: I was thinking we need to do smth more clever than this to minimize patches,
but this way it is clear.  

Thank you very much for explaining!

Best Regards,
Elena.

> 
> good luck!
> 
> greg k-h

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

end of thread, other threads:[~2017-01-23  8:52 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-18  9:11 [kernel-hardening] [RFCv2 PATCH 00/18] refcount_t API + usage Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 01/18] kref: Add KREF_INIT() Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 02/18] kref: Add kref_read() Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 03/18] kref: Kill kref_sub() Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 04/18] kref: Use kref_get_unless_zero() more Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 05/18] kref: Implement kref_put_lock() Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 06/18] kref: Avoid more abuse Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 07/18] kref: Implement using refcount_t Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 08/18] kernel, mm: convert from atomic_t to refcount_t Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 09/18] net: " Elena Reshetova
2017-01-18 18:39   ` [kernel-hardening] " David Windsor
2017-01-19  1:11     ` Kees Cook
2017-01-19  3:29       ` David Windsor
2017-01-19  7:48         ` Reshetova, Elena
2017-01-19 15:08           ` David Windsor
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 10/18] fs: " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 11/18] security: " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 12/18] sound: " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 13/18] ipc: covert " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 14/18] tools: convert " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 15/18] block: " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 16/18] drivers: net " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 17/18] drivers: misc drivers " Elena Reshetova
2017-01-18  9:11 ` [kernel-hardening] [RFCv2 PATCH 18/18] drivers: infiniband " Elena Reshetova
2017-01-18 10:30 ` [kernel-hardening] Re: [RFCv2 PATCH 00/18] refcount_t API + usage Greg KH
2017-01-18 20:06   ` Kees Cook
2017-01-18 20:35     ` Greg KH
2017-01-18 20:57       ` Kees Cook
2017-01-19  8:52       ` Peter Zijlstra
2017-01-23  7:52   ` [kernel-hardening] " Reshetova, Elena
2017-01-23  8:36     ` [kernel-hardening] " Greg KH
2017-01-23  8:52       ` [kernel-hardening] " Reshetova, Elena
2017-01-18 21:52 ` [kernel-hardening] " Eric Biggers
2017-01-19  8:31   ` Reshetova, Elena
2017-01-19  9:19   ` Peter Zijlstra
2017-01-19 10:22     ` Reshetova, Elena
2017-01-19 12:52       ` Peter Zijlstra
2017-01-19 14:15         ` Reshetova, Elena
2017-01-19 15:20     ` [kernel-hardening] " David Windsor
2017-01-19 16:00       ` [kernel-hardening] " Reshetova, Elena
2017-01-19 19:18     ` [kernel-hardening] " Eric Biggers
2017-01-20  8:36       ` Peter Zijlstra
2017-01-20  9:20         ` Reshetova, Elena
2017-01-20 10:23           ` gregkh
2017-01-20 10:44           ` Solar Designer
2017-01-20 17:52             ` Eric Biggers

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.