]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'akpm' (patches from Andrew)
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 15 Jan 2016 19:41:44 +0000 (11:41 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 15 Jan 2016 19:41:44 +0000 (11:41 -0800)
Merge first patch-bomb from Andrew Morton:

 - A few hotfixes which missed 4.4 becasue I was asleep.  cc'ed to
   -stable

 - A few misc fixes

 - OCFS2 updates

 - Part of MM.  Including pretty large changes to page-flags handling
   and to thp management which have been buffered up for 2-3 cycles now.

  I have a lot of MM material this time.

[ It turns out the THP part wasn't quite ready, so that got dropped from
  this series  - Linus ]

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (117 commits)
  zsmalloc: reorganize struct size_class to pack 4 bytes hole
  mm/zbud.c: use list_last_entry() instead of list_tail_entry()
  zram/zcomp: do not zero out zcomp private pages
  zram: pass gfp from zcomp frontend to backend
  zram: try vmalloc() after kmalloc()
  zram/zcomp: use GFP_NOIO to allocate streams
  mm: add tracepoint for scanning pages
  drivers/base/memory.c: fix kernel warning during memory hotplug on ppc64
  mm/page_isolation: use macro to judge the alignment
  mm: fix noisy sparse warning in LIBCFS_ALLOC_PRE()
  mm: rework virtual memory accounting
  include/linux/memblock.h: fix ordering of 'flags' argument in comments
  mm: move lru_to_page to mm_inline.h
  Documentation/filesystems: describe the shared memory usage/accounting
  memory-hotplug: don't BUG() in register_memory_resource()
  hugetlb: make mm and fs code explicitly non-modular
  mm/swapfile.c: use list_for_each_entry_safe in free_swap_count_continuations
  mm: /proc/pid/clear_refs: no need to clear VM_SOFTDIRTY in clear_soft_dirty_pmd()
  mm: make sure isolate_lru_page() is never called for tail page
  vmstat: make vmstat_updater deferrable again and shut down on idle
  ...

1  2 
Documentation/sysctl/vm.txt
fs/nfs/inode.c
mm/shmem.c

index 8ee925c046aa67c12a07a9c3eb9f1d4b1c812dc2,ee763f3d3b5250276606c2e0d0f90acddc1f9748..89a887c7662930844ea59850e65866bbd43c3786
@@@ -42,6 -42,8 +42,8 @@@ Currently, these files are in /proc/sys
  - min_slab_ratio
  - min_unmapped_ratio
  - mmap_min_addr
+ - mmap_rnd_bits
+ - mmap_rnd_compat_bits
  - nr_hugepages
  - nr_overcommit_hugepages
  - nr_trim_pages         (only if CONFIG_MMU=n)
@@@ -135,7 -137,7 +137,7 @@@ Contains, as a percentage of total avai
  and reclaimable pages, the number of pages at which the background kernel
  flusher threads will start writing out dirty data.
  
 -The total avaiable memory is not equal to total system memory.
 +The total available memory is not equal to total system memory.
  
  ==============================================================
  
@@@ -170,7 -172,7 +172,7 @@@ Contains, as a percentage of total avai
  and reclaimable pages, the number of pages at which a process which is
  generating disk writes will itself start writing out dirty data.
  
 -The total avaiable memory is not equal to total system memory.
 +The total available memory is not equal to total system memory.
  
  ==============================================================
  
@@@ -485,6 -487,33 +487,33 @@@ against future potential kernel bugs
  
  ==============================================================
  
+ mmap_rnd_bits:
+ This value can be used to select the number of bits to use to
+ determine the random offset to the base address of vma regions
+ resulting from mmap allocations on architectures which support
+ tuning address space randomization.  This value will be bounded
+ by the architecture's minimum and maximum supported values.
+ This value can be changed after boot using the
+ /proc/sys/vm/mmap_rnd_bits tunable
+ ==============================================================
+ mmap_rnd_compat_bits:
+ This value can be used to select the number of bits to use to
+ determine the random offset to the base address of vma regions
+ resulting from mmap allocations for applications run in
+ compatibility mode on architectures which support tuning address
+ space randomization.  This value will be bounded by the
+ architecture's minimum and maximum supported values.
+ This value can be changed after boot using the
+ /proc/sys/vm/mmap_rnd_compat_bits tunable
+ ==============================================================
  nr_hugepages
  
  Change the minimum size of the hugepage pool.
diff --combined fs/nfs/inode.c
index c11e855e0e18b09bce933982ee14904fb9910686,48fd8a87affe569c942f5b3a054e3c414e4adac8..8e24d886d2c5991c044965c3fa3093f3142632b8
@@@ -71,25 -71,19 +71,25 @@@ nfs_fattr_to_ino_t(struct nfs_fattr *fa
        return nfs_fileid_to_ino_t(fattr->fileid);
  }
  
 -/**
 - * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks
 - * @word: long word containing the bit lock
 - */
 -int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
 +static int nfs_wait_killable(int mode)
  {
        freezable_schedule_unsafe();
        if (signal_pending_state(mode, current))
                return -ERESTARTSYS;
        return 0;
  }
 +
 +int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
 +{
 +      return nfs_wait_killable(mode);
 +}
  EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
  
 +int nfs_wait_atomic_killable(atomic_t *p)
 +{
 +      return nfs_wait_killable(TASK_KILLABLE);
 +}
 +
  /**
   * nfs_compat_user_ino64 - returns the user-visible inode number
   * @fileid: 64-bit fileid
@@@ -706,7 -700,7 +706,7 @@@ static void nfs_init_lock_context(struc
        l_ctx->lockowner.l_owner = current->files;
        l_ctx->lockowner.l_pid = current->tgid;
        INIT_LIST_HEAD(&l_ctx->list);
 -      nfs_iocounter_init(&l_ctx->io_count);
 +      atomic_set(&l_ctx->io_count, 0);
  }
  
  static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
@@@ -919,12 -913,6 +919,12 @@@ void nfs_file_clear_open_context(struc
        if (ctx) {
                struct inode *inode = d_inode(ctx->dentry);
  
 +              /*
 +               * We fatal error on write before. Try to writeback
 +               * every page again.
 +               */
 +              if (ctx->error < 0)
 +                      invalidate_inode_pages2(inode->i_mapping);
                filp->private_data = NULL;
                spin_lock(&inode->i_lock);
                list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
@@@ -1675,7 -1663,6 +1675,7 @@@ static int nfs_update_inode(struct inod
        unsigned long invalid = 0;
        unsigned long now = jiffies;
        unsigned long save_cache_validity;
 +      bool cache_revalidated = true;
  
        dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n",
                        __func__, inode->i_sb->s_id, inode->i_ino,
                                nfs_force_lookup_revalidate(inode);
                        inode->i_version = fattr->change_attr;
                }
 -      } else
 +      } else {
                nfsi->cache_validity |= save_cache_validity;
 +              cache_revalidated = false;
 +      }
  
        if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
                memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
 -      } else if (server->caps & NFS_CAP_MTIME)
 +      } else if (server->caps & NFS_CAP_MTIME) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATTR
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
        if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
                memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
 -      } else if (server->caps & NFS_CAP_CTIME)
 +      } else if (server->caps & NFS_CAP_CTIME) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATTR
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
        /* Check if our cached file size is stale */
        if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
                                        (long long)cur_isize,
                                        (long long)new_isize);
                }
 -      } else
 +      } else {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATTR
                                | NFS_INO_REVAL_PAGECACHE
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
  
        if (fattr->valid & NFS_ATTR_FATTR_ATIME)
                memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
 -      else if (server->caps & NFS_CAP_ATIME)
 +      else if (server->caps & NFS_CAP_ATIME) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATIME
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
        if (fattr->valid & NFS_ATTR_FATTR_MODE) {
                if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) {
                        inode->i_mode = newmode;
                        invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
                }
 -      } else if (server->caps & NFS_CAP_MODE)
 +      } else if (server->caps & NFS_CAP_MODE) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATTR
                                | NFS_INO_INVALID_ACCESS
                                | NFS_INO_INVALID_ACL
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
        if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
                if (!uid_eq(inode->i_uid, fattr->uid)) {
                        invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
                        inode->i_uid = fattr->uid;
                }
 -      } else if (server->caps & NFS_CAP_OWNER)
 +      } else if (server->caps & NFS_CAP_OWNER) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATTR
                                | NFS_INO_INVALID_ACCESS
                                | NFS_INO_INVALID_ACL
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
        if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
                if (!gid_eq(inode->i_gid, fattr->gid)) {
                        invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
                        inode->i_gid = fattr->gid;
                }
 -      } else if (server->caps & NFS_CAP_OWNER_GROUP)
 +      } else if (server->caps & NFS_CAP_OWNER_GROUP) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATTR
                                | NFS_INO_INVALID_ACCESS
                                | NFS_INO_INVALID_ACL
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
        if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
                if (inode->i_nlink != fattr->nlink) {
                                invalid |= NFS_INO_INVALID_DATA;
                        set_nlink(inode, fattr->nlink);
                }
 -      } else if (server->caps & NFS_CAP_NLINK)
 +      } else if (server->caps & NFS_CAP_NLINK) {
                nfsi->cache_validity |= save_cache_validity &
                                (NFS_INO_INVALID_ATTR
                                | NFS_INO_REVAL_FORCED);
 +              cache_revalidated = false;
 +      }
  
        if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
                /*
                 * report the blocks in 512byte units
                 */
                inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
 -      }
 -      if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
 +      } else if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
                inode->i_blocks = fattr->du.nfs2.blocks;
 +      else
 +              cache_revalidated = false;
  
        /* Update attrtimeo value if we're out of the unstable period */
        if (invalid & NFS_INO_INVALID_ATTR) {
                /* Set barrier to be more recent than all outstanding updates */
                nfsi->attr_gencount = nfs_inc_attr_generation_counter();
        } else {
 -              if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
 -                      if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
 -                              nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
 +              if (cache_revalidated) {
 +                      if (!time_in_range_open(now, nfsi->attrtimeo_timestamp,
 +                              nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
 +                              nfsi->attrtimeo <<= 1;
 +                              if (nfsi->attrtimeo > NFS_MAXATTRTIMEO(inode))
 +                                      nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
 +                      }
                        nfsi->attrtimeo_timestamp = now;
                }
                /* Set the barrier to be more recent than this fattr */
        }
  
        /* Don't declare attrcache up to date if there were no attrs! */
 -      if (fattr->valid != 0)
 +      if (cache_revalidated)
                invalid &= ~NFS_INO_INVALID_ATTR;
  
        /* Don't invalidate the data if we were to blame */
@@@ -1969,7 -1933,7 +1969,7 @@@ static int __init nfs_init_inodecache(v
        nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
                                             sizeof(struct nfs_inode),
                                             0, (SLAB_RECLAIM_ACCOUNT|
-                                               SLAB_MEM_SPREAD),
+                                               SLAB_MEM_SPREAD|SLAB_ACCOUNT),
                                             init_once);
        if (nfs_inode_cachep == NULL)
                return -ENOMEM;
diff --combined mm/shmem.c
index 642471b0ddea0ebaa9f8a7c872521a7cb57b4195,760d90cf2a41c32bf3331f34ca8fa8532cb07548..970ff5b80853e131ee1e4abd618340faccf00f44
@@@ -359,6 -359,87 +359,87 @@@ static int shmem_free_swap(struct addre
        return 0;
  }
  
+ /*
+  * Determine (in bytes) how many of the shmem object's pages mapped by the
+  * given offsets are swapped out.
+  *
+  * This is safe to call without i_mutex or mapping->tree_lock thanks to RCU,
+  * as long as the inode doesn't go away and racy results are not a problem.
+  */
+ unsigned long shmem_partial_swap_usage(struct address_space *mapping,
+                                               pgoff_t start, pgoff_t end)
+ {
+       struct radix_tree_iter iter;
+       void **slot;
+       struct page *page;
+       unsigned long swapped = 0;
+       rcu_read_lock();
+ restart:
+       radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) {
+               if (iter.index >= end)
+                       break;
+               page = radix_tree_deref_slot(slot);
+               /*
+                * This should only be possible to happen at index 0, so we
+                * don't need to reset the counter, nor do we risk infinite
+                * restarts.
+                */
+               if (radix_tree_deref_retry(page))
+                       goto restart;
+               if (radix_tree_exceptional_entry(page))
+                       swapped++;
+               if (need_resched()) {
+                       cond_resched_rcu();
+                       start = iter.index + 1;
+                       goto restart;
+               }
+       }
+       rcu_read_unlock();
+       return swapped << PAGE_SHIFT;
+ }
+ /*
+  * Determine (in bytes) how many of the shmem object's pages mapped by the
+  * given vma is swapped out.
+  *
+  * This is safe to call without i_mutex or mapping->tree_lock thanks to RCU,
+  * as long as the inode doesn't go away and racy results are not a problem.
+  */
+ unsigned long shmem_swap_usage(struct vm_area_struct *vma)
+ {
+       struct inode *inode = file_inode(vma->vm_file);
+       struct shmem_inode_info *info = SHMEM_I(inode);
+       struct address_space *mapping = inode->i_mapping;
+       unsigned long swapped;
+       /* Be careful as we don't hold info->lock */
+       swapped = READ_ONCE(info->swapped);
+       /*
+        * The easier cases are when the shmem object has nothing in swap, or
+        * the vma maps it whole. Then we can simply use the stats that we
+        * already track.
+        */
+       if (!swapped)
+               return 0;
+       if (!vma->vm_pgoff && vma->vm_end - vma->vm_start >= inode->i_size)
+               return swapped << PAGE_SHIFT;
+       /* Here comes the more involved part */
+       return shmem_partial_swap_usage(mapping,
+                       linear_page_index(vma, vma->vm_start),
+                       linear_page_index(vma, vma->vm_end));
+ }
  /*
   * SysV IPC SHM_UNLOCK restore Unevictable pages to their evictable lists.
   */
@@@ -2469,7 -2550,6 +2550,7 @@@ static int shmem_symlink(struct inode *
                inode->i_op = &shmem_short_symlink_operations;
                inode->i_link = info->symlink;
        } else {
 +              inode_nohighmem(inode);
                error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
                if (error) {
                        iput(inode);
                }
                inode->i_mapping->a_ops = &shmem_aops;
                inode->i_op = &shmem_symlink_inode_operations;
 -              inode_nohighmem(inode);
                memcpy(page_address(page), symname, len);
                SetPageUptodate(page);
                set_page_dirty(page);
@@@ -3064,7 -3145,7 +3145,7 @@@ static int shmem_init_inodecache(void
  {
        shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
                                sizeof(struct shmem_inode_info),
-                               0, SLAB_PANIC, shmem_init_inode);
+                               0, SLAB_PANIC|SLAB_ACCOUNT, shmem_init_inode);
        return 0;
  }