]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/shmem.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[karo-tx-linux.git] / mm / shmem.c
index 320ffc1d1d1eb1e0c78ab205ab86181bdc93c75d..ed2befb4952e1805d8407ab1716acb56be052305 100644 (file)
@@ -335,19 +335,19 @@ static unsigned shmem_find_get_pages_and_swap(struct address_space *mapping,
                                        pgoff_t start, unsigned int nr_pages,
                                        struct page **pages, pgoff_t *indices)
 {
-       unsigned int i;
-       unsigned int ret;
-       unsigned int nr_found;
+       void **slot;
+       unsigned int ret = 0;
+       struct radix_tree_iter iter;
+
+       if (!nr_pages)
+               return 0;
 
        rcu_read_lock();
 restart:
-       nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
-                               (void ***)pages, indices, start, nr_pages);
-       ret = 0;
-       for (i = 0; i < nr_found; i++) {
+       radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) {
                struct page *page;
 repeat:
-               page = radix_tree_deref_slot((void **)pages[i]);
+               page = radix_tree_deref_slot(slot);
                if (unlikely(!page))
                        continue;
                if (radix_tree_exception(page)) {
@@ -364,17 +364,16 @@ repeat:
                        goto repeat;
 
                /* Has the page moved? */
-               if (unlikely(page != *((void **)pages[i]))) {
+               if (unlikely(page != *slot)) {
                        page_cache_release(page);
                        goto repeat;
                }
 export:
-               indices[ret] = indices[i];
+               indices[ret] = iter.index;
                pages[ret] = page;
-               ret++;
+               if (++ret == nr_pages)
+                       break;
        }
-       if (unlikely(!ret && nr_found))
-               goto restart;
        rcu_read_unlock();
        return ret;
 }
@@ -2386,6 +2385,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
                               bool remount)
 {
        char *this_char, *value, *rest;
+       struct mempolicy *mpol = NULL;
        uid_t uid;
        gid_t gid;
 
@@ -2414,7 +2414,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
                        printk(KERN_ERR
                            "tmpfs: No value for mount option '%s'\n",
                            this_char);
-                       return 1;
+                       goto error;
                }
 
                if (!strcmp(this_char,"size")) {
@@ -2463,19 +2463,24 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
                        if (!gid_valid(sbinfo->gid))
                                goto bad_val;
                } else if (!strcmp(this_char,"mpol")) {
-                       if (mpol_parse_str(value, &sbinfo->mpol))
+                       mpol_put(mpol);
+                       mpol = NULL;
+                       if (mpol_parse_str(value, &mpol))
                                goto bad_val;
                } else {
                        printk(KERN_ERR "tmpfs: Bad mount option %s\n",
                               this_char);
-                       return 1;
+                       goto error;
                }
        }
+       sbinfo->mpol = mpol;
        return 0;
 
 bad_val:
        printk(KERN_ERR "tmpfs: Bad value '%s' for mount option '%s'\n",
               value, this_char);
+error:
+       mpol_put(mpol);
        return 1;
 
 }
@@ -2487,6 +2492,7 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
        unsigned long inodes;
        int error = -EINVAL;
 
+       config.mpol = NULL;
        if (shmem_parse_options(data, &config, true))
                return error;
 
@@ -2511,8 +2517,13 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
        sbinfo->max_inodes  = config.max_inodes;
        sbinfo->free_inodes = config.max_inodes - inodes;
 
-       mpol_put(sbinfo->mpol);
-       sbinfo->mpol        = config.mpol;      /* transfers initial ref */
+       /*
+        * Preserve previous mempolicy unless mpol remount option was specified.
+        */
+       if (config.mpol) {
+               mpol_put(sbinfo->mpol);
+               sbinfo->mpol = config.mpol;     /* transfers initial ref */
+       }
 out:
        spin_unlock(&sbinfo->stat_lock);
        return error;
@@ -2545,6 +2556,7 @@ static void shmem_put_super(struct super_block *sb)
        struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 
        percpu_counter_destroy(&sbinfo->used_blocks);
+       mpol_put(sbinfo->mpol);
        kfree(sbinfo);
        sb->s_fs_info = NULL;
 }
@@ -2766,6 +2778,7 @@ static struct file_system_type shmem_fs_type = {
        .name           = "tmpfs",
        .mount          = shmem_mount,
        .kill_sb        = kill_litter_super,
+       .fs_flags       = FS_USERNS_MOUNT,
 };
 
 int __init shmem_init(void)
@@ -2823,6 +2836,7 @@ static struct file_system_type shmem_fs_type = {
        .name           = "tmpfs",
        .mount          = ramfs_mount,
        .kill_sb        = kill_litter_super,
+       .fs_flags       = FS_USERNS_MOUNT,
 };
 
 int __init shmem_init(void)