]> Git Repo - linux.git/commitdiff
Merge tag 'xfs-6.9-merge-8' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
authorLinus Torvalds <[email protected]>
Wed, 13 Mar 2024 20:52:24 +0000 (13:52 -0700)
committerLinus Torvalds <[email protected]>
Wed, 13 Mar 2024 20:52:24 +0000 (13:52 -0700)
Pull xfs updates from Chandan Babu:

 - Online repair updates:
    - More ondisk structures being repaired:
        - Inode's mode field by trying to obtain file type value from
          the a directory entry
        - Quota counters
        - Link counts of inodes
        - FS summary counters
        - Support for in-memory btrees has been added to support repair
          of rmap btrees
    - Misc changes:
        - Report corruption of metadata to the health tracking subsystem
        - Enable indirect health reporting when resources are scarce
        - Reduce memory usage while repairing refcount btree
        - Extend "Bmap update" intent item to support atomic extent
          swapping on the realtime device
        - Extend "Bmap update" intent item to support extended attribute
          fork and unwritten extents
    - Code cleanups:
        - Bmap log intent
        - Btree block pointer checking
        - Btree readahead
        - Buffer target
        - Symbolic link code

 - Remove mrlock wrapper around the rwsem

 - Convert all the GFP_NOFS flag usages to use the scoped
   memalloc_nofs_save() API instead of direct calls with the GFP_NOFS

 - Refactor and simplify xfile abstraction. Lower level APIs in shmem.c
   are required to be exported in order to achieve this

 - Skip checking alignment constraints for inode chunk allocations when
   block size is larger than inode chunk size

 - Do not submit delwri buffers collected during log recovery when an
   error has been encountered

 - Fix SEEK_HOLE/DATA for file regions which have active COW extents

 - Fix lock order inversion when executing error handling path during
   shrinking a filesystem

 - Remove duplicate ifdefs

* tag 'xfs-6.9-merge-8' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (183 commits)
  xfs: shrink failure needs to hold AGI buffer
  mm/shmem.c: Use new form of *@param in kernel-doc
  kernel-doc: Add unary operator * to $type_param_ref
  xfs: use kvfree() in xlog_cil_free_logvec()
  xfs: xfs_btree_bload_prep_block() should use __GFP_NOFAIL
  xfs: fix scrub stats file permissions
  xfs: fix log recovery erroring out on refcount recovery failure
  xfs: move symlink target write function to libxfs
  xfs: move remote symlink target read function to libxfs
  xfs: move xfs_symlink_remote.c declarations to xfs_symlink_remote.h
  xfs: xfs_bmap_finish_one should map unwritten extents properly
  xfs: support deferred bmap updates on the attr fork
  xfs: support recovering bmap intent items targetting realtime extents
  xfs: add a realtime flag to the bmap update log redo items
  xfs: add a xattr_entry helper
  xfs: fix xfs_bunmapi to allow unmapping of partial rt extents
  xfs: move xfs_bmap_defer_add to xfs_bmap_item.c
  xfs: reuse xfs_bmap_update_cancel_item
  xfs: add a bi_entry helper
  xfs: remove xfs_trans_set_bmap_flags
  ...

1  2 
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_mount.c
fs/xfs/xfs_super.c
include/linux/swap.h
mm/filemap.c
mm/shmem.c
scripts/kernel-doc

diff --combined fs/xfs/xfs_buf.c
index 01b41fabbe3c7ba89d2f59c6dad15e49dfe781c5,7fc26e64368de25b0da9a8d47ccb22ae6f660c6e..1a18c381127e2183169eaa8280aa620d66340a71
@@@ -21,6 -21,7 +21,7 @@@
  #include "xfs_errortag.h"
  #include "xfs_error.h"
  #include "xfs_ag.h"
+ #include "xfs_buf_mem.h"
  
  struct kmem_cache *xfs_buf_cache;
  
@@@ -60,6 -61,11 +61,11 @@@ xfs_buf_submit
        return __xfs_buf_submit(bp, !(bp->b_flags & XBF_ASYNC));
  }
  
+ static inline bool xfs_buf_is_uncached(struct xfs_buf *bp)
+ {
+       return bp->b_rhash_key == XFS_BUF_DADDR_NULL;
+ }
  static inline int
  xfs_buf_is_vmapped(
        struct xfs_buf  *bp)
@@@ -189,8 -195,8 +195,8 @@@ xfs_buf_get_maps
                return 0;
        }
  
-       bp->b_maps = kmem_zalloc(map_count * sizeof(struct xfs_buf_map),
-                               KM_NOFS);
+       bp->b_maps = kzalloc(map_count * sizeof(struct xfs_buf_map),
+                       GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
        if (!bp->b_maps)
                return -ENOMEM;
        return 0;
@@@ -204,7 -210,7 +210,7 @@@ xfs_buf_free_maps
        struct xfs_buf  *bp)
  {
        if (bp->b_maps != &bp->__b_map) {
-               kmem_free(bp->b_maps);
+               kfree(bp->b_maps);
                bp->b_maps = NULL;
        }
  }
@@@ -222,7 -228,8 +228,8 @@@ _xfs_buf_alloc
        int                     i;
  
        *bpp = NULL;
-       bp = kmem_cache_zalloc(xfs_buf_cache, GFP_NOFS | __GFP_NOFAIL);
+       bp = kmem_cache_zalloc(xfs_buf_cache,
+                       GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
  
        /*
         * We don't want certain flags to appear in b_flags unless they are
@@@ -289,7 -296,7 +296,7 @@@ xfs_buf_free_pages
        mm_account_reclaimed_pages(bp->b_page_count);
  
        if (bp->b_pages != bp->b_page_array)
-               kmem_free(bp->b_pages);
+               kfree(bp->b_pages);
        bp->b_pages = NULL;
        bp->b_flags &= ~_XBF_PAGES;
  }
@@@ -312,10 -319,12 +319,12 @@@ xfs_buf_free
  
        ASSERT(list_empty(&bp->b_lru));
  
-       if (bp->b_flags & _XBF_PAGES)
+       if (xfs_buftarg_is_mem(bp->b_target))
+               xmbuf_unmap_page(bp);
+       else if (bp->b_flags & _XBF_PAGES)
                xfs_buf_free_pages(bp);
        else if (bp->b_flags & _XBF_KMEM)
-               kmem_free(bp->b_addr);
+               kfree(bp->b_addr);
  
        call_rcu(&bp->b_rcu, xfs_buf_free_callback);
  }
@@@ -325,21 -334,21 +334,21 @@@ xfs_buf_alloc_kmem
        struct xfs_buf  *bp,
        xfs_buf_flags_t flags)
  {
-       xfs_km_flags_t  kmflag_mask = KM_NOFS;
+       gfp_t           gfp_mask = GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL;
        size_t          size = BBTOB(bp->b_length);
  
        /* Assure zeroed buffer for non-read cases. */
        if (!(flags & XBF_READ))
-               kmflag_mask |= KM_ZERO;
+               gfp_mask |= __GFP_ZERO;
  
-       bp->b_addr = kmem_alloc(size, kmflag_mask);
+       bp->b_addr = kmalloc(size, gfp_mask);
        if (!bp->b_addr)
                return -ENOMEM;
  
        if (((unsigned long)(bp->b_addr + size - 1) & PAGE_MASK) !=
            ((unsigned long)bp->b_addr & PAGE_MASK)) {
                /* b_addr spans two pages - use alloc_page instead */
-               kmem_free(bp->b_addr);
+               kfree(bp->b_addr);
                bp->b_addr = NULL;
                return -ENOMEM;
        }
@@@ -356,13 -365,11 +365,11 @@@ xfs_buf_alloc_pages
        struct xfs_buf  *bp,
        xfs_buf_flags_t flags)
  {
-       gfp_t           gfp_mask = __GFP_NOWARN;
+       gfp_t           gfp_mask = GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOWARN;
        long            filled = 0;
  
        if (flags & XBF_READ_AHEAD)
                gfp_mask |= __GFP_NORETRY;
-       else
-               gfp_mask |= GFP_NOFS;
  
        /* Make sure that we have a page list */
        bp->b_page_count = DIV_ROUND_UP(BBTOB(bp->b_length), PAGE_SIZE);
@@@ -429,11 -436,18 +436,18 @@@ _xfs_buf_map_pages
  
                /*
                 * vm_map_ram() will allocate auxiliary structures (e.g.
-                * pagetables) with GFP_KERNEL, yet we are likely to be under
-                * GFP_NOFS context here. Hence we need to tell memory reclaim
-                * that we are in such a context via PF_MEMALLOC_NOFS to prevent
-                * memory reclaim re-entering the filesystem here and
-                * potentially deadlocking.
+                * pagetables) with GFP_KERNEL, yet we often under a scoped nofs
+                * context here. Mixing GFP_KERNEL with GFP_NOFS allocations
+                * from the same call site that can be run from both above and
+                * below memory reclaim causes lockdep false positives. Hence we
+                * always need to force this allocation to nofs context because
+                * we can't pass __GFP_NOLOCKDEP down to auxillary structures to
+                * prevent false positive lockdep reports.
+                *
+                * XXX(dgc): I think dquot reclaim is the only place we can get
+                * to this function from memory reclaim context now. If we fix
+                * that like we've fixed inode reclaim to avoid writeback from
+                * reclaim, this nofs wrapping can go away.
                 */
                nofs_flag = memalloc_nofs_save();
                do {
@@@ -499,18 -513,18 +513,18 @@@ static const struct rhashtable_params x
  };
  
  int
- xfs_buf_hash_init(
-       struct xfs_perag        *pag)
+ xfs_buf_cache_init(
+       struct xfs_buf_cache    *bch)
  {
-       spin_lock_init(&pag->pag_buf_lock);
-       return rhashtable_init(&pag->pag_buf_hash, &xfs_buf_hash_params);
+       spin_lock_init(&bch->bc_lock);
+       return rhashtable_init(&bch->bc_hash, &xfs_buf_hash_params);
  }
  
  void
- xfs_buf_hash_destroy(
-       struct xfs_perag        *pag)
+ xfs_buf_cache_destroy(
+       struct xfs_buf_cache    *bch)
  {
-       rhashtable_destroy(&pag->pag_buf_hash);
+       rhashtable_destroy(&bch->bc_hash);
  }
  
  static int
@@@ -573,7 -587,7 +587,7 @@@ xfs_buf_find_lock
  
  static inline int
  xfs_buf_lookup(
-       struct xfs_perag        *pag,
+       struct xfs_buf_cache    *bch,
        struct xfs_buf_map      *map,
        xfs_buf_flags_t         flags,
        struct xfs_buf          **bpp)
        int                     error;
  
        rcu_read_lock();
-       bp = rhashtable_lookup(&pag->pag_buf_hash, map, xfs_buf_hash_params);
+       bp = rhashtable_lookup(&bch->bc_hash, map, xfs_buf_hash_params);
        if (!bp || !atomic_inc_not_zero(&bp->b_hold)) {
                rcu_read_unlock();
                return -ENOENT;
  static int
  xfs_buf_find_insert(
        struct xfs_buftarg      *btp,
+       struct xfs_buf_cache    *bch,
        struct xfs_perag        *pag,
        struct xfs_buf_map      *cmap,
        struct xfs_buf_map      *map,
        if (error)
                goto out_drop_pag;
  
-       /*
-        * For buffers that fit entirely within a single page, first attempt to
-        * allocate the memory from the heap to minimise memory usage. If we
-        * can't get heap memory for these small buffers, we fall back to using
-        * the page allocator.
-        */
-       if (BBTOB(new_bp->b_length) >= PAGE_SIZE ||
-           xfs_buf_alloc_kmem(new_bp, flags) < 0) {
+       if (xfs_buftarg_is_mem(new_bp->b_target)) {
+               error = xmbuf_map_page(new_bp);
+       } else if (BBTOB(new_bp->b_length) >= PAGE_SIZE ||
+                  xfs_buf_alloc_kmem(new_bp, flags) < 0) {
+               /*
+                * For buffers that fit entirely within a single page, first
+                * attempt to allocate the memory from the heap to minimise
+                * memory usage. If we can't get heap memory for these small
+                * buffers, we fall back to using the page allocator.
+                */
                error = xfs_buf_alloc_pages(new_bp, flags);
-               if (error)
-                       goto out_free_buf;
        }
+       if (error)
+               goto out_free_buf;
  
-       spin_lock(&pag->pag_buf_lock);
-       bp = rhashtable_lookup_get_insert_fast(&pag->pag_buf_hash,
+       spin_lock(&bch->bc_lock);
+       bp = rhashtable_lookup_get_insert_fast(&bch->bc_hash,
                        &new_bp->b_rhash_head, xfs_buf_hash_params);
        if (IS_ERR(bp)) {
                error = PTR_ERR(bp);
-               spin_unlock(&pag->pag_buf_lock);
+               spin_unlock(&bch->bc_lock);
                goto out_free_buf;
        }
        if (bp) {
                /* found an existing buffer */
                atomic_inc(&bp->b_hold);
-               spin_unlock(&pag->pag_buf_lock);
+               spin_unlock(&bch->bc_lock);
                error = xfs_buf_find_lock(bp, flags);
                if (error)
                        xfs_buf_rele(bp);
  
        /* The new buffer keeps the perag reference until it is freed. */
        new_bp->b_pag = pag;
-       spin_unlock(&pag->pag_buf_lock);
+       spin_unlock(&bch->bc_lock);
        *bpp = new_bp;
        return 0;
  
  out_free_buf:
        xfs_buf_free(new_bp);
  out_drop_pag:
-       xfs_perag_put(pag);
+       if (pag)
+               xfs_perag_put(pag);
        return error;
  }
  
+ static inline struct xfs_perag *
+ xfs_buftarg_get_pag(
+       struct xfs_buftarg              *btp,
+       const struct xfs_buf_map        *map)
+ {
+       struct xfs_mount                *mp = btp->bt_mount;
+       if (xfs_buftarg_is_mem(btp))
+               return NULL;
+       return xfs_perag_get(mp, xfs_daddr_to_agno(mp, map->bm_bn));
+ }
+ static inline struct xfs_buf_cache *
+ xfs_buftarg_buf_cache(
+       struct xfs_buftarg              *btp,
+       struct xfs_perag                *pag)
+ {
+       if (pag)
+               return &pag->pag_bcache;
+       return btp->bt_cache;
+ }
  /*
   * Assembles a buffer covering the specified range. The code is optimised for
   * cache hits, as metadata intensive workloads will see 3 orders of magnitude
@@@ -681,6 -721,7 +721,7 @@@ xfs_buf_get_map
        xfs_buf_flags_t         flags,
        struct xfs_buf          **bpp)
  {
+       struct xfs_buf_cache    *bch;
        struct xfs_perag        *pag;
        struct xfs_buf          *bp = NULL;
        struct xfs_buf_map      cmap = { .bm_bn = map[0].bm_bn };
        if (error)
                return error;
  
-       pag = xfs_perag_get(btp->bt_mount,
-                           xfs_daddr_to_agno(btp->bt_mount, cmap.bm_bn));
+       pag = xfs_buftarg_get_pag(btp, &cmap);
+       bch = xfs_buftarg_buf_cache(btp, pag);
  
-       error = xfs_buf_lookup(pag, &cmap, flags, &bp);
+       error = xfs_buf_lookup(bch, &cmap, flags, &bp);
        if (error && error != -ENOENT)
                goto out_put_perag;
  
                        goto out_put_perag;
  
                /* xfs_buf_find_insert() consumes the perag reference. */
-               error = xfs_buf_find_insert(btp, pag, &cmap, map, nmaps,
+               error = xfs_buf_find_insert(btp, bch, pag, &cmap, map, nmaps,
                                flags, &bp);
                if (error)
                        return error;
        } else {
                XFS_STATS_INC(btp->bt_mount, xb_get_locked);
-               xfs_perag_put(pag);
+               if (pag)
+                       xfs_perag_put(pag);
        }
  
        /* We do not hold a perag reference anymore. */
        return 0;
  
  out_put_perag:
-       xfs_perag_put(pag);
+       if (pag)
+               xfs_perag_put(pag);
        return error;
  }
  
@@@ -892,6 -935,13 +935,13 @@@ xfs_buf_readahead_map
  {
        struct xfs_buf          *bp;
  
+       /*
+        * Currently we don't have a good means or justification for performing
+        * xmbuf_map_page asynchronously, so we don't do readahead.
+        */
+       if (xfs_buftarg_is_mem(target))
+               return;
        xfs_buf_read_map(target, map, nmaps,
                     XBF_TRYLOCK | XBF_ASYNC | XBF_READ_AHEAD, &bp, ops,
                     __this_address);
@@@ -957,7 -1007,10 +1007,10 @@@ xfs_buf_get_uncached
        if (error)
                return error;
  
-       error = xfs_buf_alloc_pages(bp, flags);
+       if (xfs_buftarg_is_mem(bp->b_target))
+               error = xmbuf_map_page(bp);
+       else
+               error = xfs_buf_alloc_pages(bp, flags);
        if (error)
                goto fail_free_buf;
  
@@@ -990,29 -1043,29 +1043,29 @@@ xfs_buf_hold
        atomic_inc(&bp->b_hold);
  }
  
- /*
-  * Release a hold on the specified buffer. If the hold count is 1, the buffer is
-  * placed on LRU or freed (depending on b_lru_ref).
-  */
- void
- xfs_buf_rele(
+ static void
+ xfs_buf_rele_uncached(
+       struct xfs_buf          *bp)
+ {
+       ASSERT(list_empty(&bp->b_lru));
+       if (atomic_dec_and_test(&bp->b_hold)) {
+               xfs_buf_ioacct_dec(bp);
+               xfs_buf_free(bp);
+       }
+ }
+ static void
+ xfs_buf_rele_cached(
        struct xfs_buf          *bp)
  {
+       struct xfs_buftarg      *btp = bp->b_target;
        struct xfs_perag        *pag = bp->b_pag;
+       struct xfs_buf_cache    *bch = xfs_buftarg_buf_cache(btp, pag);
        bool                    release;
        bool                    freebuf = false;
  
        trace_xfs_buf_rele(bp, _RET_IP_);
  
-       if (!pag) {
-               ASSERT(list_empty(&bp->b_lru));
-               if (atomic_dec_and_test(&bp->b_hold)) {
-                       xfs_buf_ioacct_dec(bp);
-                       xfs_buf_free(bp);
-               }
-               return;
-       }
        ASSERT(atomic_read(&bp->b_hold) > 0);
  
        /*
         * leading to a use-after-free scenario.
         */
        spin_lock(&bp->b_lock);
-       release = atomic_dec_and_lock(&bp->b_hold, &pag->pag_buf_lock);
+       release = atomic_dec_and_lock(&bp->b_hold, &bch->bc_lock);
        if (!release) {
                /*
                 * Drop the in-flight state if the buffer is already on the LRU
                 * buffer for the LRU and clear the (now stale) dispose list
                 * state flag
                 */
-               if (list_lru_add_obj(&bp->b_target->bt_lru, &bp->b_lru)) {
+               if (list_lru_add_obj(&btp->bt_lru, &bp->b_lru)) {
                        bp->b_state &= ~XFS_BSTATE_DISPOSE;
                        atomic_inc(&bp->b_hold);
                }
-               spin_unlock(&pag->pag_buf_lock);
+               spin_unlock(&bch->bc_lock);
        } else {
                /*
                 * most of the time buffers will already be removed from the
                 * was on was the disposal list
                 */
                if (!(bp->b_state & XFS_BSTATE_DISPOSE)) {
-                       list_lru_del_obj(&bp->b_target->bt_lru, &bp->b_lru);
+                       list_lru_del_obj(&btp->bt_lru, &bp->b_lru);
                } else {
                        ASSERT(list_empty(&bp->b_lru));
                }
  
                ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
-               rhashtable_remove_fast(&pag->pag_buf_hash, &bp->b_rhash_head,
-                                      xfs_buf_hash_params);
-               spin_unlock(&pag->pag_buf_lock);
-               xfs_perag_put(pag);
+               rhashtable_remove_fast(&bch->bc_hash, &bp->b_rhash_head,
+                               xfs_buf_hash_params);
+               spin_unlock(&bch->bc_lock);
+               if (pag)
+                       xfs_perag_put(pag);
                freebuf = true;
        }
  
@@@ -1080,6 -1134,19 +1134,19 @@@ out_unlock
                xfs_buf_free(bp);
  }
  
+ /*
+  * Release a hold on the specified buffer.
+  */
+ void
+ xfs_buf_rele(
+       struct xfs_buf          *bp)
+ {
+       trace_xfs_buf_rele(bp, _RET_IP_);
+       if (xfs_buf_is_uncached(bp))
+               xfs_buf_rele_uncached(bp);
+       else
+               xfs_buf_rele_cached(bp);
+ }
  
  /*
   *    Lock a buffer object, if it is not already locked.
@@@ -1585,6 -1652,12 +1652,12 @@@ _xfs_buf_ioapply
        /* we only use the buffer cache for meta-data */
        op |= REQ_META;
  
+       /* in-memory targets are directly mapped, no IO required. */
+       if (xfs_buftarg_is_mem(bp->b_target)) {
+               xfs_buf_ioend(bp);
+               return;
+       }
        /*
         * Walk all the vectors issuing IO on them. Set up the initial offset
         * into the buffer and the desired IO size before we start -
@@@ -1940,25 -2013,30 +2013,30 @@@ xfs_buftarg_shrink_count
  }
  
  void
- xfs_free_buftarg(
+ xfs_destroy_buftarg(
        struct xfs_buftarg      *btp)
  {
        shrinker_free(btp->bt_shrinker);
        ASSERT(percpu_counter_sum(&btp->bt_io_count) == 0);
        percpu_counter_destroy(&btp->bt_io_count);
        list_lru_destroy(&btp->bt_lru);
+ }
  
+ void
+ xfs_free_buftarg(
+       struct xfs_buftarg      *btp)
+ {
+       xfs_destroy_buftarg(btp);
        fs_put_dax(btp->bt_daxdev, btp->bt_mount);
        /* the main block device is closed by kill_block_super */
        if (btp->bt_bdev != btp->bt_mount->m_super->s_bdev)
 -              bdev_release(btp->bt_bdev_handle);
 +              fput(btp->bt_bdev_file);
-       kmem_free(btp);
+       kfree(btp);
  }
  
  int
  xfs_setsize_buftarg(
-       xfs_buftarg_t           *btp,
+       struct xfs_buftarg      *btp,
        unsigned int            sectorsize)
  {
        /* Set up metadata sector size info */
                return -EINVAL;
        }
  
-       /* Set up device logical sector size mask */
-       btp->bt_logical_sectorsize = bdev_logical_block_size(btp->bt_bdev);
-       btp->bt_logical_sectormask = bdev_logical_block_size(btp->bt_bdev) - 1;
        return 0;
  }
  
- /*
-  * When allocating the initial buffer target we have not yet
-  * read in the superblock, so don't know what sized sectors
-  * are being used at this early stage.  Play safe.
-  */
- STATIC int
- xfs_setsize_buftarg_early(
-       xfs_buftarg_t           *btp)
+ int
+ xfs_init_buftarg(
+       struct xfs_buftarg              *btp,
+       size_t                          logical_sectorsize,
+       const char                      *descr)
  {
-       return xfs_setsize_buftarg(btp, bdev_logical_block_size(btp->bt_bdev));
+       /* Set up device logical sector size mask */
+       btp->bt_logical_sectorsize = logical_sectorsize;
+       btp->bt_logical_sectormask = logical_sectorsize - 1;
+       /*
+        * Buffer IO error rate limiting. Limit it to no more than 10 messages
+        * per 30 seconds so as to not spam logs too much on repeated errors.
+        */
+       ratelimit_state_init(&btp->bt_ioerror_rl, 30 * HZ,
+                            DEFAULT_RATELIMIT_BURST);
+       if (list_lru_init(&btp->bt_lru))
+               return -ENOMEM;
+       if (percpu_counter_init(&btp->bt_io_count, 0, GFP_KERNEL))
+               goto out_destroy_lru;
+       btp->bt_shrinker =
+               shrinker_alloc(SHRINKER_NUMA_AWARE, "xfs-buf:%s", descr);
+       if (!btp->bt_shrinker)
+               goto out_destroy_io_count;
+       btp->bt_shrinker->count_objects = xfs_buftarg_shrink_count;
+       btp->bt_shrinker->scan_objects = xfs_buftarg_shrink_scan;
+       btp->bt_shrinker->private_data = btp;
+       shrinker_register(btp->bt_shrinker);
+       return 0;
+ out_destroy_io_count:
+       percpu_counter_destroy(&btp->bt_io_count);
+ out_destroy_lru:
+       list_lru_destroy(&btp->bt_lru);
+       return -ENOMEM;
  }
  
  struct xfs_buftarg *
  xfs_alloc_buftarg(
        struct xfs_mount        *mp,
 -      struct bdev_handle      *bdev_handle)
 +      struct file             *bdev_file)
  {
-       xfs_buftarg_t           *btp;
+       struct xfs_buftarg      *btp;
        const struct dax_holder_operations *ops = NULL;
  
  #if defined(CONFIG_FS_DAX) && defined(CONFIG_MEMORY_FAILURE)
        ops = &xfs_dax_holder_operations;
  #endif
-       btp = kmem_zalloc(sizeof(*btp), KM_NOFS);
+       btp = kzalloc(sizeof(*btp), GFP_KERNEL | __GFP_NOFAIL);
  
        btp->bt_mount = mp;
 -      btp->bt_bdev_handle = bdev_handle;
 -      btp->bt_dev = bdev_handle->bdev->bd_dev;
 -      btp->bt_bdev = bdev_handle->bdev;
 +      btp->bt_bdev_file = bdev_file;
 +      btp->bt_bdev = file_bdev(bdev_file);
 +      btp->bt_dev = btp->bt_bdev->bd_dev;
        btp->bt_daxdev = fs_dax_get_by_bdev(btp->bt_bdev, &btp->bt_dax_part_off,
                                            mp, ops);
  
        /*
-        * Buffer IO error rate limiting. Limit it to no more than 10 messages
-        * per 30 seconds so as to not spam logs too much on repeated errors.
+        * When allocating the buftargs we have not yet read the super block and
+        * thus don't know the file system sector size yet.
         */
-       ratelimit_state_init(&btp->bt_ioerror_rl, 30 * HZ,
-                            DEFAULT_RATELIMIT_BURST);
-       if (xfs_setsize_buftarg_early(btp))
+       if (xfs_setsize_buftarg(btp, bdev_logical_block_size(btp->bt_bdev)))
                goto error_free;
-       if (list_lru_init(&btp->bt_lru))
+       if (xfs_init_buftarg(btp, bdev_logical_block_size(btp->bt_bdev),
+                       mp->m_super->s_id))
                goto error_free;
  
-       if (percpu_counter_init(&btp->bt_io_count, 0, GFP_KERNEL))
-               goto error_lru;
-       btp->bt_shrinker = shrinker_alloc(SHRINKER_NUMA_AWARE, "xfs-buf:%s",
-                                         mp->m_super->s_id);
-       if (!btp->bt_shrinker)
-               goto error_pcpu;
-       btp->bt_shrinker->count_objects = xfs_buftarg_shrink_count;
-       btp->bt_shrinker->scan_objects = xfs_buftarg_shrink_scan;
-       btp->bt_shrinker->private_data = btp;
-       shrinker_register(btp->bt_shrinker);
        return btp;
  
- error_pcpu:
-       percpu_counter_destroy(&btp->bt_io_count);
- error_lru:
-       list_lru_destroy(&btp->bt_lru);
  error_free:
-       kmem_free(btp);
+       kfree(btp);
        return NULL;
  }
  
diff --combined fs/xfs/xfs_buf.h
index 304e858d04fb3cfca71d4378f2878293f7462d8b,73249abca968e5ae9923c34d13a4712018a72ace..b1580644501fb079d1a719226fce4ccaf23c491f
@@@ -83,6 -83,14 +83,14 @@@ typedef unsigned int xfs_buf_flags_t
  #define XFS_BSTATE_DISPOSE     (1 << 0)       /* buffer being discarded */
  #define XFS_BSTATE_IN_FLIGHT   (1 << 1)       /* I/O in flight */
  
+ struct xfs_buf_cache {
+       spinlock_t              bc_lock;
+       struct rhashtable       bc_hash;
+ };
+ int xfs_buf_cache_init(struct xfs_buf_cache *bch);
+ void xfs_buf_cache_destroy(struct xfs_buf_cache *bch);
  /*
   * The xfs_buftarg contains 2 notions of "sector size" -
   *
   * The latter is derived from the underlying device, and controls direct IO
   * alignment constraints.
   */
typedef struct xfs_buftarg {
+ struct xfs_buftarg {
        dev_t                   bt_dev;
 -      struct bdev_handle      *bt_bdev_handle;
 +      struct file             *bt_bdev_file;
        struct block_device     *bt_bdev;
        struct dax_device       *bt_daxdev;
+       struct file             *bt_file;
        u64                     bt_dax_part_off;
        struct xfs_mount        *bt_mount;
        unsigned int            bt_meta_sectorsize;
  
        struct percpu_counter   bt_io_count;
        struct ratelimit_state  bt_ioerror_rl;
- } xfs_buftarg_t;
+       /* built-in cache, if we're not using the perag one */
+       struct xfs_buf_cache    bt_cache[];
+ };
  
  #define XB_PAGES      2
  
@@@ -366,7 -378,7 +378,7 @@@ xfs_buf_update_cksum(struct xfs_buf *bp
   *    Handling of buftargs.
   */
  struct xfs_buftarg *xfs_alloc_buftarg(struct xfs_mount *mp,
 -              struct bdev_handle *bdev_handle);
 +              struct file *bdev_file);
  extern void xfs_free_buftarg(struct xfs_buftarg *);
  extern void xfs_buftarg_wait(struct xfs_buftarg *);
  extern void xfs_buftarg_drain(struct xfs_buftarg *);
@@@ -379,4 -391,9 +391,9 @@@ int xfs_buf_reverify(struct xfs_buf *bp
  bool xfs_verify_magic(struct xfs_buf *bp, __be32 dmagic);
  bool xfs_verify_magic16(struct xfs_buf *bp, __be16 dmagic);
  
+ /* for xfs_buf_mem.c only: */
+ int xfs_init_buftarg(struct xfs_buftarg *btp, size_t logical_sectorsize,
+               const char *descr);
+ void xfs_destroy_buftarg(struct xfs_buftarg *btp);
  #endif        /* __XFS_BUF_H__ */
diff --combined fs/xfs/xfs_mount.c
index 57fa21ad79124784d205f1313db461acda2546b1,7328034d42ed8dacb2dedfb34b7da43c20fed8b9..df370eb5dc15e13ac2d2a32ed2f2e73d1ba858ae
@@@ -45,7 -45,7 +45,7 @@@ xfs_uuid_table_free(void
  {
        if (xfs_uuid_table_size == 0)
                return;
-       kmem_free(xfs_uuid_table);
+       kfree(xfs_uuid_table);
        xfs_uuid_table = NULL;
        xfs_uuid_table_size = 0;
  }
@@@ -62,7 -62,7 +62,7 @@@ xfs_uuid_mount
        int                     hole, i;
  
        /* Publish UUID in struct super_block */
 -      uuid_copy(&mp->m_super->s_uuid, uuid);
 +      super_set_uuid(mp->m_super, uuid->b, sizeof(*uuid));
  
        if (xfs_has_nouuid(mp))
                return 0;
@@@ -706,8 -706,6 +706,8 @@@ xfs_mountfs
        /* enable fail_at_unmount as default */
        mp->m_fail_unmount = true;
  
 +      super_set_sysfs_name_id(mp->m_super);
 +
        error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype,
                               NULL, mp->m_super->s_id);
        if (error)
diff --combined fs/xfs/xfs_super.c
index 59c8c0541bdd309810294484b15ee02d40b5698d,6828c48b15e9bdc42894b1208988883c035175b1..c21f10ab0f5dbef4051b6bef01eb64c77247e056
@@@ -44,6 -44,7 +44,7 @@@
  #include "xfs_dahash_test.h"
  #include "xfs_rtbitmap.h"
  #include "scrub/stats.h"
+ #include "scrub/rcbag_btree.h"
  
  #include <linux/magic.h>
  #include <linux/fs_context.h>
@@@ -350,6 -351,7 +351,6 @@@ xfs_setup_dax_always
                return -EINVAL;
        }
  
 -      xfs_warn(mp, "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
        return 0;
  
  disable_dax:
@@@ -361,16 -363,16 +362,16 @@@ STATIC in
  xfs_blkdev_get(
        xfs_mount_t             *mp,
        const char              *name,
 -      struct bdev_handle      **handlep)
 +      struct file             **bdev_filep)
  {
        int                     error = 0;
  
 -      *handlep = bdev_open_by_path(name,
 +      *bdev_filep = bdev_file_open_by_path(name,
                BLK_OPEN_READ | BLK_OPEN_WRITE | BLK_OPEN_RESTRICT_WRITES,
                mp->m_super, &fs_holder_ops);
 -      if (IS_ERR(*handlep)) {
 -              error = PTR_ERR(*handlep);
 -              *handlep = NULL;
 +      if (IS_ERR(*bdev_filep)) {
 +              error = PTR_ERR(*bdev_filep);
 +              *bdev_filep = NULL;
                xfs_warn(mp, "Invalid device [%s], error=%d", name, error);
        }
  
@@@ -435,26 -437,26 +436,26 @@@ xfs_open_devices
  {
        struct super_block      *sb = mp->m_super;
        struct block_device     *ddev = sb->s_bdev;
 -      struct bdev_handle      *logdev_handle = NULL, *rtdev_handle = NULL;
 +      struct file             *logdev_file = NULL, *rtdev_file = NULL;
        int                     error;
  
        /*
         * Open real time and log devices - order is important.
         */
        if (mp->m_logname) {
 -              error = xfs_blkdev_get(mp, mp->m_logname, &logdev_handle);
 +              error = xfs_blkdev_get(mp, mp->m_logname, &logdev_file);
                if (error)
                        return error;
        }
  
        if (mp->m_rtname) {
 -              error = xfs_blkdev_get(mp, mp->m_rtname, &rtdev_handle);
 +              error = xfs_blkdev_get(mp, mp->m_rtname, &rtdev_file);
                if (error)
                        goto out_close_logdev;
  
 -              if (rtdev_handle->bdev == ddev ||
 -                  (logdev_handle &&
 -                   rtdev_handle->bdev == logdev_handle->bdev)) {
 +              if (file_bdev(rtdev_file) == ddev ||
 +                  (logdev_file &&
 +                   file_bdev(rtdev_file) == file_bdev(logdev_file))) {
                        xfs_warn(mp,
        "Cannot mount filesystem with identical rtdev and ddev/logdev.");
                        error = -EINVAL;
         * Setup xfs_mount buffer target pointers
         */
        error = -ENOMEM;
 -      mp->m_ddev_targp = xfs_alloc_buftarg(mp, sb->s_bdev_handle);
 +      mp->m_ddev_targp = xfs_alloc_buftarg(mp, sb->s_bdev_file);
        if (!mp->m_ddev_targp)
                goto out_close_rtdev;
  
 -      if (rtdev_handle) {
 -              mp->m_rtdev_targp = xfs_alloc_buftarg(mp, rtdev_handle);
 +      if (rtdev_file) {
 +              mp->m_rtdev_targp = xfs_alloc_buftarg(mp, rtdev_file);
                if (!mp->m_rtdev_targp)
                        goto out_free_ddev_targ;
        }
  
 -      if (logdev_handle && logdev_handle->bdev != ddev) {
 -              mp->m_logdev_targp = xfs_alloc_buftarg(mp, logdev_handle);
 +      if (logdev_file && file_bdev(logdev_file) != ddev) {
 +              mp->m_logdev_targp = xfs_alloc_buftarg(mp, logdev_file);
                if (!mp->m_logdev_targp)
                        goto out_free_rtdev_targ;
        } else {
                mp->m_logdev_targp = mp->m_ddev_targp;
                /* Handle won't be used, drop it */
 -              if (logdev_handle)
 -                      bdev_release(logdev_handle);
 +              if (logdev_file)
 +                      fput(logdev_file);
        }
  
        return 0;
   out_free_ddev_targ:
        xfs_free_buftarg(mp->m_ddev_targp);
   out_close_rtdev:
 -       if (rtdev_handle)
 -              bdev_release(rtdev_handle);
 +       if (rtdev_file)
 +              fput(rtdev_file);
   out_close_logdev:
 -      if (logdev_handle)
 -              bdev_release(logdev_handle);
 +      if (logdev_file)
 +              fput(logdev_file);
        return error;
  }
  
@@@ -715,9 -717,7 +716,7 @@@ xfs_fs_inode_init_once
        /* xfs inode */
        atomic_set(&ip->i_pincount, 0);
        spin_lock_init(&ip->i_flags_lock);
-       mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
-                    "xfsino", ip->i_ino);
+       init_rwsem(&ip->i_lock);
  }
  
  /*
@@@ -760,7 -760,7 +759,7 @@@ xfs_mount_free
        debugfs_remove(mp->m_debugfs);
        kfree(mp->m_rtname);
        kfree(mp->m_logname);
-       kmem_free(mp);
+       kfree(mp);
  }
  
  STATIC int
@@@ -1986,7 -1986,7 +1985,7 @@@ static int xfs_init_fs_context
  {
        struct xfs_mount        *mp;
  
-       mp = kmem_alloc(sizeof(struct xfs_mount), KM_ZERO);
+       mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL | __GFP_NOFAIL);
        if (!mp)
                return -ENOMEM;
  
        mp->m_logbsize = -1;
        mp->m_allocsize_log = 16; /* 64k */
  
+       xfs_hooks_init(&mp->m_dir_update_hooks);
        fc->s_fs_info = mp;
        fc->ops = &xfs_context_ops;
  
@@@ -2043,7 -2045,8 +2044,7 @@@ xfs_init_caches(void
  
        xfs_buf_cache = kmem_cache_create("xfs_buf", sizeof(struct xfs_buf), 0,
                                         SLAB_HWCACHE_ALIGN |
 -                                       SLAB_RECLAIM_ACCOUNT |
 -                                       SLAB_MEM_SPREAD,
 +                                       SLAB_RECLAIM_ACCOUNT,
                                         NULL);
        if (!xfs_buf_cache)
                goto out;
        if (error)
                goto out_destroy_log_ticket_cache;
  
-       error = xfs_defer_init_item_caches();
+       error = rcbagbt_init_cur_cache();
        if (error)
                goto out_destroy_btree_cur_cache;
  
+       error = xfs_defer_init_item_caches();
+       if (error)
+               goto out_destroy_rcbagbt_cur_cache;
        xfs_da_state_cache = kmem_cache_create("xfs_da_state",
                                              sizeof(struct xfs_da_state),
                                              0, 0, NULL);
                                           sizeof(struct xfs_inode), 0,
                                           (SLAB_HWCACHE_ALIGN |
                                            SLAB_RECLAIM_ACCOUNT |
 -                                          SLAB_MEM_SPREAD | SLAB_ACCOUNT),
 +                                          SLAB_ACCOUNT),
                                           xfs_fs_inode_init_once);
        if (!xfs_inode_cache)
                goto out_destroy_efi_cache;
  
        xfs_ili_cache = kmem_cache_create("xfs_ili",
                                         sizeof(struct xfs_inode_log_item), 0,
 -                                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
 +                                       SLAB_RECLAIM_ACCOUNT,
                                         NULL);
        if (!xfs_ili_cache)
                goto out_destroy_inode_cache;
        kmem_cache_destroy(xfs_da_state_cache);
   out_destroy_defer_item_cache:
        xfs_defer_destroy_item_caches();
+  out_destroy_rcbagbt_cur_cache:
+       rcbagbt_destroy_cur_cache();
   out_destroy_btree_cur_cache:
        xfs_btree_destroy_cur_caches();
   out_destroy_log_ticket_cache:
@@@ -2255,6 -2264,7 +2262,7 @@@ xfs_destroy_caches(void
        kmem_cache_destroy(xfs_ifork_cache);
        kmem_cache_destroy(xfs_da_state_cache);
        xfs_defer_destroy_item_caches();
+       rcbagbt_destroy_cur_cache();
        xfs_btree_destroy_cur_caches();
        kmem_cache_destroy(xfs_log_ticket_cache);
        kmem_cache_destroy(xfs_buf_cache);
diff --combined include/linux/swap.h
index 378ab1cd23bdcb4be1857d0f3bada023f8a6dae7,755fc64ba48deda82e2ec7892db202dee995e980..95410ca891a7a252b8d730c1913c3ab208434288
@@@ -298,7 -298,7 +298,7 @@@ struct swap_info_struct 
        unsigned int __percpu *cluster_next_cpu; /*percpu index for next allocation */
        struct percpu_cluster __percpu *percpu_cluster; /* per cpu's swap location */
        struct rb_root swap_extent_root;/* root of the swap extent rbtree */
 -      struct bdev_handle *bdev_handle;/* open handle of the bdev */
 +      struct file *bdev_file;         /* open handle of the bdev */
        struct block_device *bdev;      /* swap device or bdev of swap file */
        struct file *swap_file;         /* seldom referenced */
        unsigned int old_block_size;    /* seldom referenced */
@@@ -350,16 -350,6 +350,6 @@@ void *workingset_eviction(struct folio 
  void workingset_refault(struct folio *folio, void *shadow);
  void workingset_activation(struct folio *folio);
  
- /* Only track the nodes of mappings with shadow entries */
- void workingset_update_node(struct xa_node *node);
- extern struct list_lru shadow_nodes;
- #define mapping_set_update(xas, mapping) do {                         \
-       if (!dax_mapping(mapping) && !shmem_mapping(mapping)) {         \
-               xas_set_update(xas, workingset_update_node);            \
-               xas_set_lru(xas, &shadow_nodes);                        \
-       }                                                               \
- } while (0)
  /* linux/mm/page_alloc.c */
  extern unsigned long totalreserve_pages;
  
@@@ -549,11 -539,6 +539,11 @@@ static inline int swap_duplicate(swp_en
        return 0;
  }
  
 +static inline int swapcache_prepare(swp_entry_t swp)
 +{
 +      return 0;
 +}
 +
  static inline void swap_free(swp_entry_t swp)
  {
  }
diff --combined mm/filemap.c
index 8df4797c5287fa748aef1c26dd63f92dc24f03fd,6c8b089f00d26af8def778db01e2a9cc1d2caa04..fef125d9508b8bb7ece2aa1689899484d07851cf
   *    ->private_lock          (zap_pte_range->block_dirty_folio)
   */
  
+ static void mapping_set_update(struct xa_state *xas,
+               struct address_space *mapping)
+ {
+       if (dax_mapping(mapping) || shmem_mapping(mapping))
+               return;
+       xas_set_update(xas, workingset_update_node);
+       xas_set_lru(xas, &shadow_nodes);
+ }
  static void page_cache_delete(struct address_space *mapping,
                                   struct folio *folio, void *shadow)
  {
@@@ -2608,6 -2617,15 +2617,6 @@@ ssize_t filemap_read(struct kiocb *iocb
                        goto put_folios;
                end_offset = min_t(loff_t, isize, iocb->ki_pos + iter->count);
  
 -              /*
 -               * Pairs with a barrier in
 -               * block_write_end()->mark_buffer_dirty() or other page
 -               * dirtying routines like iomap_write_end() to ensure
 -               * changes to page contents are visible before we see
 -               * increased inode size.
 -               */
 -              smp_rmb();
 -
                /*
                 * Once we start copying data, we don't want to be touching any
                 * cachelines that might be contended:
@@@ -4102,40 -4120,28 +4111,40 @@@ static void filemap_cachestat(struct ad
  
        rcu_read_lock();
        xas_for_each(&xas, folio, last_index) {
 +              int order;
                unsigned long nr_pages;
                pgoff_t folio_first_index, folio_last_index;
  
 +              /*
 +               * Don't deref the folio. It is not pinned, and might
 +               * get freed (and reused) underneath us.
 +               *
 +               * We *could* pin it, but that would be expensive for
 +               * what should be a fast and lightweight syscall.
 +               *
 +               * Instead, derive all information of interest from
 +               * the rcu-protected xarray.
 +               */
 +
                if (xas_retry(&xas, folio))
                        continue;
  
 +              order = xa_get_order(xas.xa, xas.xa_index);
 +              nr_pages = 1 << order;
 +              folio_first_index = round_down(xas.xa_index, 1 << order);
 +              folio_last_index = folio_first_index + nr_pages - 1;
 +
 +              /* Folios might straddle the range boundaries, only count covered pages */
 +              if (folio_first_index < first_index)
 +                      nr_pages -= first_index - folio_first_index;
 +
 +              if (folio_last_index > last_index)
 +                      nr_pages -= folio_last_index - last_index;
 +
                if (xa_is_value(folio)) {
                        /* page is evicted */
                        void *shadow = (void *)folio;
                        bool workingset; /* not used */
 -                      int order = xa_get_order(xas.xa, xas.xa_index);
 -
 -                      nr_pages = 1 << order;
 -                      folio_first_index = round_down(xas.xa_index, 1 << order);
 -                      folio_last_index = folio_first_index + nr_pages - 1;
 -
 -                      /* Folios might straddle the range boundaries, only count covered pages */
 -                      if (folio_first_index < first_index)
 -                              nr_pages -= first_index - folio_first_index;
 -
 -                      if (folio_last_index > last_index)
 -                              nr_pages -= folio_last_index - last_index;
  
                        cs->nr_evicted += nr_pages;
  
                        goto resched;
                }
  
 -              nr_pages = folio_nr_pages(folio);
 -              folio_first_index = folio_pgoff(folio);
 -              folio_last_index = folio_first_index + nr_pages - 1;
 -
 -              /* Folios might straddle the range boundaries, only count covered pages */
 -              if (folio_first_index < first_index)
 -                      nr_pages -= first_index - folio_first_index;
 -
 -              if (folio_last_index > last_index)
 -                      nr_pages -= folio_last_index - last_index;
 -
                /* page is in cache */
                cs->nr_cache += nr_pages;
  
 -              if (folio_test_dirty(folio))
 +              if (xas_get_mark(&xas, PAGECACHE_TAG_DIRTY))
                        cs->nr_dirty += nr_pages;
  
 -              if (folio_test_writeback(folio))
 +              if (xas_get_mark(&xas, PAGECACHE_TAG_WRITEBACK))
                        cs->nr_writeback += nr_pages;
  
  resched:
diff --combined mm/shmem.c
index 29d5a024df48ae85ca2c39793477bf359d0c3980,cf36899264188f5581265f31626f6df4bb9e5381..be890844fc92a61c7dc0d6bf3c3eba557d4eb322
@@@ -254,7 -254,7 +254,7 @@@ static void shmem_inode_unacct_blocks(s
  }
  
  static const struct super_operations shmem_ops;
- const struct address_space_operations shmem_aops;
static const struct address_space_operations shmem_aops;
  static const struct file_operations shmem_file_operations;
  static const struct inode_operations shmem_inode_operations;
  static const struct inode_operations shmem_dir_inode_operations;
@@@ -263,6 -263,12 +263,12 @@@ static const struct vm_operations_struc
  static const struct vm_operations_struct shmem_anon_vm_ops;
  static struct file_system_type shmem_fs_type;
  
+ bool shmem_mapping(struct address_space *mapping)
+ {
+       return mapping->a_ops == &shmem_aops;
+ }
+ EXPORT_SYMBOL_GPL(shmem_mapping);
  bool vma_is_anon_shmem(struct vm_area_struct *vma)
  {
        return vma->vm_ops == &shmem_anon_vm_ops;
@@@ -1966,6 -1972,9 +1972,9 @@@ static int shmem_get_folio_gfp(struct i
        int error;
        bool alloced;
  
+       if (WARN_ON_ONCE(!shmem_mapping(inode->i_mapping)))
+               return -EINVAL;
        if (index > (MAX_LFS_FILESIZE >> PAGE_SHIFT))
                return -EFBIG;
  repeat:
@@@ -2128,12 -2137,36 +2137,36 @@@ unlock
        return error;
  }
  
+ /**
+  * shmem_get_folio - find, and lock a shmem folio.
+  * @inode:    inode to search
+  * @index:    the page index.
+  * @foliop:   pointer to the folio if found
+  * @sgp:      SGP_* flags to control behavior
+  *
+  * Looks up the page cache entry at @inode & @index.  If a folio is
+  * present, it is returned locked with an increased refcount.
+  *
+  * If the caller modifies data in the folio, it must call folio_mark_dirty()
+  * before unlocking the folio to ensure that the folio is not reclaimed.
+  * There is no need to reserve space before calling folio_mark_dirty().
+  *
+  * When no folio is found, the behavior depends on @sgp:
+  *  - for SGP_READ, *@foliop is %NULL and 0 is returned
+  *  - for SGP_NOALLOC, *@foliop is %NULL and -ENOENT is returned
+  *  - for all other flags a new folio is allocated, inserted into the
+  *    page cache and returned locked in @foliop.
+  *
+  * Context: May sleep.
+  * Return: 0 if successful, else a negative error code.
+  */
  int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
                enum sgp_type sgp)
  {
        return shmem_get_folio_gfp(inode, index, foliop, sgp,
                        mapping_gfp_mask(inode->i_mapping), NULL, NULL);
  }
+ EXPORT_SYMBOL_GPL(shmem_get_folio);
  
  /*
   * This is like autoremove_wake_function, but it removes the wait queue
@@@ -3374,7 -3407,7 +3407,7 @@@ static int shmem_unlink(struct inode *d
  
  static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
  {
 -      if (!simple_empty(dentry))
 +      if (!simple_offset_empty(dentry))
                return -ENOTEMPTY;
  
        drop_nlink(d_inode(dentry));
@@@ -3431,7 -3464,7 +3464,7 @@@ static int shmem_rename2(struct mnt_idm
                return simple_offset_rename_exchange(old_dir, old_dentry,
                                                     new_dir, new_dentry);
  
 -      if (!simple_empty(new_dentry))
 +      if (!simple_offset_empty(new_dentry))
                return -ENOTEMPTY;
  
        if (flags & RENAME_WHITEOUT) {
@@@ -3500,10 -3533,10 +3533,10 @@@ static int shmem_symlink(struct mnt_idm
                inode->i_op = &shmem_short_symlink_operations;
        } else {
                inode_nohighmem(inode);
+               inode->i_mapping->a_ops = &shmem_aops;
                error = shmem_get_folio(inode, 0, &folio, SGP_WRITE);
                if (error)
                        goto out_remove_offset;
-               inode->i_mapping->a_ops = &shmem_aops;
                inode->i_op = &shmem_symlink_inode_operations;
                memcpy(folio_address(folio), symname, len);
                folio_mark_uptodate(folio);
@@@ -4355,9 -4388,7 +4388,9 @@@ static int shmem_fill_super(struct supe
  #ifdef CONFIG_TMPFS_POSIX_ACL
        sb->s_flags |= SB_POSIXACL;
  #endif
 -      uuid_gen(&sb->s_uuid);
 +      uuid_t uuid;
 +      uuid_gen(&uuid);
 +      super_set_uuid(sb, uuid.b, sizeof(uuid));
  
  #ifdef CONFIG_TMPFS_QUOTA
        if (ctx->seen & SHMEM_SEEN_QUOTA) {
@@@ -4468,7 -4499,7 +4501,7 @@@ static int shmem_error_remove_folio(str
        return 0;
  }
  
- const struct address_space_operations shmem_aops = {
static const struct address_space_operations shmem_aops = {
        .writepage      = shmem_writepage,
        .dirty_folio    = noop_dirty_folio,
  #ifdef CONFIG_TMPFS
  #endif
        .error_remove_folio = shmem_error_remove_folio,
  };
- EXPORT_SYMBOL(shmem_aops);
  
  static const struct file_operations shmem_file_operations = {
        .mmap           = shmem_mmap,
@@@ -4835,6 -4865,7 +4867,7 @@@ struct file *shmem_kernel_file_setup(co
  {
        return __shmem_file_setup(shm_mnt, name, size, flags, S_PRIVATE);
  }
+ EXPORT_SYMBOL_GPL(shmem_kernel_file_setup);
  
  /**
   * shmem_file_setup - get an unlinked file living in tmpfs
@@@ -4912,7 -4943,6 +4945,6 @@@ struct folio *shmem_read_folio_gfp(stru
        struct folio *folio;
        int error;
  
-       BUG_ON(!shmem_mapping(mapping));
        error = shmem_get_folio_gfp(inode, index, &folio, SGP_CACHE,
                                    gfp, NULL, NULL);
        if (error)
diff --combined scripts/kernel-doc
index 71a89d8832c1a849de10b747750436af0267c659,d2f3fa3505c6e4808dd36d5b7e00b1a02b9cfb2f..967f1abb0edbd83dd26c9872ed9254992aadea6d
@@@ -1,6 -1,5 +1,6 @@@
  #!/usr/bin/env perl
  # SPDX-License-Identifier: GPL-2.0
 +# vim: softtabstop=4
  
  use warnings;
  use strict;
@@@ -65,7 -64,7 +65,7 @@@ my $type_constant = '\b``([^\`]+)``\b'
  my $type_constant2 = '\%([-_\w]+)';
  my $type_func = '(\w+)\(\)';
  my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
- my $type_param_ref = '([\!~]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
+ my $type_param_ref = '([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
  my $type_fp_param = '\@(\w+)\(\)';  # Special RST handling for func ptr params
  my $type_fp_param2 = '\@(\w+->\S+)\(\)';  # Special RST handling for structs with func ptr params
  my $type_env = '(\$\w+)';
@@@ -82,51 -81,49 +82,51 @@@ my $type_member_func = $type_member . '
  
  # these are pretty rough
  my @highlights_man = (
 -                      [$type_constant, "\$1"],
 -                      [$type_constant2, "\$1"],
 -                      [$type_func, "\\\\fB\$1\\\\fP"],
 -                      [$type_enum, "\\\\fI\$1\\\\fP"],
 -                      [$type_struct, "\\\\fI\$1\\\\fP"],
 -                      [$type_typedef, "\\\\fI\$1\\\\fP"],
 -                      [$type_union, "\\\\fI\$1\\\\fP"],
 -                      [$type_param, "\\\\fI\$1\\\\fP"],
 -                      [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
 -                      [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
 -                      [$type_fallback, "\\\\fI\$1\\\\fP"]
 -                   );
 +    [$type_constant, "\$1"],
 +    [$type_constant2, "\$1"],
 +    [$type_func, "\\\\fB\$1\\\\fP"],
 +    [$type_enum, "\\\\fI\$1\\\\fP"],
 +    [$type_struct, "\\\\fI\$1\\\\fP"],
 +    [$type_typedef, "\\\\fI\$1\\\\fP"],
 +    [$type_union, "\\\\fI\$1\\\\fP"],
 +    [$type_param, "\\\\fI\$1\\\\fP"],
 +    [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
 +    [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
 +    [$type_fallback, "\\\\fI\$1\\\\fP"]
 +  );
  my $blankline_man = "";
  
  # rst-mode
  my @highlights_rst = (
 -                       [$type_constant, "``\$1``"],
 -                       [$type_constant2, "``\$1``"],
 -                       # Note: need to escape () to avoid func matching later
 -                       [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
 -                       [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
 -                     [$type_fp_param, "**\$1\\\\(\\\\)**"],
 -                     [$type_fp_param2, "**\$1\\\\(\\\\)**"],
 -                       [$type_func, "\$1()"],
 -                       [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
 -                       [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
 -                       [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
 -                       [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
 -                       # in rst this can refer to any type
 -                       [$type_fallback, "\\:c\\:type\\:`\$1`"],
 -                       [$type_param_ref, "**\$1\$2**"]
 -                    );
 +    [$type_constant, "``\$1``"],
 +    [$type_constant2, "``\$1``"],
 +
 +    # Note: need to escape () to avoid func matching later
 +    [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
 +    [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
 +    [$type_fp_param, "**\$1\\\\(\\\\)**"],
 +    [$type_fp_param2, "**\$1\\\\(\\\\)**"],
 +    [$type_func, "\$1()"],
 +    [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
 +    [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
 +    [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
 +    [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
 +
 +    # in rst this can refer to any type
 +    [$type_fallback, "\\:c\\:type\\:`\$1`"],
 +    [$type_param_ref, "**\$1\$2**"]
 +  );
  my $blankline_rst = "\n";
  
  # read arguments
  if ($#ARGV == -1) {
 -      pod2usage(
 -              -message => "No arguments!\n",
 -              -exitval => 1,
 -              -verbose => 99,
 -              -sections => 'SYNOPSIS',
 -              -output => \*STDERR,
 -      );
 +    pod2usage(
 +        -message => "No arguments!\n",
 +        -exitval => 1,
 +        -verbose => 99,
 +        -sections => 'SYNOPSIS',
 +        -output => \*STDERR,
 +      );
  }
  
  my $kernelversion;
@@@ -167,9 -164,9 +167,9 @@@ if (defined($ENV{'KBUILD_BUILD_TIMESTAM
  }
  
  my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
 -              'July', 'August', 'September', 'October',
 -              'November', 'December')[$build_time[4]] .
 -  " " . ($build_time[5]+1900);
 +                'July', 'August', 'September', 'October',
 +                'November', 'December')[$build_time[4]] .
 +    " " . ($build_time[5]+1900);
  
  # Essentially these are globals.
  # They probably want to be tidied up, made more localised or something.
@@@ -182,22 -179,22 +182,22 @@@ my ($type, $declaration_name, $return_t
  my ($newsection, $newcontents, $prototype, $brcount, %source_map);
  
  if (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'KBUILD_VERBOSE'} =~ '1') {
 -      $verbose = 1;
 +    $verbose = 1;
  }
  
  if (defined($ENV{'KCFLAGS'})) {
 -      my $kcflags = "$ENV{'KCFLAGS'}";
 +    my $kcflags = "$ENV{'KCFLAGS'}";
  
 -      if ($kcflags =~ /(\s|^)-Werror(\s|$)/) {
 -              $Werror = 1;
 -      }
 +    if ($kcflags =~ /(\s|^)-Werror(\s|$)/) {
 +        $Werror = 1;
 +    }
  }
  
  # reading this variable is for backwards compat just in case
  # someone was calling it with the variable from outside the
  # kernel's build system
  if (defined($ENV{'KDOC_WERROR'})) {
 -      $Werror = "$ENV{'KDOC_WERROR'}";
 +    $Werror = "$ENV{'KDOC_WERROR'}";
  }
  # other environment variables are converted to command-line
  # arguments in cmd_checkdoc in the build system
@@@ -298,90 -295,90 +298,90 @@@ while ($ARGV[0] =~ m/^--?(.*)/) 
      my $cmd = $1;
      shift @ARGV;
      if ($cmd eq "man") {
 -      $output_mode = "man";
 -      @highlights = @highlights_man;
 -      $blankline = $blankline_man;
 +        $output_mode = "man";
 +        @highlights = @highlights_man;
 +        $blankline = $blankline_man;
      } elsif ($cmd eq "rst") {
 -      $output_mode = "rst";
 -      @highlights = @highlights_rst;
 -      $blankline = $blankline_rst;
 +        $output_mode = "rst";
 +        @highlights = @highlights_rst;
 +        $blankline = $blankline_rst;
      } elsif ($cmd eq "none") {
 -      $output_mode = "none";
 +        $output_mode = "none";
      } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document
 -      $modulename = shift @ARGV;
 +        $modulename = shift @ARGV;
      } elsif ($cmd eq "function") { # to only output specific functions
 -      $output_selection = OUTPUT_INCLUDE;
 -      $function = shift @ARGV;
 -      $function_table{$function} = 1;
 +        $output_selection = OUTPUT_INCLUDE;
 +        $function = shift @ARGV;
 +        $function_table{$function} = 1;
      } elsif ($cmd eq "nosymbol") { # Exclude specific symbols
 -      my $symbol = shift @ARGV;
 -      $nosymbol_table{$symbol} = 1;
 +        my $symbol = shift @ARGV;
 +        $nosymbol_table{$symbol} = 1;
      } elsif ($cmd eq "export") { # only exported symbols
 -      $output_selection = OUTPUT_EXPORTED;
 -      %function_table = ();
 +        $output_selection = OUTPUT_EXPORTED;
 +        %function_table = ();
      } elsif ($cmd eq "internal") { # only non-exported symbols
 -      $output_selection = OUTPUT_INTERNAL;
 -      %function_table = ();
 +        $output_selection = OUTPUT_INTERNAL;
 +        %function_table = ();
      } elsif ($cmd eq "export-file") {
 -      my $file = shift @ARGV;
 -      push(@export_file_list, $file);
 +        my $file = shift @ARGV;
 +        push(@export_file_list, $file);
      } elsif ($cmd eq "v") {
 -      $verbose = 1;
 +        $verbose = 1;
      } elsif ($cmd eq "Werror") {
 -      $Werror = 1;
 +        $Werror = 1;
      } elsif ($cmd eq "Wreturn") {
 -      $Wreturn = 1;
 +        $Wreturn = 1;
      } elsif ($cmd eq "Wshort-desc" or $cmd eq "Wshort-description") {
 -      $Wshort_desc = 1;
 +        $Wshort_desc = 1;
      } elsif ($cmd eq "Wcontents-before-sections") {
 -      $Wcontents_before_sections = 1;
 +        $Wcontents_before_sections = 1;
      } elsif ($cmd eq "Wall") {
          $Wreturn = 1;
          $Wshort_desc = 1;
          $Wcontents_before_sections = 1;
      } elsif (($cmd eq "h") || ($cmd eq "help")) {
 -              pod2usage(-exitval => 0, -verbose => 2);
 +        pod2usage(-exitval => 0, -verbose => 2);
      } elsif ($cmd eq 'no-doc-sections') {
 -          $no_doc_sections = 1;
 +        $no_doc_sections = 1;
      } elsif ($cmd eq 'enable-lineno') {
 -          $enable_lineno = 1;
 +        $enable_lineno = 1;
      } elsif ($cmd eq 'show-not-found') {
 -      $show_not_found = 1;  # A no-op but don't fail
 +        $show_not_found = 1;  # A no-op but don't fail
      } elsif ($cmd eq "sphinx-version") {
 -      my $ver_string = shift @ARGV;
 -      if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) {
 -          $sphinx_major = $1;
 -          if (defined($2)) {
 -              $sphinx_minor = substr($2,1);
 -          } else {
 -              $sphinx_minor = 0;
 -          }
 -          if (defined($3)) {
 -              $sphinx_patch = substr($3,1)
 -          } else {
 -              $sphinx_patch = 0;
 -          }
 -      } else {
 -          die "Sphinx version should either major.minor or major.minor.patch format\n";
 -      }
 +        my $ver_string = shift @ARGV;
 +        if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) {
 +            $sphinx_major = $1;
 +            if (defined($2)) {
 +                $sphinx_minor = substr($2,1);
 +            } else {
 +                $sphinx_minor = 0;
 +            }
 +            if (defined($3)) {
 +                $sphinx_patch = substr($3,1)
 +            } else {
 +                $sphinx_patch = 0;
 +            }
 +        } else {
 +            die "Sphinx version should either major.minor or major.minor.patch format\n";
 +        }
      } else {
 -      # Unknown argument
 -      pod2usage(
 -          -message => "Argument unknown!\n",
 -          -exitval => 1,
 -          -verbose => 99,
 -          -sections => 'SYNOPSIS',
 -          -output => \*STDERR,
 -          );
 +        # Unknown argument
 +        pod2usage(
 +            -message => "Argument unknown!\n",
 +            -exitval => 1,
 +            -verbose => 99,
 +            -sections => 'SYNOPSIS',
 +            -output => \*STDERR,
 +            );
      }
      if ($#ARGV < 0){
 -      pod2usage(
 -          -message => "FILE argument missing\n",
 -          -exitval => 1,
 -          -verbose => 99,
 -          -sections => 'SYNOPSIS',
 -          -output => \*STDERR,
 -          );
 +        pod2usage(
 +            -message => "FILE argument missing\n",
 +            -exitval => 1,
 +            -verbose => 99,
 +            -sections => 'SYNOPSIS',
 +            -output => \*STDERR,
 +            );
      }
  }
  
  # version in order to produce the right tags.
  sub findprog($)
  {
 -      foreach(split(/:/, $ENV{PATH})) {
 -              return "$_/$_[0]" if(-x "$_/$_[0]");
 -      }
 +    foreach(split(/:/, $ENV{PATH})) {
 +        return "$_/$_[0]" if(-x "$_/$_[0]");
 +    }
  }
  
  sub get_sphinx_version()
  {
 -      my $ver;
 -
 -      my $cmd = "sphinx-build";
 -      if (!findprog($cmd)) {
 -              my $cmd = "sphinx-build3";
 -              if (!findprog($cmd)) {
 -                      $sphinx_major = 1;
 -                      $sphinx_minor = 2;
 -                      $sphinx_patch = 0;
 -                      printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n",
 -                             $sphinx_major, $sphinx_minor, $sphinx_patch;
 -                      return;
 -              }
 -      }
 -
 -      open IN, "$cmd --version 2>&1 |";
 -      while (<IN>) {
 -              if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) {
 -                      $sphinx_major = $1;
 -                      $sphinx_minor = $2;
 -                      $sphinx_patch = $3;
 -                      last;
 -              }
 -              # Sphinx 1.2.x uses a different format
 -              if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) {
 -                      $sphinx_major = $1;
 -                      $sphinx_minor = $2;
 -                      $sphinx_patch = $3;
 -                      last;
 -              }
 -      }
 -      close IN;
 +    my $ver;
 +
 +    my $cmd = "sphinx-build";
 +    if (!findprog($cmd)) {
 +        my $cmd = "sphinx-build3";
 +        if (!findprog($cmd)) {
 +            $sphinx_major = 1;
 +            $sphinx_minor = 2;
 +            $sphinx_patch = 0;
 +            printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n",
 +                   $sphinx_major, $sphinx_minor, $sphinx_patch;
 +            return;
 +        }
 +    }
 +
 +    open IN, "$cmd --version 2>&1 |";
 +    while (<IN>) {
 +        if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) {
 +            $sphinx_major = $1;
 +            $sphinx_minor = $2;
 +            $sphinx_patch = $3;
 +            last;
 +        }
 +        # Sphinx 1.2.x uses a different format
 +        if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) {
 +            $sphinx_major = $1;
 +            $sphinx_minor = $2;
 +            $sphinx_patch = $3;
 +            last;
 +        }
 +    }
 +    close IN;
  }
  
  # get kernel version from env
@@@ -437,7 -434,7 +437,7 @@@ sub get_kernel_version() 
      my $version = 'unknown kernel version';
  
      if (defined($ENV{'KERNELVERSION'})) {
 -      $version = $ENV{'KERNELVERSION'};
 +        $version = $ENV{'KERNELVERSION'};
      }
      return $version;
  }
@@@ -465,30 -462,30 +465,30 @@@ sub dump_section 
      my $contents = join "\n", @_;
  
      if ($name =~ m/$type_param/) {
 -      $name = $1;
 -      $parameterdescs{$name} = $contents;
 -      $sectcheck = $sectcheck . $name . " ";
 +        $name = $1;
 +        $parameterdescs{$name} = $contents;
 +        $sectcheck = $sectcheck . $name . " ";
          $parameterdesc_start_lines{$name} = $new_start_line;
          $new_start_line = 0;
      } elsif ($name eq "@\.\.\.") {
 -      $name = "...";
 -      $parameterdescs{$name} = $contents;
 -      $sectcheck = $sectcheck . $name . " ";
 +        $name = "...";
 +        $parameterdescs{$name} = $contents;
 +        $sectcheck = $sectcheck . $name . " ";
          $parameterdesc_start_lines{$name} = $new_start_line;
          $new_start_line = 0;
      } else {
 -      if (defined($sections{$name}) && ($sections{$name} ne "")) {
 -          # Only warn on user specified duplicate section names.
 -          if ($name ne $section_default) {
 -              emit_warning("${file}:$.", "duplicate section name '$name'\n");
 -          }
 -          $sections{$name} .= $contents;
 -      } else {
 -          $sections{$name} = $contents;
 -          push @sectionlist, $name;
 +        if (defined($sections{$name}) && ($sections{$name} ne "")) {
 +            # Only warn on user specified duplicate section names.
 +            if ($name ne $section_default) {
 +                emit_warning("${file}:$.", "duplicate section name '$name'\n");
 +            }
 +            $sections{$name} .= $contents;
 +        } else {
 +            $sections{$name} = $contents;
 +            push @sectionlist, $name;
              $section_start_lines{$name} = $new_start_line;
              $new_start_line = 0;
 -      }
 +        }
      }
  }
  
@@@ -507,14 -504,14 +507,14 @@@ sub dump_doc_section 
      return if (defined($nosymbol_table{$name}));
  
      if (($output_selection == OUTPUT_ALL) ||
 -      (($output_selection == OUTPUT_INCLUDE) &&
 -       defined($function_table{$name})))
 +        (($output_selection == OUTPUT_INCLUDE) &&
 +         defined($function_table{$name})))
      {
 -      dump_section($file, $name, $contents);
 -      output_blockhead({'sectionlist' => \@sectionlist,
 -                        'sections' => \%sections,
 -                        'module' => $modulename,
 -                        'content-only' => ($output_selection != OUTPUT_ALL), });
 +        dump_section($file, $name, $contents);
 +        output_blockhead({'sectionlist' => \@sectionlist,
 +                          'sections' => \%sections,
 +                          'module' => $modulename,
 +                          'content-only' => ($output_selection != OUTPUT_ALL), });
      }
  }
  
@@@ -545,21 -542,21 +545,21 @@@ sub output_highlight 
  #   print STDERR "contents af:$contents\n";
  
      foreach $line (split "\n", $contents) {
 -      if (! $output_preformatted) {
 -          $line =~ s/^\s*//;
 -      }
 -      if ($line eq ""){
 -          if (! $output_preformatted) {
 -              print $lineprefix, $blankline;
 -          }
 -      } else {
 -          if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
 -              print "\\&$line";
 -          } else {
 -              print $lineprefix, $line;
 -          }
 -      }
 -      print "\n";
 +        if (! $output_preformatted) {
 +            $line =~ s/^\s*//;
 +        }
 +        if ($line eq ""){
 +            if (! $output_preformatted) {
 +                print $lineprefix, $blankline;
 +            }
 +        } else {
 +            if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
 +                print "\\&$line";
 +            } else {
 +                print $lineprefix, $line;
 +            }
 +        }
 +        print "\n";
      }
  }
  
@@@ -577,40 -574,40 +577,40 @@@ sub output_function_man(%) 
  
      print ".SH SYNOPSIS\n";
      if ($args{'functiontype'} ne "") {
 -      print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
 +        print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
      } else {
 -      print ".B \"" . $args{'function'} . "\n";
 +        print ".B \"" . $args{'function'} . "\n";
      }
      $count = 0;
      my $parenth = "(";
      my $post = ",";
      foreach my $parameter (@{$args{'parameterlist'}}) {
 -      if ($count == $#{$args{'parameterlist'}}) {
 -          $post = ");";
 -      }
 -      $type = $args{'parametertypes'}{$parameter};
 -      if ($type =~ m/$function_pointer/) {
 -          # pointer-to-function
 -          print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
 -      } else {
 -          $type =~ s/([^\*])$/$1 /;
 -          print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
 -      }
 -      $count++;
 -      $parenth = "";
 +        if ($count == $#{$args{'parameterlist'}}) {
 +            $post = ");";
 +        }
 +        $type = $args{'parametertypes'}{$parameter};
 +        if ($type =~ m/$function_pointer/) {
 +            # pointer-to-function
 +            print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
 +        } else {
 +            $type =~ s/([^\*])$/$1 /;
 +            print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
 +        }
 +        $count++;
 +        $parenth = "";
      }
  
      print ".SH ARGUMENTS\n";
      foreach $parameter (@{$args{'parameterlist'}}) {
 -      my $parameter_name = $parameter;
 -      $parameter_name =~ s/\[.*//;
 +        my $parameter_name = $parameter;
 +        $parameter_name =~ s/\[.*//;
  
 -      print ".IP \"" . $parameter . "\" 12\n";
 -      output_highlight($args{'parameterdescs'}{$parameter_name});
 +        print ".IP \"" . $parameter . "\" 12\n";
 +        output_highlight($args{'parameterdescs'}{$parameter_name});
      }
      foreach $section (@{$args{'sectionlist'}}) {
 -      print ".SH \"", uc $section, "\"\n";
 -      output_highlight($args{'sections'}{$section});
 +        print ".SH \"", uc $section, "\"\n";
 +        output_highlight($args{'sections'}{$section});
      }
  }
  
@@@ -630,27 -627,28 +630,27 @@@ sub output_enum_man(%) 
      print "enum " . $args{'enum'} . " {\n";
      $count = 0;
      foreach my $parameter (@{$args{'parameterlist'}}) {
 -      print ".br\n.BI \"    $parameter\"\n";
 -      if ($count == $#{$args{'parameterlist'}}) {
 -          print "\n};\n";
 -          last;
 -      }
 -      else {
 -          print ", \n.br\n";
 -      }
 -      $count++;
 +        print ".br\n.BI \"    $parameter\"\n";
 +        if ($count == $#{$args{'parameterlist'}}) {
 +            print "\n};\n";
 +            last;
 +        } else {
 +            print ", \n.br\n";
 +        }
 +        $count++;
      }
  
      print ".SH Constants\n";
      foreach $parameter (@{$args{'parameterlist'}}) {
 -      my $parameter_name = $parameter;
 -      $parameter_name =~ s/\[.*//;
 +        my $parameter_name = $parameter;
 +        $parameter_name =~ s/\[.*//;
  
 -      print ".IP \"" . $parameter . "\" 12\n";
 -      output_highlight($args{'parameterdescs'}{$parameter_name});
 +        print ".IP \"" . $parameter . "\" 12\n";
 +        output_highlight($args{'parameterdescs'}{$parameter_name});
      }
      foreach $section (@{$args{'sectionlist'}}) {
 -      print ".SH \"$section\"\n";
 -      output_highlight($args{'sections'}{$section});
 +        print ".SH \"$section\"\n";
 +        output_highlight($args{'sections'}{$section});
      }
  }
  
@@@ -674,18 -672,18 +674,18 @@@ sub output_struct_man(%) 
  
      print ".SH Members\n";
      foreach $parameter (@{$args{'parameterlist'}}) {
 -      ($parameter =~ /^#/) && next;
 +        ($parameter =~ /^#/) && next;
  
 -      my $parameter_name = $parameter;
 -      $parameter_name =~ s/\[.*//;
 +        my $parameter_name = $parameter;
 +        $parameter_name =~ s/\[.*//;
  
 -      ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 -      print ".IP \"" . $parameter . "\" 12\n";
 -      output_highlight($args{'parameterdescs'}{$parameter_name});
 +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 +        print ".IP \"" . $parameter . "\" 12\n";
 +        output_highlight($args{'parameterdescs'}{$parameter_name});
      }
      foreach $section (@{$args{'sectionlist'}}) {
 -      print ".SH \"$section\"\n";
 -      output_highlight($args{'sections'}{$section});
 +        print ".SH \"$section\"\n";
 +        output_highlight($args{'sections'}{$section});
      }
  }
  
@@@ -701,8 -699,8 +701,8 @@@ sub output_typedef_man(%) 
      print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
  
      foreach $section (@{$args{'sectionlist'}}) {
 -      print ".SH \"$section\"\n";
 -      output_highlight($args{'sections'}{$section});
 +        print ".SH \"$section\"\n";
 +        output_highlight($args{'sections'}{$section});
      }
  }
  
@@@ -714,8 -712,8 +714,8 @@@ sub output_blockhead_man(%) 
      print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
  
      foreach $section (@{$args{'sectionlist'}}) {
 -      print ".SH \"$section\"\n";
 -      output_highlight($args{'sections'}{$section});
 +        print ".SH \"$section\"\n";
 +        output_highlight($args{'sections'}{$section});
      }
  }
  
@@@ -733,15 -731,15 +733,15 @@@ sub output_blockhead_rst(%) 
      my ($parameter, $section);
  
      foreach $section (@{$args{'sectionlist'}}) {
 -      next if (defined($nosymbol_table{$section}));
 +        next if (defined($nosymbol_table{$section}));
  
 -      if ($output_selection != OUTPUT_INCLUDE) {
 -          print ".. _$section:\n\n";
 -          print "**$section**\n\n";
 -      }
 +        if ($output_selection != OUTPUT_INCLUDE) {
 +            print ".. _$section:\n\n";
 +            print "**$section**\n\n";
 +        }
          print_lineno($section_start_lines{$section});
 -      output_highlight_rst($args{'sections'}{$section});
 -      print "\n";
 +        output_highlight_rst($args{'sections'}{$section});
 +        print "\n";
      }
  }
  
@@@ -771,48 -769,48 +771,48 @@@ sub output_highlight_rst 
      my $block = "";
  
      foreach $line (split "\n",$input) {
 -      #
 -      # If we're in a literal block, see if we should drop out
 -      # of it.  Otherwise pass the line straight through unmunged.
 -      #
 -      if ($in_literal) {
 -          if (! ($line =~ /^\s*$/)) {
 -              #
 -              # If this is the first non-blank line in a literal
 -              # block we need to figure out what the proper indent is.
 -              #
 -              if ($litprefix eq "") {
 -                  $line =~ /^(\s*)/;
 -                  $litprefix = '^' . $1;
 -                  $output .= $line . "\n";
 -              } elsif (! ($line =~ /$litprefix/)) {
 -                  $in_literal = 0;
 -              } else {
 -                  $output .= $line . "\n";
 -              }
 -          } else {
 -              $output .= $line . "\n";
 -          }
 -      }
 -      #
 -      # Not in a literal block (or just dropped out)
 -      #
 -      if (! $in_literal) {
 -          $block .= $line . "\n";
 -          if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
 -              $in_literal = 1;
 -              $litprefix = "";
 -              $output .= highlight_block($block);
 -              $block = ""
 -          }
 -      }
 +        #
 +        # If we're in a literal block, see if we should drop out
 +        # of it.  Otherwise pass the line straight through unmunged.
 +        #
 +        if ($in_literal) {
 +            if (! ($line =~ /^\s*$/)) {
 +                #
 +                # If this is the first non-blank line in a literal
 +                # block we need to figure out what the proper indent is.
 +                #
 +                if ($litprefix eq "") {
 +                    $line =~ /^(\s*)/;
 +                    $litprefix = '^' . $1;
 +                    $output .= $line . "\n";
 +                } elsif (! ($line =~ /$litprefix/)) {
 +                    $in_literal = 0;
 +                } else {
 +                    $output .= $line . "\n";
 +                }
 +            } else {
 +                $output .= $line . "\n";
 +            }
 +        }
 +        #
 +        # Not in a literal block (or just dropped out)
 +        #
 +        if (! $in_literal) {
 +            $block .= $line . "\n";
 +            if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
 +                $in_literal = 1;
 +                $litprefix = "";
 +                $output .= highlight_block($block);
 +                $block = ""
 +            }
 +        }
      }
  
      if ($block) {
 -      $output .= highlight_block($block);
 +        $output .= highlight_block($block);
      }
      foreach $line (split "\n", $output) {
 -      print $lineprefix . $line . "\n";
 +        print $lineprefix . $line . "\n";
      }
  }
  
@@@ -820,68 -818,71 +820,68 @@@ sub output_function_rst(%) 
      my %args = %{$_[0]};
      my ($parameter, $section);
      my $oldprefix = $lineprefix;
 -    my $start = "";
 -    my $is_macro = 0;
  
 -    if ($sphinx_major < 3) {
 -      if ($args{'typedef'}) {
 -          print ".. c:type:: ". $args{'function'} . "\n\n";
 -          print_lineno($declaration_start_line);
 -          print "   **Typedef**: ";
 -          $lineprefix = "";
 -          output_highlight_rst($args{'purpose'});
 -          $start = "\n\n**Syntax**\n\n  ``";
 -          $is_macro = 1;
 -      } else {
 -          print ".. c:function:: ";
 -      }
 -    } else {
 -      if ($args{'typedef'} || $args{'functiontype'} eq "") {
 -          $is_macro = 1;
 -          print ".. c:macro:: ". $args{'function'} . "\n\n";
 -      } else {
 -          print ".. c:function:: ";
 -      }
 -
 -      if ($args{'typedef'}) {
 -          print_lineno($declaration_start_line);
 -          print "   **Typedef**: ";
 -          $lineprefix = "";
 -          output_highlight_rst($args{'purpose'});
 -          $start = "\n\n**Syntax**\n\n  ``";
 -      } else {
 -          print "``" if ($is_macro);
 -      }
 -    }
 +    my $signature = "";
      if ($args{'functiontype'} ne "") {
 -      $start .= $args{'functiontype'} . " " . $args{'function'} . " (";
 +        $signature = $args{'functiontype'} . " " . $args{'function'} . " (";
      } else {
 -      $start .= $args{'function'} . " (";
 +        $signature = $args{'function'} . " (";
      }
 -    print $start;
  
      my $count = 0;
      foreach my $parameter (@{$args{'parameterlist'}}) {
 -      if ($count ne 0) {
 -          print ", ";
 -      }
 -      $count++;
 -      $type = $args{'parametertypes'}{$parameter};
 -
 -      if ($type =~ m/$function_pointer/) {
 -          # pointer-to-function
 -          print $1 . $parameter . ") (" . $2 . ")";
 -      } else {
 -          print $type;
 -      }
 -    }
 -    if ($is_macro) {
 -      print ")``\n\n";
 +        if ($count ne 0) {
 +            $signature .= ", ";
 +        }
 +        $count++;
 +        $type = $args{'parametertypes'}{$parameter};
 +
 +        if ($type =~ m/$function_pointer/) {
 +            # pointer-to-function
 +            $signature .= $1 . $parameter . ") (" . $2 . ")";
 +        } else {
 +            $signature .= $type;
 +        }
 +    }
 +
 +    $signature .= ")";
 +
 +    if ($sphinx_major < 3) {
 +        if ($args{'typedef'}) {
 +            print ".. c:type:: ". $args{'function'} . "\n\n";
 +            print_lineno($declaration_start_line);
 +            print "   **Typedef**: ";
 +            $lineprefix = "";
 +            output_highlight_rst($args{'purpose'});
 +            print "\n\n**Syntax**\n\n";
 +            print "  ``$signature``\n\n";
 +        } else {
 +            print ".. c:function:: $signature\n\n";
 +        }
      } else {
 -      print ")\n\n";
 +        if ($args{'typedef'} || $args{'functiontype'} eq "") {
 +            print ".. c:macro:: ". $args{'function'} . "\n\n";
 +
 +            if ($args{'typedef'}) {
 +                print_lineno($declaration_start_line);
 +                print "   **Typedef**: ";
 +                $lineprefix = "";
 +                output_highlight_rst($args{'purpose'});
 +                print "\n\n**Syntax**\n\n";
 +                print "  ``$signature``\n\n";
 +            } else {
 +                print "``$signature``\n\n";
 +            }
 +        } else {
 +            print ".. c:function:: $signature\n\n";
 +        }
      }
 +
      if (!$args{'typedef'}) {
 -      print_lineno($declaration_start_line);
 -      $lineprefix = "   ";
 -      output_highlight_rst($args{'purpose'});
 -      print "\n";
 +        print_lineno($declaration_start_line);
 +        $lineprefix = "   ";
 +        output_highlight_rst($args{'purpose'});
 +        print "\n";
      }
  
      #
      $lineprefix = "  ";
      print $lineprefix . "**Parameters**\n\n";
      foreach $parameter (@{$args{'parameterlist'}}) {
 -      my $parameter_name = $parameter;
 -      $parameter_name =~ s/\[.*//;
 -      $type = $args{'parametertypes'}{$parameter};
 -
 -      if ($type ne "") {
 -          print $lineprefix . "``$type``\n";
 -      } else {
 -          print $lineprefix . "``$parameter``\n";
 -      }
 +        my $parameter_name = $parameter;
 +        $parameter_name =~ s/\[.*//;
 +        $type = $args{'parametertypes'}{$parameter};
 +
 +        if ($type ne "") {
 +            print $lineprefix . "``$type``\n";
 +        } else {
 +            print $lineprefix . "``$parameter``\n";
 +        }
  
          print_lineno($parameterdesc_start_lines{$parameter_name});
  
 -      $lineprefix = "    ";
 -      if (defined($args{'parameterdescs'}{$parameter_name}) &&
 -          $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
 -          output_highlight_rst($args{'parameterdescs'}{$parameter_name});
 -      } else {
 -          print $lineprefix . "*undescribed*\n";
 -      }
 -      $lineprefix = "  ";
 -      print "\n";
 +        $lineprefix = "    ";
 +        if (defined($args{'parameterdescs'}{$parameter_name}) &&
 +            $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
 +            output_highlight_rst($args{'parameterdescs'}{$parameter_name});
 +        } else {
 +            print $lineprefix . "*undescribed*\n";
 +        }
 +        $lineprefix = "  ";
 +        print "\n";
      }
  
      output_section_rst(@_);
@@@ -925,10 -926,10 +925,10 @@@ sub output_section_rst(%) 
      my $oldprefix = $lineprefix;
  
      foreach $section (@{$args{'sectionlist'}}) {
 -      print $lineprefix . "**$section**\n\n";
 +        print $lineprefix . "**$section**\n\n";
          print_lineno($section_start_lines{$section});
 -      output_highlight_rst($args{'sections'}{$section});
 -      print "\n";
 +        output_highlight_rst($args{'sections'}{$section});
 +        print "\n";
      }
      print "\n";
  }
@@@ -941,11 -942,11 +941,11 @@@ sub output_enum_rst(%) 
      my $outer;
  
      if ($sphinx_major < 3) {
 -      my $name = "enum " . $args{'enum'};
 -      print "\n\n.. c:type:: " . $name . "\n\n";
 +        my $name = "enum " . $args{'enum'};
 +        print "\n\n.. c:type:: " . $name . "\n\n";
      } else {
 -      my $name = $args{'enum'};
 -      print "\n\n.. c:enum:: " . $name . "\n\n";
 +        my $name = $args{'enum'};
 +        print "\n\n.. c:enum:: " . $name . "\n\n";
      }
      print_lineno($declaration_start_line);
      $lineprefix = "  ";
      $lineprefix = $outer . "  ";
      print $outer . "**Constants**\n\n";
      foreach $parameter (@{$args{'parameterlist'}}) {
 -      print $outer . "``$parameter``\n";
 +        print $outer . "``$parameter``\n";
  
 -      if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
 -          output_highlight_rst($args{'parameterdescs'}{$parameter});
 -      } else {
 -          print $lineprefix . "*undescribed*\n";
 -      }
 -      print "\n";
 +        if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
 +            output_highlight_rst($args{'parameterdescs'}{$parameter});
 +        } else {
 +            print $lineprefix . "*undescribed*\n";
 +        }
 +        print "\n";
      }
      print "\n";
      $lineprefix = $oldprefix;
@@@ -978,9 -979,9 +978,9 @@@ sub output_typedef_rst(%) 
      my $name;
  
      if ($sphinx_major < 3) {
 -      $name = "typedef " . $args{'typedef'};
 +        $name = "typedef " . $args{'typedef'};
      } else {
 -      $name = $args{'typedef'};
 +        $name = $args{'typedef'};
      }
      print "\n\n.. c:type:: " . $name . "\n\n";
      print_lineno($declaration_start_line);
@@@ -998,15 -999,15 +998,15 @@@ sub output_struct_rst(%) 
      my $oldprefix = $lineprefix;
  
      if ($sphinx_major < 3) {
 -      my $name = $args{'type'} . " " . $args{'struct'};
 -      print "\n\n.. c:type:: " . $name . "\n\n";
 +        my $name = $args{'type'} . " " . $args{'struct'};
 +        print "\n\n.. c:type:: " . $name . "\n\n";
      } else {
 -      my $name = $args{'struct'};
 -      if ($args{'type'} eq 'union') {
 -          print "\n\n.. c:union:: " . $name . "\n\n";
 -      } else {
 -          print "\n\n.. c:struct:: " . $name . "\n\n";
 -      }
 +        my $name = $args{'struct'};
 +        if ($args{'type'} eq 'union') {
 +            print "\n\n.. c:union:: " . $name . "\n\n";
 +        } else {
 +            print "\n\n.. c:struct:: " . $name . "\n\n";
 +        }
      }
      print_lineno($declaration_start_line);
      $lineprefix = "  ";
      $lineprefix = "  ";
      print $lineprefix . "**Members**\n\n";
      foreach $parameter (@{$args{'parameterlist'}}) {
 -      ($parameter =~ /^#/) && next;
 +        ($parameter =~ /^#/) && next;
  
 -      my $parameter_name = $parameter;
 -      $parameter_name =~ s/\[.*//;
 +        my $parameter_name = $parameter;
 +        $parameter_name =~ s/\[.*//;
  
 -      ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 -      $type = $args{'parametertypes'}{$parameter};
 +        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 +        $type = $args{'parametertypes'}{$parameter};
          print_lineno($parameterdesc_start_lines{$parameter_name});
 -      print $lineprefix . "``" . $parameter . "``\n";
 -      $lineprefix = "    ";
 -      output_highlight_rst($args{'parameterdescs'}{$parameter_name});
 -      $lineprefix = "  ";
 -      print "\n";
 +        print $lineprefix . "``" . $parameter . "``\n";
 +        $lineprefix = "    ";
 +        output_highlight_rst($args{'parameterdescs'}{$parameter_name});
 +        $lineprefix = "  ";
 +        print "\n";
      }
      print "\n";
  
@@@ -1073,14 -1074,14 +1073,14 @@@ sub output_declaration 
      return if (defined($nosymbol_table{$name}));
  
      if (($output_selection == OUTPUT_ALL) ||
 -      (($output_selection == OUTPUT_INCLUDE ||
 -        $output_selection == OUTPUT_EXPORTED) &&
 -       defined($function_table{$name})) ||
 -      ($output_selection == OUTPUT_INTERNAL &&
 -       !($functype eq "function" && defined($function_table{$name}))))
 +        (($output_selection == OUTPUT_INCLUDE ||
 +          $output_selection == OUTPUT_EXPORTED) &&
 +         defined($function_table{$name})) ||
 +        ($output_selection == OUTPUT_INTERNAL &&
 +         !($functype eq "function" && defined($function_table{$name}))))
      {
 -      &$func(@_);
 -      $section_counter++;
 +        &$func(@_);
 +        $section_counter++;
      }
  }
  
@@@ -1119,202 -1120,203 +1119,202 @@@ sub dump_struct($$) 
      my $struct_members = qr{($type)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;};
  
      if ($x =~ /($type)\s+(\w+)\s*$definition_body/) {
 -      $decl_type = $1;
 -      $declaration_name = $2;
 -      $members = $3;
 +        $decl_type = $1;
 +        $declaration_name = $2;
 +        $members = $3;
      } elsif ($x =~ /typedef\s+($type)\s*$definition_body\s*(\w+)\s*;/) {
 -      $decl_type = $1;
 -      $declaration_name = $3;
 -      $members = $2;
 +        $decl_type = $1;
 +        $declaration_name = $3;
 +        $members = $2;
      }
  
      if ($members) {
 -      if ($identifier ne $declaration_name) {
 -          emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
 -          return;
 -      }
 -
 -      # ignore members marked private:
 -      $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
 -      $members =~ s/\/\*\s*private:.*//gosi;
 -      # strip comments:
 -      $members =~ s/\/\*.*?\*\///gos;
 -      # strip attributes
 -      $members =~ s/\s*$attribute/ /gi;
 -      $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
 -      $members =~ s/\s*__counted_by\s*\([^;]*\)/ /gos;
 -      $members =~ s/\s*__packed\s*/ /gos;
 -      $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
 -      $members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
 -      $members =~ s/\s*____cacheline_aligned/ /gos;
 -      # unwrap struct_group():
 -      # - first eat non-declaration parameters and rewrite for final match
 -      # - then remove macro, outer parens, and trailing semicolon
 -      $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
 -      $members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
 -      $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
 -      $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
 -
 -      my $args = qr{([^,)]+)};
 -      # replace DECLARE_BITMAP
 -      $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
 -      $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;
 -      $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
 -      # replace DECLARE_HASHTABLE
 -      $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
 -      # replace DECLARE_KFIFO
 -      $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;
 -      # replace DECLARE_KFIFO_PTR
 -      $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;
 -      # replace DECLARE_FLEX_ARRAY
 -      $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
 -      #replace DEFINE_DMA_UNMAP_ADDR
 -      $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos;
 -      #replace DEFINE_DMA_UNMAP_LEN
 -      $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos;
 -      my $declaration = $members;
 -
 -      # Split nested struct/union elements as newer ones
 -      while ($members =~ m/$struct_members/) {
 -              my $newmember;
 -              my $maintype = $1;
 -              my $ids = $4;
 -              my $content = $3;
 -              foreach my $id(split /,/, $ids) {
 -                      $newmember .= "$maintype $id; ";
 -
 -                      $id =~ s/[:\[].*//;
 -                      $id =~ s/^\s*\**(\S+)\s*/$1/;
 -                      foreach my $arg (split /;/, $content) {
 -                              next if ($arg =~ m/^\s*$/);
 -                              if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
 -                                      # pointer-to-function
 -                                      my $type = $1;
 -                                      my $name = $2;
 -                                      my $extra = $3;
 -                                      next if (!$name);
 -                                      if ($id =~ m/^\s*$/) {
 -                                              # anonymous struct/union
 -                                              $newmember .= "$type$name$extra; ";
 -                                      } else {
 -                                              $newmember .= "$type$id.$name$extra; ";
 -                                      }
 -                              } else {
 -                                      my $type;
 -                                      my $names;
 -                                      $arg =~ s/^\s+//;
 -                                      $arg =~ s/\s+$//;
 -                                      # Handle bitmaps
 -                                      $arg =~ s/:\s*\d+\s*//g;
 -                                      # Handle arrays
 -                                      $arg =~ s/\[.*\]//g;
 -                                      # The type may have multiple words,
 -                                      # and multiple IDs can be defined, like:
 -                                      #       const struct foo, *bar, foobar
 -                                      # So, we remove spaces when parsing the
 -                                      # names, in order to match just names
 -                                      # and commas for the names
 -                                      $arg =~ s/\s*,\s*/,/g;
 -                                      if ($arg =~ m/(.*)\s+([\S+,]+)/) {
 -                                              $type = $1;
 -                                              $names = $2;
 -                                      } else {
 -                                              $newmember .= "$arg; ";
 -                                              next;
 -                                      }
 -                                      foreach my $name (split /,/, $names) {
 -                                              $name =~ s/^\s*\**(\S+)\s*/$1/;
 -                                              next if (($name =~ m/^\s*$/));
 -                                              if ($id =~ m/^\s*$/) {
 -                                                      # anonymous struct/union
 -                                                      $newmember .= "$type $name; ";
 -                                              } else {
 -                                                      $newmember .= "$type $id.$name; ";
 -                                              }
 -                                      }
 -                              }
 -                      }
 -              }
 -              $members =~ s/$struct_members/$newmember/;
 -      }
 -
 -      # Ignore other nested elements, like enums
 -      $members =~ s/(\{[^\{\}]*\})//g;
 -
 -      create_parameterlist($members, ';', $file, $declaration_name);
 -      check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
 -
 -      # Adjust declaration for better display
 -      $declaration =~ s/([\{;])/$1\n/g;
 -      $declaration =~ s/\}\s+;/};/g;
 -      # Better handle inlined enums
 -      do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
 -
 -      my @def_args = split /\n/, $declaration;
 -      my $level = 1;
 -      $declaration = "";
 -      foreach my $clause (@def_args) {
 -              $clause =~ s/^\s+//;
 -              $clause =~ s/\s+$//;
 -              $clause =~ s/\s+/ /;
 -              next if (!$clause);
 -              $level-- if ($clause =~ m/(\})/ && $level > 1);
 -              if (!($clause =~ m/^\s*#/)) {
 -                      $declaration .= "\t" x $level;
 -              }
 -              $declaration .= "\t" . $clause . "\n";
 -              $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
 -      }
 -      output_declaration($declaration_name,
 -                         'struct',
 -                         {'struct' => $declaration_name,
 -                          'module' => $modulename,
 -                          'definition' => $declaration,
 -                          'parameterlist' => \@parameterlist,
 -                          'parameterdescs' => \%parameterdescs,
 -                          'parametertypes' => \%parametertypes,
 -                          'sectionlist' => \@sectionlist,
 -                          'sections' => \%sections,
 -                          'purpose' => $declaration_purpose,
 -                          'type' => $decl_type
 -                         });
 -    }
 -    else {
 -      print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
 -      ++$errors;
 +        if ($identifier ne $declaration_name) {
 +            emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
 +            return;
 +        }
 +
 +        # ignore members marked private:
 +        $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
 +        $members =~ s/\/\*\s*private:.*//gosi;
 +        # strip comments:
 +        $members =~ s/\/\*.*?\*\///gos;
 +        # strip attributes
 +        $members =~ s/\s*$attribute/ /gi;
 +        $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
 +        $members =~ s/\s*__counted_by\s*\([^;]*\)/ /gos;
 +        $members =~ s/\s*__packed\s*/ /gos;
 +        $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
 +        $members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
 +        $members =~ s/\s*____cacheline_aligned/ /gos;
 +        # unwrap struct_group():
 +        # - first eat non-declaration parameters and rewrite for final match
 +        # - then remove macro, outer parens, and trailing semicolon
 +        $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
 +        $members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
 +        $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
 +        $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
 +
 +        my $args = qr{([^,)]+)};
 +        # replace DECLARE_BITMAP
 +        $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
 +        $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;
 +        $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
 +        # replace DECLARE_HASHTABLE
 +        $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
 +        # replace DECLARE_KFIFO
 +        $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;
 +        # replace DECLARE_KFIFO_PTR
 +        $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;
 +        # replace DECLARE_FLEX_ARRAY
 +        $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
 +        #replace DEFINE_DMA_UNMAP_ADDR
 +        $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos;
 +        #replace DEFINE_DMA_UNMAP_LEN
 +        $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos;
 +        my $declaration = $members;
 +
 +        # Split nested struct/union elements as newer ones
 +        while ($members =~ m/$struct_members/) {
 +            my $newmember;
 +            my $maintype = $1;
 +            my $ids = $4;
 +            my $content = $3;
 +            foreach my $id(split /,/, $ids) {
 +                $newmember .= "$maintype $id; ";
 +
 +                $id =~ s/[:\[].*//;
 +                $id =~ s/^\s*\**(\S+)\s*/$1/;
 +                foreach my $arg (split /;/, $content) {
 +                    next if ($arg =~ m/^\s*$/);
 +                    if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
 +                        # pointer-to-function
 +                        my $type = $1;
 +                        my $name = $2;
 +                        my $extra = $3;
 +                        next if (!$name);
 +                        if ($id =~ m/^\s*$/) {
 +                            # anonymous struct/union
 +                            $newmember .= "$type$name$extra; ";
 +                        } else {
 +                            $newmember .= "$type$id.$name$extra; ";
 +                        }
 +                    } else {
 +                        my $type;
 +                        my $names;
 +                        $arg =~ s/^\s+//;
 +                        $arg =~ s/\s+$//;
 +                        # Handle bitmaps
 +                        $arg =~ s/:\s*\d+\s*//g;
 +                        # Handle arrays
 +                        $arg =~ s/\[.*\]//g;
 +                        # The type may have multiple words,
 +                        # and multiple IDs can be defined, like:
 +                        #    const struct foo, *bar, foobar
 +                        # So, we remove spaces when parsing the
 +                        # names, in order to match just names
 +                        # and commas for the names
 +                        $arg =~ s/\s*,\s*/,/g;
 +                        if ($arg =~ m/(.*)\s+([\S+,]+)/) {
 +                            $type = $1;
 +                            $names = $2;
 +                        } else {
 +                            $newmember .= "$arg; ";
 +                            next;
 +                        }
 +                        foreach my $name (split /,/, $names) {
 +                            $name =~ s/^\s*\**(\S+)\s*/$1/;
 +                            next if (($name =~ m/^\s*$/));
 +                            if ($id =~ m/^\s*$/) {
 +                                # anonymous struct/union
 +                                $newmember .= "$type $name; ";
 +                            } else {
 +                                $newmember .= "$type $id.$name; ";
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +            $members =~ s/$struct_members/$newmember/;
 +        }
 +
 +        # Ignore other nested elements, like enums
 +        $members =~ s/(\{[^\{\}]*\})//g;
 +
 +        create_parameterlist($members, ';', $file, $declaration_name);
 +        check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
 +
 +        # Adjust declaration for better display
 +        $declaration =~ s/([\{;])/$1\n/g;
 +        $declaration =~ s/\}\s+;/};/g;
 +        # Better handle inlined enums
 +        do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
 +
 +        my @def_args = split /\n/, $declaration;
 +        my $level = 1;
 +        $declaration = "";
 +        foreach my $clause (@def_args) {
 +            $clause =~ s/^\s+//;
 +            $clause =~ s/\s+$//;
 +            $clause =~ s/\s+/ /;
 +            next if (!$clause);
 +            $level-- if ($clause =~ m/(\})/ && $level > 1);
 +            if (!($clause =~ m/^\s*#/)) {
 +                $declaration .= "\t" x $level;
 +            }
 +            $declaration .= "\t" . $clause . "\n";
 +            $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
 +        }
 +        output_declaration($declaration_name,
 +                   'struct',
 +                   {'struct' => $declaration_name,
 +                    'module' => $modulename,
 +                    'definition' => $declaration,
 +                    'parameterlist' => \@parameterlist,
 +                    'parameterdescs' => \%parameterdescs,
 +                    'parametertypes' => \%parametertypes,
 +                    'sectionlist' => \@sectionlist,
 +                    'sections' => \%sections,
 +                    'purpose' => $declaration_purpose,
 +                    'type' => $decl_type
 +                   });
 +    } else {
 +        print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
 +        ++$errors;
      }
  }
  
  
  sub show_warnings($$) {
 -      my $functype = shift;
 -      my $name = shift;
 -
 -      return 0 if (defined($nosymbol_table{$name}));
 -
 -      return 1 if ($output_selection == OUTPUT_ALL);
 -
 -      if ($output_selection == OUTPUT_EXPORTED) {
 -              if (defined($function_table{$name})) {
 -                      return 1;
 -              } else {
 -                      return 0;
 -              }
 -      }
 -        if ($output_selection == OUTPUT_INTERNAL) {
 -              if (!($functype eq "function" && defined($function_table{$name}))) {
 -                      return 1;
 -              } else {
 -                      return 0;
 -              }
 -      }
 -      if ($output_selection == OUTPUT_INCLUDE) {
 -              if (defined($function_table{$name})) {
 -                      return 1;
 -              } else {
 -                      return 0;
 -              }
 -      }
 -      die("Please add the new output type at show_warnings()");
 +    my $functype = shift;
 +    my $name = shift;
 +
 +    return 0 if (defined($nosymbol_table{$name}));
 +
 +    return 1 if ($output_selection == OUTPUT_ALL);
 +
 +    if ($output_selection == OUTPUT_EXPORTED) {
 +        if (defined($function_table{$name})) {
 +            return 1;
 +        } else {
 +            return 0;
 +        }
 +    }
 +    if ($output_selection == OUTPUT_INTERNAL) {
 +        if (!($functype eq "function" && defined($function_table{$name}))) {
 +            return 1;
 +        } else {
 +            return 0;
 +        }
 +    }
 +    if ($output_selection == OUTPUT_INCLUDE) {
 +        if (defined($function_table{$name})) {
 +            return 1;
 +        } else {
 +            return 0;
 +        }
 +    }
 +    die("Please add the new output type at show_warnings()");
  }
  
  sub dump_enum($$) {
  
      $x =~ s@/\*.*?\*/@@gos;   # strip comments.
      # strip #define macros inside enums
 -    $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
 +    $x =~ s@#\s*((define|ifdef|if)\s+|endif)[^;]*;@@gos;
  
      if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) {
 -      $declaration_name = $2;
 -      $members = $1;
 +        $declaration_name = $2;
 +        $members = $1;
      } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
 -      $declaration_name = $1;
 -      $members = $2;
 +        $declaration_name = $1;
 +        $members = $2;
      }
  
      if ($members) {
 -      if ($identifier ne $declaration_name) {
 -          if ($identifier eq "") {
 -              emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
 -          } else {
 -              emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
 -          }
 -          return;
 -      }
 -      $declaration_name = "(anonymous)" if ($declaration_name eq "");
 -
 -      my %_members;
 -
 -      $members =~ s/\s+$//;
 -      $members =~ s/\([^;]*?[\)]//g;
 -
 -      foreach my $arg (split ',', $members) {
 -          $arg =~ s/^\s*(\w+).*/$1/;
 -          push @parameterlist, $arg;
 -          if (!$parameterdescs{$arg}) {
 -              $parameterdescs{$arg} = $undescribed;
 -              if (show_warnings("enum", $declaration_name)) {
 -                      emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
 -              }
 -          }
 -          $_members{$arg} = 1;
 -      }
 -
 -      while (my ($k, $v) = each %parameterdescs) {
 -          if (!exists($_members{$k})) {
 -              if (show_warnings("enum", $declaration_name)) {
 -                   emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
 -              }
 -          }
 -        }
 -
 -      output_declaration($declaration_name,
 -                         'enum',
 -                         {'enum' => $declaration_name,
 -                          'module' => $modulename,
 -                          'parameterlist' => \@parameterlist,
 -                          'parameterdescs' => \%parameterdescs,
 -                          'sectionlist' => \@sectionlist,
 -                          'sections' => \%sections,
 -                          'purpose' => $declaration_purpose
 -                         });
 +        if ($identifier ne $declaration_name) {
 +            if ($identifier eq "") {
 +                emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
 +            } else {
 +                emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
 +            }
 +            return;
 +        }
 +        $declaration_name = "(anonymous)" if ($declaration_name eq "");
 +
 +        my %_members;
 +
 +        $members =~ s/\s+$//;
 +        $members =~ s/\([^;]*?[\)]//g;
 +
 +        foreach my $arg (split ',', $members) {
 +            $arg =~ s/^\s*(\w+).*/$1/;
 +            push @parameterlist, $arg;
 +            if (!$parameterdescs{$arg}) {
 +                $parameterdescs{$arg} = $undescribed;
 +                if (show_warnings("enum", $declaration_name)) {
 +                    emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
 +                }
 +            }
 +            $_members{$arg} = 1;
 +        }
 +
 +        while (my ($k, $v) = each %parameterdescs) {
 +            if (!exists($_members{$k})) {
 +                if (show_warnings("enum", $declaration_name)) {
 +                    emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
 +                }
 +            }
 +        }
 +
 +        output_declaration($declaration_name,
 +                           'enum',
 +                           {'enum' => $declaration_name,
 +                            'module' => $modulename,
 +                            'parameterlist' => \@parameterlist,
 +                            'parameterdescs' => \%parameterdescs,
 +                            'sectionlist' => \@sectionlist,
 +                            'sections' => \%sections,
 +                            'purpose' => $declaration_purpose
 +                           });
      } else {
 -      print STDERR "${file}:$.: error: Cannot parse enum!\n";
 -      ++$errors;
 +        print STDERR "${file}:$.: error: Cannot parse enum!\n";
 +        ++$errors;
      }
  }
  
@@@ -1405,58 -1407,59 +1405,58 @@@ sub dump_typedef($$) 
  
      # Parse function typedef prototypes
      if ($x =~ $typedef1 || $x =~ $typedef2) {
 -      $return_type = $1;
 -      $declaration_name = $2;
 -      my $args = $3;
 -      $return_type =~ s/^\s+//;
 -
 -      if ($identifier ne $declaration_name) {
 -          emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
 -          return;
 -      }
 -
 -      create_parameterlist($args, ',', $file, $declaration_name);
 -
 -      output_declaration($declaration_name,
 -                         'function',
 -                         {'function' => $declaration_name,
 -                          'typedef' => 1,
 -                          'module' => $modulename,
 -                          'functiontype' => $return_type,
 -                          'parameterlist' => \@parameterlist,
 -                          'parameterdescs' => \%parameterdescs,
 -                          'parametertypes' => \%parametertypes,
 -                          'sectionlist' => \@sectionlist,
 -                          'sections' => \%sections,
 -                          'purpose' => $declaration_purpose
 -                         });
 -      return;
 +        $return_type = $1;
 +        $declaration_name = $2;
 +        my $args = $3;
 +        $return_type =~ s/^\s+//;
 +
 +        if ($identifier ne $declaration_name) {
 +            emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
 +            return;
 +        }
 +
 +        create_parameterlist($args, ',', $file, $declaration_name);
 +
 +        output_declaration($declaration_name,
 +                           'function',
 +                           {'function' => $declaration_name,
 +                            'typedef' => 1,
 +                            'module' => $modulename,
 +                            'functiontype' => $return_type,
 +                            'parameterlist' => \@parameterlist,
 +                            'parameterdescs' => \%parameterdescs,
 +                            'parametertypes' => \%parametertypes,
 +                            'sectionlist' => \@sectionlist,
 +                            'sections' => \%sections,
 +                            'purpose' => $declaration_purpose
 +                           });
 +        return;
      }
  
      while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
 -      $x =~ s/\(*.\)\s*;$/;/;
 -      $x =~ s/\[*.\]\s*;$/;/;
 +        $x =~ s/\(*.\)\s*;$/;/;
 +        $x =~ s/\[*.\]\s*;$/;/;
      }
  
      if ($x =~ /typedef.*\s+(\w+)\s*;/) {
 -      $declaration_name = $1;
 +        $declaration_name = $1;
  
 -      if ($identifier ne $declaration_name) {
 -          emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
 -          return;
 -      }
 +        if ($identifier ne $declaration_name) {
 +            emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
 +            return;
 +        }
  
 -      output_declaration($declaration_name,
 -                         'typedef',
 -                         {'typedef' => $declaration_name,
 -                          'module' => $modulename,
 -                          'sectionlist' => \@sectionlist,
 -                          'sections' => \%sections,
 -                          'purpose' => $declaration_purpose
 -                         });
 -    }
 -    else {
 -      print STDERR "${file}:$.: error: Cannot parse typedef!\n";
 -      ++$errors;
 +        output_declaration($declaration_name,
 +                           'typedef',
 +                           {'typedef' => $declaration_name,
 +                            'module' => $modulename,
 +                            'sectionlist' => \@sectionlist,
 +                            'sections' => \%sections,
 +                            'purpose' => $declaration_purpose
 +                           });
 +    } else {
 +        print STDERR "${file}:$.: error: Cannot parse typedef!\n";
 +        ++$errors;
      }
  }
  
@@@ -1479,220 -1482,214 +1479,220 @@@ sub create_parameterlist($$$$) 
      # temporarily replace commas inside function pointer definition
      my $arg_expr = qr{\([^\),]+};
      while ($args =~ /$arg_expr,/) {
 -      $args =~ s/($arg_expr),/$1#/g;
 +        $args =~ s/($arg_expr),/$1#/g;
      }
  
      foreach my $arg (split($splitter, $args)) {
 -      # strip comments
 -      $arg =~ s/\/\*.*\*\///;
 -      # ignore argument attributes
 -      $arg =~ s/\sPOS0?\s/ /;
 -      # strip leading/trailing spaces
 -      $arg =~ s/^\s*//;
 -      $arg =~ s/\s*$//;
 -      $arg =~ s/\s+/ /;
 -
 -      if ($arg =~ /^#/) {
 -          # Treat preprocessor directive as a typeless variable just to fill
 -          # corresponding data structures "correctly". Catch it later in
 -          # output_* subs.
 -          push_parameter($arg, "", "", $file);
 -      } elsif ($arg =~ m/\(.+\)\s*\(/) {
 -          # pointer-to-function
 -          $arg =~ tr/#/,/;
 -          $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
 -          $param = $1;
 -          $type = $arg;
 -          $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
 -          save_struct_actual($param);
 -          push_parameter($param, $type, $arg, $file, $declaration_name);
 -      } elsif ($arg) {
 -          $arg =~ s/\s*:\s*/:/g;
 -          $arg =~ s/\s*\[/\[/g;
 -
 -          my @args = split('\s*,\s*', $arg);
 -          if ($args[0] =~ m/\*/) {
 -              $args[0] =~ s/(\*+)\s*/ $1/;
 -          }
 -
 -          my @first_arg;
 -          if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
 -                  shift @args;
 -                  push(@first_arg, split('\s+', $1));
 -                  push(@first_arg, $2);
 -          } else {
 -                  @first_arg = split('\s+', shift @args);
 -          }
 -
 -          unshift(@args, pop @first_arg);
 -          $type = join " ", @first_arg;
 -
 -          foreach $param (@args) {
 -              if ($param =~ m/^(\*+)\s*(.*)/) {
 -                  save_struct_actual($2);
 -
 -                  push_parameter($2, "$type $1", $arg, $file, $declaration_name);
 -              }
 -              elsif ($param =~ m/(.*?):(\d+)/) {
 -                  if ($type ne "") { # skip unnamed bit-fields
 -                      save_struct_actual($1);
 -                      push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
 -                  }
 -              }
 -              else {
 -                  save_struct_actual($param);
 -                  push_parameter($param, $type, $arg, $file, $declaration_name);
 -              }
 -          }
 -      }
 +        # strip comments
 +        $arg =~ s/\/\*.*\*\///;
 +        # ignore argument attributes
 +        $arg =~ s/\sPOS0?\s/ /;
 +        # strip leading/trailing spaces
 +        $arg =~ s/^\s*//;
 +        $arg =~ s/\s*$//;
 +        $arg =~ s/\s+/ /;
 +
 +        if ($arg =~ /^#/) {
 +            # Treat preprocessor directive as a typeless variable just to fill
 +            # corresponding data structures "correctly". Catch it later in
 +            # output_* subs.
 +            push_parameter($arg, "", "", $file);
 +        } elsif ($arg =~ m/\(.+\)\s*\(/) {
 +            # pointer-to-function
 +            $arg =~ tr/#/,/;
 +            $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
 +            $param = $1;
 +            $type = $arg;
 +            $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
 +            save_struct_actual($param);
 +            push_parameter($param, $type, $arg, $file, $declaration_name);
 +        } elsif ($arg =~ m/\(.+\)\s*\[/) {
 +            # array-of-pointers
 +            $arg =~ tr/#/,/;
 +            $arg =~ m/[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[\w]+\s*\]\s*)*\)/;
 +            $param = $1;
 +            $type = $arg;
 +            $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
 +            save_struct_actual($param);
 +            push_parameter($param, $type, $arg, $file, $declaration_name);
 +        } elsif ($arg) {
 +            $arg =~ s/\s*:\s*/:/g;
 +            $arg =~ s/\s*\[/\[/g;
 +
 +            my @args = split('\s*,\s*', $arg);
 +            if ($args[0] =~ m/\*/) {
 +                $args[0] =~ s/(\*+)\s*/ $1/;
 +            }
 +
 +            my @first_arg;
 +            if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
 +                shift @args;
 +                push(@first_arg, split('\s+', $1));
 +                push(@first_arg, $2);
 +            } else {
 +                @first_arg = split('\s+', shift @args);
 +            }
 +
 +            unshift(@args, pop @first_arg);
 +            $type = join " ", @first_arg;
 +
 +            foreach $param (@args) {
 +                if ($param =~ m/^(\*+)\s*(.*)/) {
 +                    save_struct_actual($2);
 +
 +                    push_parameter($2, "$type $1", $arg, $file, $declaration_name);
 +                } elsif ($param =~ m/(.*?):(\d+)/) {
 +                    if ($type ne "") { # skip unnamed bit-fields
 +                        save_struct_actual($1);
 +                        push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
 +                    }
 +                } else {
 +                    save_struct_actual($param);
 +                    push_parameter($param, $type, $arg, $file, $declaration_name);
 +                }
 +            }
 +        }
      }
  }
  
  sub push_parameter($$$$$) {
 -      my $param = shift;
 -      my $type = shift;
 -      my $org_arg = shift;
 -      my $file = shift;
 -      my $declaration_name = shift;
 -
 -      if (($anon_struct_union == 1) && ($type eq "") &&
 -          ($param eq "}")) {
 -              return;         # ignore the ending }; from anon. struct/union
 -      }
 -
 -      $anon_struct_union = 0;
 -      $param =~ s/[\[\)].*//;
 -
 -      if ($type eq "" && $param =~ /\.\.\.$/)
 -      {
 -          if (!$param =~ /\w\.\.\.$/) {
 -            # handles unnamed variable parameters
 -            $param = "...";
 -          }
 -          elsif ($param =~ /\w\.\.\.$/) {
 -            # for named variable parameters of the form `x...`, remove the dots
 -            $param =~ s/\.\.\.$//;
 -          }
 -          if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
 -              $parameterdescs{$param} = "variable arguments";
 -          }
 -      }
 -      elsif ($type eq "" && ($param eq "" or $param eq "void"))
 -      {
 -          $param="void";
 -          $parameterdescs{void} = "no arguments";
 -      }
 -      elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
 -      # handle unnamed (anonymous) union or struct:
 -      {
 -              $type = $param;
 -              $param = "{unnamed_" . $param . "}";
 -              $parameterdescs{$param} = "anonymous\n";
 -              $anon_struct_union = 1;
 -      }
 -      elsif ($param =~ "__cacheline_group" )
 -      # handle cache group enforcing variables: they do not need be described in header files
 -      {
 -              return; # ignore __cacheline_group_begin and __cacheline_group_end
 -      }
 -
 -      # warn if parameter has no description
 -      # (but ignore ones starting with # as these are not parameters
 -      # but inline preprocessor statements);
 -      # Note: It will also ignore void params and unnamed structs/unions
 -      if (!defined $parameterdescs{$param} && $param !~ /^#/) {
 -              $parameterdescs{$param} = $undescribed;
 -
 -              if (show_warnings($type, $declaration_name) && $param !~ /\./) {
 -                      emit_warning("${file}:$.", "Function parameter or struct member '$param' not described in '$declaration_name'\n");
 -              }
 -      }
 -
 -      # strip spaces from $param so that it is one continuous string
 -      # on @parameterlist;
 -      # this fixes a problem where check_sections() cannot find
 -      # a parameter like "addr[6 + 2]" because it actually appears
 -      # as "addr[6", "+", "2]" on the parameter list;
 -      # but it's better to maintain the param string unchanged for output,
 -      # so just weaken the string compare in check_sections() to ignore
 -      # "[blah" in a parameter string;
 -      ###$param =~ s/\s*//g;
 -      push @parameterlist, $param;
 -      $org_arg =~ s/\s\s+/ /g;
 -      $parametertypes{$param} = $org_arg;
 +    my $param = shift;
 +    my $type = shift;
 +    my $org_arg = shift;
 +    my $file = shift;
 +    my $declaration_name = shift;
 +
 +    if (($anon_struct_union == 1) && ($type eq "") &&
 +        ($param eq "}")) {
 +        return;        # ignore the ending }; from anon. struct/union
 +    }
 +
 +    $anon_struct_union = 0;
 +    $param =~ s/[\[\)].*//;
 +
 +    if ($type eq "" && $param =~ /\.\.\.$/)
 +    {
 +        if (!$param =~ /\w\.\.\.$/) {
 +            # handles unnamed variable parameters
 +            $param = "...";
 +        } elsif ($param =~ /\w\.\.\.$/) {
 +            # for named variable parameters of the form `x...`, remove the dots
 +            $param =~ s/\.\.\.$//;
 +        }
 +        if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
 +            $parameterdescs{$param} = "variable arguments";
 +        }
 +    }
 +    elsif ($type eq "" && ($param eq "" or $param eq "void"))
 +    {
 +        $param="void";
 +        $parameterdescs{void} = "no arguments";
 +    }
 +    elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
 +    # handle unnamed (anonymous) union or struct:
 +    {
 +        $type = $param;
 +        $param = "{unnamed_" . $param . "}";
 +        $parameterdescs{$param} = "anonymous\n";
 +        $anon_struct_union = 1;
 +    }
 +    elsif ($param =~ "__cacheline_group" )
 +    # handle cache group enforcing variables: they do not need be described in header files
 +    {
 +        return; # ignore __cacheline_group_begin and __cacheline_group_end
 +    }
 +
 +    # warn if parameter has no description
 +    # (but ignore ones starting with # as these are not parameters
 +    # but inline preprocessor statements);
 +    # Note: It will also ignore void params and unnamed structs/unions
 +    if (!defined $parameterdescs{$param} && $param !~ /^#/) {
 +        $parameterdescs{$param} = $undescribed;
 +
 +        if (show_warnings($type, $declaration_name) && $param !~ /\./) {
 +            emit_warning("${file}:$.", "Function parameter or struct member '$param' not described in '$declaration_name'\n");
 +        }
 +    }
 +
 +    # strip spaces from $param so that it is one continuous string
 +    # on @parameterlist;
 +    # this fixes a problem where check_sections() cannot find
 +    # a parameter like "addr[6 + 2]" because it actually appears
 +    # as "addr[6", "+", "2]" on the parameter list;
 +    # but it's better to maintain the param string unchanged for output,
 +    # so just weaken the string compare in check_sections() to ignore
 +    # "[blah" in a parameter string;
 +    ###$param =~ s/\s*//g;
 +    push @parameterlist, $param;
 +    $org_arg =~ s/\s\s+/ /g;
 +    $parametertypes{$param} = $org_arg;
  }
  
  sub check_sections($$$$$) {
 -      my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
 -      my @sects = split ' ', $sectcheck;
 -      my @prms = split ' ', $prmscheck;
 -      my $err;
 -      my ($px, $sx);
 -      my $prm_clean;          # strip trailing "[array size]" and/or beginning "*"
 -
 -      foreach $sx (0 .. $#sects) {
 -              $err = 1;
 -              foreach $px (0 .. $#prms) {
 -                      $prm_clean = $prms[$px];
 -                      $prm_clean =~ s/\[.*\]//;
 -                      $prm_clean =~ s/$attribute//i;
 -                      # ignore array size in a parameter string;
 -                      # however, the original param string may contain
 -                      # spaces, e.g.:  addr[6 + 2]
 -                      # and this appears in @prms as "addr[6" since the
 -                      # parameter list is split at spaces;
 -                      # hence just ignore "[..." for the sections check;
 -                      $prm_clean =~ s/\[.*//;
 -
 -                      ##$prm_clean =~ s/^\**//;
 -                      if ($prm_clean eq $sects[$sx]) {
 -                              $err = 0;
 -                              last;
 -                      }
 -              }
 -              if ($err) {
 -                      if ($decl_type eq "function") {
 -                              emit_warning("${file}:$.",
 -                                      "Excess function parameter " .
 -                                      "'$sects[$sx]' " .
 -                                      "description in '$decl_name'\n");
 -                      }
 -                      elsif (($decl_type eq "struct") or
 -                             ($decl_type eq "union")) {
 -                              emit_warning("${file}:$.",
 -                                      "Excess $decl_type member " .
 -                                      "'$sects[$sx]' " .
 -                                      "description in '$decl_name'\n");
 -                      }
 -              }
 -      }
 +    my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
 +    my @sects = split ' ', $sectcheck;
 +    my @prms = split ' ', $prmscheck;
 +    my $err;
 +    my ($px, $sx);
 +    my $prm_clean;        # strip trailing "[array size]" and/or beginning "*"
 +
 +    foreach $sx (0 .. $#sects) {
 +        $err = 1;
 +        foreach $px (0 .. $#prms) {
 +            $prm_clean = $prms[$px];
 +            $prm_clean =~ s/\[.*\]//;
 +            $prm_clean =~ s/$attribute//i;
 +            # ignore array size in a parameter string;
 +            # however, the original param string may contain
 +            # spaces, e.g.:  addr[6 + 2]
 +            # and this appears in @prms as "addr[6" since the
 +            # parameter list is split at spaces;
 +            # hence just ignore "[..." for the sections check;
 +            $prm_clean =~ s/\[.*//;
 +
 +            ##$prm_clean =~ s/^\**//;
 +            if ($prm_clean eq $sects[$sx]) {
 +                $err = 0;
 +                last;
 +            }
 +        }
 +        if ($err) {
 +            if ($decl_type eq "function") {
 +                emit_warning("${file}:$.",
 +                    "Excess function parameter " .
 +                    "'$sects[$sx]' " .
 +                    "description in '$decl_name'\n");
 +            } elsif (($decl_type eq "struct") or
 +                          ($decl_type eq "union")) {
 +                emit_warning("${file}:$.",
 +                    "Excess $decl_type member " .
 +                    "'$sects[$sx]' " .
 +                    "description in '$decl_name'\n");
 +            }
 +        }
 +    }
  }
  
  ##
  # Checks the section describing the return value of a function.
  sub check_return_section {
 -        my $file = shift;
 -        my $declaration_name = shift;
 -        my $return_type = shift;
 +    my $file = shift;
 +    my $declaration_name = shift;
 +    my $return_type = shift;
  
 -        # Ignore an empty return type (It's a macro)
 -        # Ignore functions with a "void" return type. (But don't ignore "void *")
 -        if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
 -                return;
 -        }
 +    # Ignore an empty return type (It's a macro)
 +    # Ignore functions with a "void" return type. (But don't ignore "void *")
 +    if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
 +        return;
 +    }
  
 -        if (!defined($sections{$section_return}) ||
 -            $sections{$section_return} eq "") {
 -                emit_warning("${file}:$.",
 -                        "No description found for return value of " .
 -                        "'$declaration_name'\n");
 -        }
 +    if (!defined($sections{$section_return}) ||
 +        $sections{$section_return} eq "")
 +    {
 +        emit_warning("${file}:$.",
 +                     "No description found for return value of " .
 +                     "'$declaration_name'\n");
 +    }
  }
  
  ##
@@@ -1767,21 -1764,21 +1767,21 @@@ sub dump_function($$) 
          $declaration_name = $2;
          $noret = 1;
      } elsif ($prototype =~ m/^()($name)\s*$prototype_end/ ||
 -      $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ ||
 -      $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/)  {
 -      $return_type = $1;
 -      $declaration_name = $2;
 -      my $args = $3;
 +        $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ ||
 +        $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/)  {
 +        $return_type = $1;
 +        $declaration_name = $2;
 +        my $args = $3;
  
 -      create_parameterlist($args, ',', $file, $declaration_name);
 +        create_parameterlist($args, ',', $file, $declaration_name);
      } else {
 -      emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
 -      return;
 +        emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
 +        return;
      }
  
      if ($identifier ne $declaration_name) {
 -      emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
 -      return;
 +        emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
 +        return;
      }
  
      my $prms = join " ", @parameterlist;
      # -Wreturn mode.
      # TODO: always perform the check.
      if ($Wreturn && !$noret) {
 -          check_return_section($file, $declaration_name, $return_type);
 +        check_return_section($file, $declaration_name, $return_type);
      }
  
      # The function parser can be called with a typedef parameter.
      # Handle it.
      if ($return_type =~ /typedef/) {
 -      output_declaration($declaration_name,
 -                         'function',
 -                         {'function' => $declaration_name,
 -                          'typedef' => 1,
 -                          'module' => $modulename,
 -                          'functiontype' => $return_type,
 -                          'parameterlist' => \@parameterlist,
 -                          'parameterdescs' => \%parameterdescs,
 -                          'parametertypes' => \%parametertypes,
 -                          'sectionlist' => \@sectionlist,
 -                          'sections' => \%sections,
 -                          'purpose' => $declaration_purpose
 -                         });
 +        output_declaration($declaration_name,
 +                           'function',
 +                           {'function' => $declaration_name,
 +                            'typedef' => 1,
 +                            'module' => $modulename,
 +                            'functiontype' => $return_type,
 +                            'parameterlist' => \@parameterlist,
 +                            'parameterdescs' => \%parameterdescs,
 +                            'parametertypes' => \%parametertypes,
 +                            'sectionlist' => \@sectionlist,
 +                            'sections' => \%sections,
 +                            'purpose' => $declaration_purpose
 +                           });
      } else {
 -      output_declaration($declaration_name,
 -                         'function',
 -                         {'function' => $declaration_name,
 -                          'module' => $modulename,
 -                          'functiontype' => $return_type,
 -                          'parameterlist' => \@parameterlist,
 -                          'parameterdescs' => \%parameterdescs,
 -                          'parametertypes' => \%parametertypes,
 -                          'sectionlist' => \@sectionlist,
 -                          'sections' => \%sections,
 -                          'purpose' => $declaration_purpose
 -                         });
 +        output_declaration($declaration_name,
 +                           'function',
 +                           {'function' => $declaration_name,
 +                            'module' => $modulename,
 +                            'functiontype' => $return_type,
 +                            'parameterlist' => \@parameterlist,
 +                            'parameterdescs' => \%parameterdescs,
 +                            'parametertypes' => \%parametertypes,
 +                            'sectionlist' => \@sectionlist,
 +                            'sections' => \%sections,
 +                            'purpose' => $declaration_purpose
 +                           });
      }
  }
  
@@@ -1844,64 -1841,64 +1844,64 @@@ sub reset_state 
  }
  
  sub tracepoint_munge($) {
 -      my $file = shift;
 -      my $tracepointname = 0;
 -      my $tracepointargs = 0;
 -
 -      if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
 -              $tracepointname = $1;
 -      }
 -      if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
 -              $tracepointname = $1;
 -      }
 -      if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
 -              $tracepointname = $2;
 -      }
 -      $tracepointname =~ s/^\s+//; #strip leading whitespace
 -      if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
 -              $tracepointargs = $1;
 -      }
 -      if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
 -              emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
 -                           "$prototype\n");
 -      } else {
 -              $prototype = "static inline void trace_$tracepointname($tracepointargs)";
 -              $identifier = "trace_$identifier";
 -      }
 +    my $file = shift;
 +    my $tracepointname = 0;
 +    my $tracepointargs = 0;
 +
 +    if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
 +        $tracepointname = $1;
 +    }
 +    if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
 +        $tracepointname = $1;
 +    }
 +    if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
 +        $tracepointname = $2;
 +    }
 +    $tracepointname =~ s/^\s+//; #strip leading whitespace
 +    if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
 +        $tracepointargs = $1;
 +    }
 +    if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
 +        emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
 +                 "$prototype\n");
 +    } else {
 +        $prototype = "static inline void trace_$tracepointname($tracepointargs)";
 +        $identifier = "trace_$identifier";
 +    }
  }
  
  sub syscall_munge() {
 -      my $void = 0;
 -
 -      $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
 -##    if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
 -      if ($prototype =~ m/SYSCALL_DEFINE0/) {
 -              $void = 1;
 -##            $prototype = "long sys_$1(void)";
 -      }
 -
 -      $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
 -      if ($prototype =~ m/long (sys_.*?),/) {
 -              $prototype =~ s/,/\(/;
 -      } elsif ($void) {
 -              $prototype =~ s/\)/\(void\)/;
 -      }
 -
 -      # now delete all of the odd-number commas in $prototype
 -      # so that arg types & arg names don't have a comma between them
 -      my $count = 0;
 -      my $len = length($prototype);
 -      if ($void) {
 -              $len = 0;       # skip the for-loop
 -      }
 -      for (my $ix = 0; $ix < $len; $ix++) {
 -              if (substr($prototype, $ix, 1) eq ',') {
 -                      $count++;
 -                      if ($count % 2 == 1) {
 -                              substr($prototype, $ix, 1) = ' ';
 -                      }
 -              }
 -      }
 +    my $void = 0;
 +
 +    $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
 +##    if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
 +    if ($prototype =~ m/SYSCALL_DEFINE0/) {
 +        $void = 1;
 +##        $prototype = "long sys_$1(void)";
 +    }
 +
 +    $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
 +    if ($prototype =~ m/long (sys_.*?),/) {
 +        $prototype =~ s/,/\(/;
 +    } elsif ($void) {
 +        $prototype =~ s/\)/\(void\)/;
 +    }
 +
 +    # now delete all of the odd-number commas in $prototype
 +    # so that arg types & arg names don't have a comma between them
 +    my $count = 0;
 +    my $len = length($prototype);
 +    if ($void) {
 +        $len = 0;    # skip the for-loop
 +    }
 +    for (my $ix = 0; $ix < $len; $ix++) {
 +        if (substr($prototype, $ix, 1) eq ',') {
 +            $count++;
 +            if ($count % 2 == 1) {
 +                substr($prototype, $ix, 1) = ' ';
 +            }
 +        }
 +    }
  }
  
  sub process_proto_function($$) {
  
      $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
  
 -    if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {
 -      # do nothing
 -    }
 -    elsif ($x =~ /([^\{]*)/) {
 -      $prototype .= $1;
 +    if ($x =~ /^#/ && $x !~ /^#\s*define/) {
 +        # do nothing
 +    } elsif ($x =~ /([^\{]*)/) {
 +        $prototype .= $1;
      }
  
      if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
 -      $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
 -      $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
 -      $prototype =~ s@^\s+@@gos; # strip leading spaces
 +        $prototype =~ s@/\*.*?\*/@@gos;        # strip comments.
 +        $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
 +        $prototype =~ s@^\s+@@gos; # strip leading spaces
  
 -       # Handle prototypes for function pointers like:
 -       # int (*pcs_config)(struct foo)
 -      $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
 +        # Handle prototypes for function pointers like:
 +        # int (*pcs_config)(struct foo)
 +        $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
  
 -      if ($prototype =~ /SYSCALL_DEFINE/) {
 -              syscall_munge();
 -      }
 -      if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
 -          $prototype =~ /DEFINE_SINGLE_EVENT/)
 -      {
 -              tracepoint_munge($file);
 -      }
 -      dump_function($prototype, $file);
 -      reset_state();
 +        if ($prototype =~ /SYSCALL_DEFINE/) {
 +            syscall_munge();
 +        }
 +        if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
 +            $prototype =~ /DEFINE_SINGLE_EVENT/)
 +        {
 +            tracepoint_munge($file);
 +        }
 +        dump_function($prototype, $file);
 +        reset_state();
      }
  }
  
@@@ -1948,28 -1946,28 +1948,28 @@@ sub process_proto_type($$) 
      $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
  
      if ($x =~ /^#/) {
 -      # To distinguish preprocessor directive from regular declaration later.
 -      $x .= ";";
 +        # To distinguish preprocessor directive from regular declaration later.
 +        $x .= ";";
      }
  
      while (1) {
 -      if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
 +        if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
              if( length $prototype ) {
                  $prototype .= " "
              }
 -          $prototype .= $1 . $2;
 -          ($2 eq '{') && $brcount++;
 -          ($2 eq '}') && $brcount--;
 -          if (($2 eq ';') && ($brcount == 0)) {
 -              dump_declaration($prototype, $file);
 -              reset_state();
 -              last;
 -          }
 -          $x = $3;
 -      } else {
 -          $prototype .= $x;
 -          last;
 -      }
 +            $prototype .= $1 . $2;
 +            ($2 eq '{') && $brcount++;
 +            ($2 eq '}') && $brcount--;
 +            if (($2 eq ';') && ($brcount == 0)) {
 +                dump_declaration($prototype, $file);
 +                reset_state();
 +                last;
 +            }
 +            $x = $3;
 +        } else {
 +            $prototype .= $x;
 +            last;
 +        }
      }
  }
  
@@@ -1979,13 -1977,13 +1979,13 @@@ sub map_filename($) 
      my ($orig_file) = @_;
  
      if (defined($ENV{'SRCTREE'})) {
 -      $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
 +        $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
      } else {
 -      $file = $orig_file;
 +        $file = $orig_file;
      }
  
      if (defined($source_map{$file})) {
 -      $file = $source_map{$file};
 +        $file = $source_map{$file};
      }
  
      return $file;
@@@ -1996,20 -1994,20 +1996,20 @@@ sub process_export_file($) 
      my $file = map_filename($orig_file);
  
      if (!open(IN,"<$file")) {
 -      print STDERR "Error: Cannot open file $file\n";
 -      ++$errors;
 -      return;
 +        print STDERR "Error: Cannot open file $file\n";
 +        ++$errors;
 +        return;
      }
  
      while (<IN>) {
 -      if (/$export_symbol/) {
 -          next if (defined($nosymbol_table{$2}));
 -          $function_table{$2} = 1;
 -      }
 -      if (/$export_symbol_ns/) {
 -          next if (defined($nosymbol_table{$2}));
 -          $function_table{$2} = 1;
 -      }
 +        if (/$export_symbol/) {
 +            next if (defined($nosymbol_table{$2}));
 +            $function_table{$2} = 1;
 +        }
 +        if (/$export_symbol_ns/) {
 +            next if (defined($nosymbol_table{$2}));
 +            $function_table{$2} = 1;
 +        }
      }
  
      close(IN);
  #
  sub process_normal() {
      if (/$doc_start/o) {
 -      $state = STATE_NAME;    # next line is always the function name
 -      $in_doc_sect = 0;
 -      $declaration_start_line = $. + 1;
 +        $state = STATE_NAME;        # next line is always the function name
 +        $in_doc_sect = 0;
 +        $declaration_start_line = $. + 1;
      }
  }
  
@@@ -2036,80 -2034,80 +2036,80 @@@ sub process_name($$) 
      my $descr;
  
      if (/$doc_block/o) {
 -      $state = STATE_DOCBLOCK;
 -      $contents = "";
 -      $new_start_line = $.;
 -
 -      if ( $1 eq "" ) {
 -          $section = $section_intro;
 -      } else {
 -          $section = $1;
 -      }
 +        $state = STATE_DOCBLOCK;
 +        $contents = "";
 +        $new_start_line = $.;
 +
 +        if ( $1 eq "" ) {
 +            $section = $section_intro;
 +        } else {
 +            $section = $1;
 +        }
      } elsif (/$doc_decl/o) {
 -      $identifier = $1;
 -      my $is_kernel_comment = 0;
 -      my $decl_start = qr{$doc_com};
 -      # test for pointer declaration type, foo * bar() - desc
 -      my $fn_type = qr{\w+\s*\*\s*}; 
 -      my $parenthesis = qr{\(\w*\)};
 -      my $decl_end = qr{[-:].*};
 -      if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) {
 -          $identifier = $1;
 -      }
 -      if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
 -          $decl_type = $1;
 -          $identifier = $2;
 -          $is_kernel_comment = 1;
 -      }
 -      # Look for foo() or static void foo() - description; or misspelt
 -      # identifier
 -      elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
 -          /^$decl_start$fn_type?(\w+.*)$parenthesis?\s*$decl_end$/) {
 -          $identifier = $1;
 -          $decl_type = 'function';
 -          $identifier =~ s/^define\s+//;
 -          $is_kernel_comment = 1;
 -      }
 -      $identifier =~ s/\s+$//;
 -
 -      $state = STATE_BODY;
 -      # if there's no @param blocks need to set up default section
 -      # here
 -      $contents = "";
 -      $section = $section_default;
 -      $new_start_line = $. + 1;
 -      if (/[-:](.*)/) {
 -          # strip leading/trailing/multiple spaces
 -          $descr= $1;
 -          $descr =~ s/^\s*//;
 -          $descr =~ s/\s*$//;
 -          $descr =~ s/\s+/ /g;
 -          $declaration_purpose = $descr;
 -          $state = STATE_BODY_MAYBE;
 -      } else {
 -          $declaration_purpose = "";
 -      }
 -
 -      if (!$is_kernel_comment) {
 -          emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
 -          $state = STATE_NORMAL;
 -      }
 -
 -      if (($declaration_purpose eq "") && $Wshort_desc) {
 -          emit_warning("${file}:$.", "missing initial short description on line:\n$_");
 -      }
 -
 -      if ($identifier eq "" && $decl_type ne "enum") {
 -          emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
 -          $state = STATE_NORMAL;
 -      }
 -
 -      if ($verbose) {
 -          print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
 -      }
 +        $identifier = $1;
 +        my $is_kernel_comment = 0;
 +        my $decl_start = qr{$doc_com};
 +        # test for pointer declaration type, foo * bar() - desc
 +        my $fn_type = qr{\w+\s*\*\s*};
 +        my $parenthesis = qr{\(\w*\)};
 +        my $decl_end = qr{[-:].*};
 +        if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) {
 +            $identifier = $1;
 +        }
 +        if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
 +            $decl_type = $1;
 +            $identifier = $2;
 +            $is_kernel_comment = 1;
 +        }
 +        # Look for foo() or static void foo() - description; or misspelt
 +        # identifier
 +        elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
 +            /^$decl_start$fn_type?(\w+.*)$parenthesis?\s*$decl_end$/) {
 +            $identifier = $1;
 +            $decl_type = 'function';
 +            $identifier =~ s/^define\s+//;
 +            $is_kernel_comment = 1;
 +        }
 +        $identifier =~ s/\s+$//;
 +
 +        $state = STATE_BODY;
 +        # if there's no @param blocks need to set up default section
 +        # here
 +        $contents = "";
 +        $section = $section_default;
 +        $new_start_line = $. + 1;
 +        if (/[-:](.*)/) {
 +            # strip leading/trailing/multiple spaces
 +            $descr= $1;
 +            $descr =~ s/^\s*//;
 +            $descr =~ s/\s*$//;
 +            $descr =~ s/\s+/ /g;
 +            $declaration_purpose = $descr;
 +            $state = STATE_BODY_MAYBE;
 +        } else {
 +            $declaration_purpose = "";
 +        }
 +
 +        if (!$is_kernel_comment) {
 +            emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
 +            $state = STATE_NORMAL;
 +        }
 +
 +        if (($declaration_purpose eq "") && $Wshort_desc) {
 +            emit_warning("${file}:$.", "missing initial short description on line:\n$_");
 +        }
 +
 +        if ($identifier eq "" && $decl_type ne "enum") {
 +            emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
 +            $state = STATE_NORMAL;
 +        }
 +
 +        if ($verbose) {
 +            print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
 +        }
      } else {
 -      emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
 -      $state = STATE_NORMAL;
 +        emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
 +        $state = STATE_NORMAL;
      }
  }
  
@@@ -2121,102 -2119,102 +2121,102 @@@ sub process_body($$) 
      my $file = shift;
  
      if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) {
 -      dump_section($file, $section, $contents);
 -      $section = $section_default;
 -      $new_start_line = $.;
 -      $contents = "";
 +        dump_section($file, $section, $contents);
 +        $section = $section_default;
 +        $new_start_line = $.;
 +        $contents = "";
      }
  
      if (/$doc_sect/i) { # case insensitive for supported section names
 -      $in_doc_sect = 1;
 -      $newsection = $1;
 -      $newcontents = $2;
 -
 -      # map the supported section names to the canonical names
 -      if ($newsection =~ m/^description$/i) {
 -          $newsection = $section_default;
 -      } elsif ($newsection =~ m/^context$/i) {
 -          $newsection = $section_context;
 -      } elsif ($newsection =~ m/^returns?$/i) {
 -          $newsection = $section_return;
 -      } elsif ($newsection =~ m/^\@return$/) {
 -          # special: @return is a section, not a param description
 -          $newsection = $section_return;
 -      }
 -
 -      if (($contents ne "") && ($contents ne "\n")) {
 -          if (!$in_doc_sect && $Wcontents_before_sections) {
 -              emit_warning("${file}:$.", "contents before sections\n");
 -          }
 -          dump_section($file, $section, $contents);
 -          $section = $section_default;
 -      }
 -
 -      $in_doc_sect = 1;
 -      $state = STATE_BODY;
 -      $contents = $newcontents;
 -      $new_start_line = $.;
 -      while (substr($contents, 0, 1) eq " ") {
 -          $contents = substr($contents, 1);
 -      }
 -      if ($contents ne "") {
 -          $contents .= "\n";
 -      }
 -      $section = $newsection;
 -      $leading_space = undef;
 +        $in_doc_sect = 1;
 +        $newsection = $1;
 +        $newcontents = $2;
 +
 +        # map the supported section names to the canonical names
 +        if ($newsection =~ m/^description$/i) {
 +            $newsection = $section_default;
 +        } elsif ($newsection =~ m/^context$/i) {
 +            $newsection = $section_context;
 +        } elsif ($newsection =~ m/^returns?$/i) {
 +            $newsection = $section_return;
 +        } elsif ($newsection =~ m/^\@return$/) {
 +            # special: @return is a section, not a param description
 +            $newsection = $section_return;
 +        }
 +
 +        if (($contents ne "") && ($contents ne "\n")) {
 +            if (!$in_doc_sect && $Wcontents_before_sections) {
 +                emit_warning("${file}:$.", "contents before sections\n");
 +            }
 +            dump_section($file, $section, $contents);
 +            $section = $section_default;
 +        }
 +
 +        $in_doc_sect = 1;
 +        $state = STATE_BODY;
 +        $contents = $newcontents;
 +        $new_start_line = $.;
 +        while (substr($contents, 0, 1) eq " ") {
 +            $contents = substr($contents, 1);
 +        }
 +        if ($contents ne "") {
 +            $contents .= "\n";
 +        }
 +        $section = $newsection;
 +        $leading_space = undef;
      } elsif (/$doc_end/) {
 -      if (($contents ne "") && ($contents ne "\n")) {
 -          dump_section($file, $section, $contents);
 -          $section = $section_default;
 -          $contents = "";
 -      }
 -      # look for doc_com + <text> + doc_end:
 -      if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
 -          emit_warning("${file}:$.", "suspicious ending line: $_");
 -      }
 -
 -      $prototype = "";
 -      $state = STATE_PROTO;
 -      $brcount = 0;
 +        if (($contents ne "") && ($contents ne "\n")) {
 +            dump_section($file, $section, $contents);
 +            $section = $section_default;
 +            $contents = "";
 +        }
 +        # look for doc_com + <text> + doc_end:
 +        if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
 +            emit_warning("${file}:$.", "suspicious ending line: $_");
 +        }
 +
 +        $prototype = "";
 +        $state = STATE_PROTO;
 +        $brcount = 0;
          $new_start_line = $. + 1;
      } elsif (/$doc_content/) {
 -      if ($1 eq "") {
 -          if ($section eq $section_context) {
 -              dump_section($file, $section, $contents);
 -              $section = $section_default;
 -              $contents = "";
 -              $new_start_line = $.;
 -              $state = STATE_BODY;
 -          } else {
 -              if ($section ne $section_default) {
 -                  $state = STATE_BODY_WITH_BLANK_LINE;
 -              } else {
 -                  $state = STATE_BODY;
 -              }
 -              $contents .= "\n";
 -          }
 -      } elsif ($state == STATE_BODY_MAYBE) {
 -          # Continued declaration purpose
 -          chomp($declaration_purpose);
 -          $declaration_purpose .= " " . $1;
 -          $declaration_purpose =~ s/\s+/ /g;
 -      } else {
 -          my $cont = $1;
 -          if ($section =~ m/^@/ || $section eq $section_context) {
 -              if (!defined $leading_space) {
 -                  if ($cont =~ m/^(\s+)/) {
 -                      $leading_space = $1;
 -                  } else {
 -                      $leading_space = "";
 -                  }
 -              }
 -              $cont =~ s/^$leading_space//;
 -          }
 -          $contents .= $cont . "\n";
 -      }
 +        if ($1 eq "") {
 +            if ($section eq $section_context) {
 +                dump_section($file, $section, $contents);
 +                $section = $section_default;
 +                $contents = "";
 +                $new_start_line = $.;
 +                $state = STATE_BODY;
 +            } else {
 +                if ($section ne $section_default) {
 +                    $state = STATE_BODY_WITH_BLANK_LINE;
 +                } else {
 +                    $state = STATE_BODY;
 +                }
 +                $contents .= "\n";
 +            }
 +        } elsif ($state == STATE_BODY_MAYBE) {
 +            # Continued declaration purpose
 +            chomp($declaration_purpose);
 +            $declaration_purpose .= " " . $1;
 +            $declaration_purpose =~ s/\s+/ /g;
 +        } else {
 +            my $cont = $1;
 +            if ($section =~ m/^@/ || $section eq $section_context) {
 +                if (!defined $leading_space) {
 +                    if ($cont =~ m/^(\s+)/) {
 +                        $leading_space = $1;
 +                    } else {
 +                        $leading_space = "";
 +                    }
 +                }
 +                $cont =~ s/^$leading_space//;
 +            }
 +            $contents .= $cont . "\n";
 +        }
      } else {
 -      # i dont know - bad line?  ignore.
 -      emit_warning("${file}:$.", "bad line: $_");
 +        # i dont know - bad line?  ignore.
 +        emit_warning("${file}:$.", "bad line: $_");
      }
  }
  
@@@ -2228,21 -2226,21 +2228,21 @@@ sub process_proto($$) 
      my $file = shift;
  
      if (/$doc_inline_oneline/) {
 -      $section = $1;
 -      $contents = $2;
 -      if ($contents ne "") {
 -          $contents .= "\n";
 -          dump_section($file, $section, $contents);
 -          $section = $section_default;
 -          $contents = "";
 -      }
 +        $section = $1;
 +        $contents = $2;
 +        if ($contents ne "") {
 +            $contents .= "\n";
 +            dump_section($file, $section, $contents);
 +            $section = $section_default;
 +            $contents = "";
 +        }
      } elsif (/$doc_inline_start/) {
 -      $state = STATE_INLINE;
 -      $inline_doc_state = STATE_INLINE_NAME;
 +        $state = STATE_INLINE;
 +        $inline_doc_state = STATE_INLINE_NAME;
      } elsif ($decl_type eq 'function') {
 -      process_proto_function($_, $file);
 +        process_proto_function($_, $file);
      } else {
 -      process_proto_type($_, $file);
 +        process_proto_type($_, $file);
      }
  }
  
@@@ -2253,23 -2251,23 +2253,23 @@@ sub process_docblock($$) 
      my $file = shift;
  
      if (/$doc_end/) {
 -      dump_doc_section($file, $section, $contents);
 -      $section = $section_default;
 -      $contents = "";
 -      $function = "";
 -      %parameterdescs = ();
 -      %parametertypes = ();
 -      @parameterlist = ();
 -      %sections = ();
 -      @sectionlist = ();
 -      $prototype = "";
 -      $state = STATE_NORMAL;
 +        dump_doc_section($file, $section, $contents);
 +        $section = $section_default;
 +        $contents = "";
 +        $function = "";
 +        %parameterdescs = ();
 +        %parametertypes = ();
 +        @parameterlist = ();
 +        %sections = ();
 +        @sectionlist = ();
 +        $prototype = "";
 +        $state = STATE_NORMAL;
      } elsif (/$doc_content/) {
 -      if ( $1 eq "" ) {
 -          $contents .= $blankline;
 -      } else {
 -          $contents .= $1 . "\n";
 -      }
 +        if ( $1 eq "" )        {
 +            $contents .= $blankline;
 +        } else {
 +            $contents .= $1 . "\n";
 +        }
      }
  }
  
@@@ -2281,37 -2279,37 +2281,37 @@@ sub process_inline($$) 
  
      # First line (state 1) needs to be a @parameter
      if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
 -      $section = $1;
 -      $contents = $2;
 -      $new_start_line = $.;
 -      if ($contents ne "") {
 -          while (substr($contents, 0, 1) eq " ") {
 -              $contents = substr($contents, 1);
 -          }
 -          $contents .= "\n";
 -      }
 -      $inline_doc_state = STATE_INLINE_TEXT;
 -      # Documentation block end */
 +        $section = $1;
 +        $contents = $2;
 +        $new_start_line = $.;
 +        if ($contents ne "") {
 +            while (substr($contents, 0, 1) eq " ") {
 +                $contents = substr($contents, 1);
 +            }
 +            $contents .= "\n";
 +        }
 +        $inline_doc_state = STATE_INLINE_TEXT;
 +        # Documentation block end */
      } elsif (/$doc_inline_end/) {
 -      if (($contents ne "") && ($contents ne "\n")) {
 -          dump_section($file, $section, $contents);
 -          $section = $section_default;
 -          $contents = "";
 -      }
 -      $state = STATE_PROTO;
 -      $inline_doc_state = STATE_INLINE_NA;
 -      # Regular text
 +        if (($contents ne "") && ($contents ne "\n")) {
 +            dump_section($file, $section, $contents);
 +            $section = $section_default;
 +            $contents = "";
 +        }
 +        $state = STATE_PROTO;
 +        $inline_doc_state = STATE_INLINE_NA;
 +        # Regular text
      } elsif (/$doc_content/) {
 -      if ($inline_doc_state == STATE_INLINE_TEXT) {
 -          $contents .= $1 . "\n";
 -          # nuke leading blank lines
 -          if ($contents =~ /^\s*$/) {
 -              $contents = "";
 -          }
 -      } elsif ($inline_doc_state == STATE_INLINE_NAME) {
 -          $inline_doc_state = STATE_INLINE_ERROR;
 -          emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
 -      }
 +        if ($inline_doc_state == STATE_INLINE_TEXT) {
 +            $contents .= $1 . "\n";
 +            # nuke leading blank lines
 +            if ($contents =~ /^\s*$/) {
 +                $contents = "";
 +            }
 +        } elsif ($inline_doc_state == STATE_INLINE_NAME) {
 +            $inline_doc_state = STATE_INLINE_ERROR;
 +            emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
 +        }
      }
  }
  
@@@ -2324,53 -2322,54 +2324,53 @@@ sub process_file($) 
      $file = map_filename($orig_file);
  
      if (!open(IN_FILE,"<$file")) {
 -      print STDERR "Error: Cannot open file $file\n";
 -      ++$errors;
 -      return;
 +        print STDERR "Error: Cannot open file $file\n";
 +        ++$errors;
 +        return;
      }
  
      $. = 1;
  
      $section_counter = 0;
      while (<IN_FILE>) {
 -      while (s/\\\s*$//) {
 -          $_ .= <IN_FILE>;
 -      }
 -      # Replace tabs by spaces
 +        while (!/^ \*/ && s/\\\s*$//) {
 +            $_ .= <IN_FILE>;
 +        }
 +        # Replace tabs by spaces
          while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
 -      # Hand this line to the appropriate state handler
 -      if ($state == STATE_NORMAL) {
 -          process_normal();
 -      } elsif ($state == STATE_NAME) {
 -          process_name($file, $_);
 -      } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
 -               $state == STATE_BODY_WITH_BLANK_LINE) {
 -          process_body($file, $_);
 -      } elsif ($state == STATE_INLINE) { # scanning for inline parameters
 -          process_inline($file, $_);
 -      } elsif ($state == STATE_PROTO) {
 -          process_proto($file, $_);
 -      } elsif ($state == STATE_DOCBLOCK) {
 -          process_docblock($file, $_);
 -      }
 +        # Hand this line to the appropriate state handler
 +        if ($state == STATE_NORMAL) {
 +            process_normal();
 +        } elsif ($state == STATE_NAME) {
 +            process_name($file, $_);
 +        } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
 +                 $state == STATE_BODY_WITH_BLANK_LINE) {
 +            process_body($file, $_);
 +        } elsif ($state == STATE_INLINE) { # scanning for inline parameters
 +            process_inline($file, $_);
 +        } elsif ($state == STATE_PROTO) {
 +            process_proto($file, $_);
 +        } elsif ($state == STATE_DOCBLOCK) {
 +            process_docblock($file, $_);
 +        }
      }
  
      # Make sure we got something interesting.
      if ($initial_section_counter == $section_counter && $
 -      output_mode ne "none") {
 -      if ($output_selection == OUTPUT_INCLUDE) {
 -          emit_warning("${file}:1", "'$_' not found\n")
 -              for keys %function_table;
 -      }
 -      else {
 -          emit_warning("${file}:1", "no structured comments found\n");
 -      }
 +        output_mode ne "none") {
 +        if ($output_selection == OUTPUT_INCLUDE) {
 +            emit_warning("${file}:1", "'$_' not found\n")
 +                for keys %function_table;
 +        } else {
 +            emit_warning("${file}:1", "no structured comments found\n");
 +        }
      }
      close IN_FILE;
  }
  
  
  if ($output_mode eq "rst") {
 -      get_sphinx_version() if (!$sphinx_major);
 +    get_sphinx_version() if (!$sphinx_major);
  }
  
  $kernelversion = get_kernel_version();
@@@ -2387,14 -2386,14 +2387,14 @@@ for (my $k = 0; $k < @highlights; $k++
  # Read the file that maps relative names to absolute names for
  # separate source and object directories and for shadow trees.
  if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
 -      my ($relname, $absname);
 -      while(<SOURCE_MAP>) {
 -              chop();
 -              ($relname, $absname) = (split())[0..1];
 -              $relname =~ s:^/+::;
 -              $source_map{$relname} = $absname;
 -      }
 -      close(SOURCE_MAP);
 +    my ($relname, $absname);
 +    while(<SOURCE_MAP>) {
 +        chop();
 +        ($relname, $absname) = (split())[0..1];
 +        $relname =~ s:^/+::;
 +        $source_map{$relname} = $absname;
 +    }
 +    close(SOURCE_MAP);
  }
  
  if ($output_selection == OUTPUT_EXPORTED ||
      push(@export_file_list, @ARGV);
  
      foreach (@export_file_list) {
 -      chomp;
 -      process_export_file($_);
 +        chomp;
 +        process_export_file($_);
      }
  }
  
@@@ -2413,10 -2412,10 +2413,10 @@@ foreach (@ARGV) 
      process_file($_);
  }
  if ($verbose && $errors) {
 -  print STDERR "$errors errors\n";
 +    print STDERR "$errors errors\n";
  }
  if ($verbose && $warnings) {
 -  print STDERR "$warnings warnings\n";
 +    print STDERR "$warnings warnings\n";
  }
  
  if ($Werror && $warnings) {
This page took 0.279082 seconds and 4 git commands to generate.