RDMA/core: Simplify ib_post_(send|recv|srq_recv)() calls
[linux-2.6-microblaze.git] / mm / shmem.c
index 9d6c7e5..2cab844 100644 (file)
@@ -327,7 +327,7 @@ static int shmem_radix_tree_replace(struct address_space *mapping,
                        pgoff_t index, void *expected, void *replacement)
 {
        struct radix_tree_node *node;
-       void **pslot;
+       void __rcu **pslot;
        void *item;
 
        VM_BUG_ON(!expected);
@@ -395,7 +395,7 @@ static bool shmem_confirm_swap(struct address_space *mapping,
 #ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE
 /* ifdef here to avoid bloating shmem.o when not necessary */
 
-int shmem_huge __read_mostly;
+static int shmem_huge __read_mostly;
 
 #if defined(CONFIG_SYSFS) || defined(CONFIG_TMPFS)
 static int shmem_parse_huge(const char *str)
@@ -571,6 +571,15 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
 }
 #endif /* CONFIG_TRANSPARENT_HUGE_PAGECACHE */
 
+static inline bool is_huge_enabled(struct shmem_sb_info *sbinfo)
+{
+       if (IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE) &&
+           (shmem_huge == SHMEM_HUGE_FORCE || sbinfo->huge) &&
+           shmem_huge != SHMEM_HUGE_DENY)
+               return true;
+       return false;
+}
+
 /*
  * Like add_to_page_cache_locked, but error if expected item has gone.
  */
@@ -682,7 +691,7 @@ unsigned long shmem_partial_swap_usage(struct address_space *mapping,
                                                pgoff_t start, pgoff_t end)
 {
        struct radix_tree_iter iter;
-       void **slot;
+       void __rcu **slot;
        struct page *page;
        unsigned long swapped = 0;
 
@@ -988,6 +997,7 @@ static int shmem_getattr(const struct path *path, struct kstat *stat,
 {
        struct inode *inode = path->dentry->d_inode;
        struct shmem_inode_info *info = SHMEM_I(inode);
+       struct shmem_sb_info *sb_info = SHMEM_SB(inode->i_sb);
 
        if (info->alloced - info->swapped != inode->i_mapping->nrpages) {
                spin_lock_irq(&info->lock);
@@ -995,6 +1005,10 @@ static int shmem_getattr(const struct path *path, struct kstat *stat,
                spin_unlock_irq(&info->lock);
        }
        generic_fillattr(inode, stat);
+
+       if (is_huge_enabled(sb_info))
+               stat->blksize = HPAGE_PMD_SIZE;
+
        return 0;
 }
 
@@ -1098,13 +1112,19 @@ static void shmem_evict_inode(struct inode *inode)
 static unsigned long find_swap_entry(struct radix_tree_root *root, void *item)
 {
        struct radix_tree_iter iter;
-       void **slot;
+       void __rcu **slot;
        unsigned long found = -1;
        unsigned int checked = 0;
 
        rcu_read_lock();
        radix_tree_for_each_slot(slot, root, &iter, 0) {
-               if (*slot == item) {
+               void *entry = radix_tree_deref_slot(slot);
+
+               if (radix_tree_deref_retry(entry)) {
+                       slot = radix_tree_iter_retry(&iter);
+                       continue;
+               }
+               if (entry == item) {
                        found = iter.index;
                        break;
                }
@@ -1322,9 +1342,6 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
        if (!swap.val)
                goto redirty;
 
-       if (mem_cgroup_try_charge_swap(page, swap))
-               goto free_swap;
-
        /*
         * Add inode to shmem_unuse()'s list of swapped-out inodes,
         * if it's not already there.  Do it now before the page is
@@ -1353,7 +1370,6 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
        }
 
        mutex_unlock(&shmem_swaplist_mutex);
-free_swap:
        put_swap_page(page, swap);
 redirty:
        set_page_dirty(page);
@@ -1404,10 +1420,9 @@ static void shmem_pseudo_vma_init(struct vm_area_struct *vma,
                struct shmem_inode_info *info, pgoff_t index)
 {
        /* Create a pseudo vma that just contains the policy */
-       vma->vm_start = 0;
+       memset(vma, 0, sizeof(*vma));
        /* Bias interleave by inode number to distribute better across nodes */
        vma->vm_pgoff = index + info->vfs_inode.i_ino;
-       vma->vm_ops = NULL;
        vma->vm_policy = mpol_shared_policy_lookup(&info->policy, index);
 }
 
@@ -1931,14 +1946,14 @@ static int synchronous_wake_function(wait_queue_entry_t *wait, unsigned mode, in
        return ret;
 }
 
-static int shmem_fault(struct vm_fault *vmf)
+static vm_fault_t shmem_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct inode *inode = file_inode(vma->vm_file);
        gfp_t gfp = mapping_gfp_mask(inode->i_mapping);
        enum sgp_type sgp;
-       int error;
-       int ret = VM_FAULT_LOCKED;
+       int err;
+       vm_fault_t ret = VM_FAULT_LOCKED;
 
        /*
         * Trinity finds that probing a hole which tmpfs is punching can
@@ -2006,10 +2021,10 @@ static int shmem_fault(struct vm_fault *vmf)
        else if (vma->vm_flags & VM_HUGEPAGE)
                sgp = SGP_HUGE;
 
-       error = shmem_getpage_gfp(inode, vmf->pgoff, &vmf->page, sgp,
+       err = shmem_getpage_gfp(inode, vmf->pgoff, &vmf->page, sgp,
                                  gfp, vma, vmf, &ret);
-       if (error)
-               return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
+       if (err)
+               return vmf_error(err);
        return ret;
 }
 
@@ -2616,241 +2631,6 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence)
        return offset;
 }
 
-/*
- * We need a tag: a new tag would expand every radix_tree_node by 8 bytes,
- * so reuse a tag which we firmly believe is never set or cleared on shmem.
- */
-#define SHMEM_TAG_PINNED        PAGECACHE_TAG_TOWRITE
-#define LAST_SCAN               4       /* about 150ms max */
-
-static void shmem_tag_pins(struct address_space *mapping)
-{
-       struct radix_tree_iter iter;
-       void **slot;
-       pgoff_t start;
-       struct page *page;
-
-       lru_add_drain();
-       start = 0;
-       rcu_read_lock();
-
-       radix_tree_for_each_slot(slot, &mapping->i_pages, &iter, start) {
-               page = radix_tree_deref_slot(slot);
-               if (!page || radix_tree_exception(page)) {
-                       if (radix_tree_deref_retry(page)) {
-                               slot = radix_tree_iter_retry(&iter);
-                               continue;
-                       }
-               } else if (page_count(page) - page_mapcount(page) > 1) {
-                       xa_lock_irq(&mapping->i_pages);
-                       radix_tree_tag_set(&mapping->i_pages, iter.index,
-                                          SHMEM_TAG_PINNED);
-                       xa_unlock_irq(&mapping->i_pages);
-               }
-
-               if (need_resched()) {
-                       slot = radix_tree_iter_resume(slot, &iter);
-                       cond_resched_rcu();
-               }
-       }
-       rcu_read_unlock();
-}
-
-/*
- * Setting SEAL_WRITE requires us to verify there's no pending writer. However,
- * via get_user_pages(), drivers might have some pending I/O without any active
- * user-space mappings (eg., direct-IO, AIO). Therefore, we look at all pages
- * and see whether it has an elevated ref-count. If so, we tag them and wait for
- * them to be dropped.
- * The caller must guarantee that no new user will acquire writable references
- * to those pages to avoid races.
- */
-static int shmem_wait_for_pins(struct address_space *mapping)
-{
-       struct radix_tree_iter iter;
-       void **slot;
-       pgoff_t start;
-       struct page *page;
-       int error, scan;
-
-       shmem_tag_pins(mapping);
-
-       error = 0;
-       for (scan = 0; scan <= LAST_SCAN; scan++) {
-               if (!radix_tree_tagged(&mapping->i_pages, SHMEM_TAG_PINNED))
-                       break;
-
-               if (!scan)
-                       lru_add_drain_all();
-               else if (schedule_timeout_killable((HZ << scan) / 200))
-                       scan = LAST_SCAN;
-
-               start = 0;
-               rcu_read_lock();
-               radix_tree_for_each_tagged(slot, &mapping->i_pages, &iter,
-                                          start, SHMEM_TAG_PINNED) {
-
-                       page = radix_tree_deref_slot(slot);
-                       if (radix_tree_exception(page)) {
-                               if (radix_tree_deref_retry(page)) {
-                                       slot = radix_tree_iter_retry(&iter);
-                                       continue;
-                               }
-
-                               page = NULL;
-                       }
-
-                       if (page &&
-                           page_count(page) - page_mapcount(page) != 1) {
-                               if (scan < LAST_SCAN)
-                                       goto continue_resched;
-
-                               /*
-                                * On the last scan, we clean up all those tags
-                                * we inserted; but make a note that we still
-                                * found pages pinned.
-                                */
-                               error = -EBUSY;
-                       }
-
-                       xa_lock_irq(&mapping->i_pages);
-                       radix_tree_tag_clear(&mapping->i_pages,
-                                            iter.index, SHMEM_TAG_PINNED);
-                       xa_unlock_irq(&mapping->i_pages);
-continue_resched:
-                       if (need_resched()) {
-                               slot = radix_tree_iter_resume(slot, &iter);
-                               cond_resched_rcu();
-                       }
-               }
-               rcu_read_unlock();
-       }
-
-       return error;
-}
-
-static unsigned int *memfd_file_seals_ptr(struct file *file)
-{
-       if (file->f_op == &shmem_file_operations)
-               return &SHMEM_I(file_inode(file))->seals;
-
-#ifdef CONFIG_HUGETLBFS
-       if (file->f_op == &hugetlbfs_file_operations)
-               return &HUGETLBFS_I(file_inode(file))->seals;
-#endif
-
-       return NULL;
-}
-
-#define F_ALL_SEALS (F_SEAL_SEAL | \
-                    F_SEAL_SHRINK | \
-                    F_SEAL_GROW | \
-                    F_SEAL_WRITE)
-
-static int memfd_add_seals(struct file *file, unsigned int seals)
-{
-       struct inode *inode = file_inode(file);
-       unsigned int *file_seals;
-       int error;
-
-       /*
-        * SEALING
-        * Sealing allows multiple parties to share a shmem-file but restrict
-        * access to a specific subset of file operations. Seals can only be
-        * added, but never removed. This way, mutually untrusted parties can
-        * share common memory regions with a well-defined policy. A malicious
-        * peer can thus never perform unwanted operations on a shared object.
-        *
-        * Seals are only supported on special shmem-files and always affect
-        * the whole underlying inode. Once a seal is set, it may prevent some
-        * kinds of access to the file. Currently, the following seals are
-        * defined:
-        *   SEAL_SEAL: Prevent further seals from being set on this file
-        *   SEAL_SHRINK: Prevent the file from shrinking
-        *   SEAL_GROW: Prevent the file from growing
-        *   SEAL_WRITE: Prevent write access to the file
-        *
-        * As we don't require any trust relationship between two parties, we
-        * must prevent seals from being removed. Therefore, sealing a file
-        * only adds a given set of seals to the file, it never touches
-        * existing seals. Furthermore, the "setting seals"-operation can be
-        * sealed itself, which basically prevents any further seal from being
-        * added.
-        *
-        * Semantics of sealing are only defined on volatile files. Only
-        * anonymous shmem files support sealing. More importantly, seals are
-        * never written to disk. Therefore, there's no plan to support it on
-        * other file types.
-        */
-
-       if (!(file->f_mode & FMODE_WRITE))
-               return -EPERM;
-       if (seals & ~(unsigned int)F_ALL_SEALS)
-               return -EINVAL;
-
-       inode_lock(inode);
-
-       file_seals = memfd_file_seals_ptr(file);
-       if (!file_seals) {
-               error = -EINVAL;
-               goto unlock;
-       }
-
-       if (*file_seals & F_SEAL_SEAL) {
-               error = -EPERM;
-               goto unlock;
-       }
-
-       if ((seals & F_SEAL_WRITE) && !(*file_seals & F_SEAL_WRITE)) {
-               error = mapping_deny_writable(file->f_mapping);
-               if (error)
-                       goto unlock;
-
-               error = shmem_wait_for_pins(file->f_mapping);
-               if (error) {
-                       mapping_allow_writable(file->f_mapping);
-                       goto unlock;
-               }
-       }
-
-       *file_seals |= seals;
-       error = 0;
-
-unlock:
-       inode_unlock(inode);
-       return error;
-}
-
-static int memfd_get_seals(struct file *file)
-{
-       unsigned int *seals = memfd_file_seals_ptr(file);
-
-       return seals ? *seals : -EINVAL;
-}
-
-long memfd_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       long error;
-
-       switch (cmd) {
-       case F_ADD_SEALS:
-               /* disallow upper 32bit */
-               if (arg > UINT_MAX)
-                       return -EINVAL;
-
-               error = memfd_add_seals(file, arg);
-               break;
-       case F_GET_SEALS:
-               error = memfd_get_seals(file);
-               break;
-       default:
-               error = -EINVAL;
-               break;
-       }
-
-       return error;
-}
-
 static long shmem_fallocate(struct file *file, int mode, loff_t offset,
                                                         loff_t len)
 {
@@ -3233,7 +3013,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        if (len > PAGE_SIZE)
                return -ENAMETOOLONG;
 
-       inode = shmem_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0, VM_NORESERVE);
+       inode = shmem_get_inode(dir->i_sb, dir, S_IFLNK | 0777, 0,
+                               VM_NORESERVE);
        if (!inode)
                return -ENOSPC;
 
@@ -3428,6 +3209,15 @@ static int shmem_match(struct inode *ino, void *vfh)
        return ino->i_ino == inum && fh[0] == ino->i_generation;
 }
 
+/* Find any alias of inode, but prefer a hashed alias */
+static struct dentry *shmem_find_alias(struct inode *inode)
+{
+       struct dentry *alias = d_find_alias(inode);
+
+       return alias ?: d_find_any_alias(inode);
+}
+
+
 static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
                struct fid *fid, int fh_len, int fh_type)
 {
@@ -3444,7 +3234,7 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
        inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
                        shmem_match, fid->raw);
        if (inode) {
-               dentry = d_find_alias(inode);
+               dentry = shmem_find_alias(inode);
                iput(inode);
        }
 
@@ -3656,7 +3446,7 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root)
                        sbinfo->max_blocks << (PAGE_SHIFT - 10));
        if (sbinfo->max_inodes != shmem_default_max_inodes())
                seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes);
-       if (sbinfo->mode != (S_IRWXUGO | S_ISVTX))
+       if (sbinfo->mode != (0777 | S_ISVTX))
                seq_printf(seq, ",mode=%03ho", sbinfo->mode);
        if (!uid_eq(sbinfo->uid, GLOBAL_ROOT_UID))
                seq_printf(seq, ",uid=%u",
@@ -3673,93 +3463,6 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root)
        return 0;
 }
 
-#define MFD_NAME_PREFIX "memfd:"
-#define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1)
-#define MFD_NAME_MAX_LEN (NAME_MAX - MFD_NAME_PREFIX_LEN)
-
-#define MFD_ALL_FLAGS (MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB)
-
-SYSCALL_DEFINE2(memfd_create,
-               const char __user *, uname,
-               unsigned int, flags)
-{
-       unsigned int *file_seals;
-       struct file *file;
-       int fd, error;
-       char *name;
-       long len;
-
-       if (!(flags & MFD_HUGETLB)) {
-               if (flags & ~(unsigned int)MFD_ALL_FLAGS)
-                       return -EINVAL;
-       } else {
-               /* Allow huge page size encoding in flags. */
-               if (flags & ~(unsigned int)(MFD_ALL_FLAGS |
-                               (MFD_HUGE_MASK << MFD_HUGE_SHIFT)))
-                       return -EINVAL;
-       }
-
-       /* length includes terminating zero */
-       len = strnlen_user(uname, MFD_NAME_MAX_LEN + 1);
-       if (len <= 0)
-               return -EFAULT;
-       if (len > MFD_NAME_MAX_LEN + 1)
-               return -EINVAL;
-
-       name = kmalloc(len + MFD_NAME_PREFIX_LEN, GFP_KERNEL);
-       if (!name)
-               return -ENOMEM;
-
-       strcpy(name, MFD_NAME_PREFIX);
-       if (copy_from_user(&name[MFD_NAME_PREFIX_LEN], uname, len)) {
-               error = -EFAULT;
-               goto err_name;
-       }
-
-       /* terminating-zero may have changed after strnlen_user() returned */
-       if (name[len + MFD_NAME_PREFIX_LEN - 1]) {
-               error = -EFAULT;
-               goto err_name;
-       }
-
-       fd = get_unused_fd_flags((flags & MFD_CLOEXEC) ? O_CLOEXEC : 0);
-       if (fd < 0) {
-               error = fd;
-               goto err_name;
-       }
-
-       if (flags & MFD_HUGETLB) {
-               struct user_struct *user = NULL;
-
-               file = hugetlb_file_setup(name, 0, VM_NORESERVE, &user,
-                                       HUGETLB_ANONHUGE_INODE,
-                                       (flags >> MFD_HUGE_SHIFT) &
-                                       MFD_HUGE_MASK);
-       } else
-               file = shmem_file_setup(name, 0, VM_NORESERVE);
-       if (IS_ERR(file)) {
-               error = PTR_ERR(file);
-               goto err_fd;
-       }
-       file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
-       file->f_flags |= O_RDWR | O_LARGEFILE;
-
-       if (flags & MFD_ALLOW_SEALING) {
-               file_seals = memfd_file_seals_ptr(file);
-               *file_seals &= ~F_SEAL_SEAL;
-       }
-
-       fd_install(fd, file);
-       kfree(name);
-       return fd;
-
-err_fd:
-       put_unused_fd(fd);
-err_name:
-       kfree(name);
-       return error;
-}
-
 #endif /* CONFIG_TMPFS */
 
 static void shmem_put_super(struct super_block *sb)
@@ -3784,7 +3487,7 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbinfo)
                return -ENOMEM;
 
-       sbinfo->mode = S_IRWXUGO | S_ISVTX;
+       sbinfo->mode = 0777 | S_ISVTX;
        sbinfo->uid = current_fsuid();
        sbinfo->gid = current_fsgid();
        sb->s_fs_info = sbinfo;
@@ -4227,7 +3930,7 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
        d_set_d_op(path.dentry, &anon_ops);
 
        res = ERR_PTR(-ENOSPC);
-       inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags);
+       inode = shmem_get_inode(sb, NULL, S_IFREG | 0777, 0, flags);
        if (!inode)
                goto put_memory;