]> err.no Git - linux-2.6/blobdiff - mm/shmem.c
[PATCH] page migration cleanup: rename "ignrefs" to "migration"
[linux-2.6] / mm / shmem.c
index f7ac7b812f926a24b3ba71bb4757318ab75b357b..84b5cf9b63c519b64b9682f9747152bc10407800 100644 (file)
@@ -45,6 +45,9 @@
 #include <linux/swapops.h>
 #include <linux/mempolicy.h>
 #include <linux/namei.h>
+#include <linux/ctype.h>
+#include <linux/migrate.h>
+
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 #include <asm/pgtable.h>
@@ -874,6 +877,51 @@ redirty:
 }
 
 #ifdef CONFIG_NUMA
+static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
+{
+       char *nodelist = strchr(value, ':');
+       int err = 1;
+
+       if (nodelist) {
+               /* NUL-terminate policy string */
+               *nodelist++ = '\0';
+               if (nodelist_parse(nodelist, *policy_nodes))
+                       goto out;
+       }
+       if (!strcmp(value, "default")) {
+               *policy = MPOL_DEFAULT;
+               /* Don't allow a nodelist */
+               if (!nodelist)
+                       err = 0;
+       } else if (!strcmp(value, "prefer")) {
+               *policy = MPOL_PREFERRED;
+               /* Insist on a nodelist of one node only */
+               if (nodelist) {
+                       char *rest = nodelist;
+                       while (isdigit(*rest))
+                               rest++;
+                       if (!*rest)
+                               err = 0;
+               }
+       } else if (!strcmp(value, "bind")) {
+               *policy = MPOL_BIND;
+               /* Insist on a nodelist */
+               if (nodelist)
+                       err = 0;
+       } else if (!strcmp(value, "interleave")) {
+               *policy = MPOL_INTERLEAVE;
+               /* Default to nodes online if no nodelist */
+               if (!nodelist)
+                       *policy_nodes = node_online_map;
+               err = 0;
+       }
+out:
+       /* Restore string for error message */
+       if (nodelist)
+               *--nodelist = ':';
+       return err;
+}
+
 static struct page *shmem_swapin_async(struct shared_policy *p,
                                       swp_entry_t entry, unsigned long idx)
 {
@@ -926,6 +974,11 @@ shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info,
        return page;
 }
 #else
+static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes)
+{
+       return 1;
+}
+
 static inline struct page *
 shmem_swapin(struct shmem_inode_info *info,swp_entry_t entry,unsigned long idx)
 {
@@ -1028,14 +1081,6 @@ repeat:
                        page_cache_release(swappage);
                        goto repeat;
                }
-               if (!PageSwapCache(swappage)) {
-                       /* Page migration has occured */
-                       shmem_swp_unmap(entry);
-                       spin_unlock(&info->lock);
-                       unlock_page(swappage);
-                       page_cache_release(swappage);
-                       goto repeat;
-               }
                if (PageWriteback(swappage)) {
                        shmem_swp_unmap(entry);
                        spin_unlock(&info->lock);
@@ -1601,9 +1646,9 @@ static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
        return desc.error;
 }
 
-static int shmem_statfs(struct super_block *sb, struct kstatfs *buf)
+static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
+       struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
 
        buf->f_type = TMPFS_MAGIC;
        buf->f_bsize = PAGE_CACHE_SIZE;
@@ -1727,6 +1772,7 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
        if (!simple_empty(dentry))
                return -ENOTEMPTY;
 
+       dentry->d_inode->i_nlink--;
        dir->i_nlink--;
        return shmem_unlink(dir, dentry);
 }
@@ -1859,7 +1905,23 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid,
 {
        char *this_char, *value, *rest;
 
-       while ((this_char = strsep(&options, ",")) != NULL) {
+       while (options != NULL) {
+               this_char = options;
+               for (;;) {
+                       /*
+                        * NUL-terminate this option: unfortunately,
+                        * mount options form a comma-separated list,
+                        * but mpol's nodelist may also contain commas.
+                        */
+                       options = strchr(options, ',');
+                       if (options == NULL)
+                               break;
+                       options++;
+                       if (!isdigit(*options)) {
+                               options[-1] = '\0';
+                               break;
+                       }
+               }
                if (!*this_char)
                        continue;
                if ((value = strchr(this_char,'=')) != NULL) {
@@ -1910,18 +1972,8 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid,
                        if (*rest)
                                goto bad_val;
                } else if (!strcmp(this_char,"mpol")) {
-                       if (!strcmp(value,"default"))
-                               *policy = MPOL_DEFAULT;
-                       else if (!strcmp(value,"preferred"))
-                               *policy = MPOL_PREFERRED;
-                       else if (!strcmp(value,"bind"))
-                               *policy = MPOL_BIND;
-                       else if (!strcmp(value,"interleave"))
-                               *policy = MPOL_INTERLEAVE;
-                       else
+                       if (shmem_parse_mpol(value,policy,policy_nodes))
                                goto bad_val;
-               } else if (!strcmp(this_char,"mpol_nodelist")) {
-                       nodelist_parse(value, *policy_nodes);
                } else {
                        printk(KERN_ERR "tmpfs: Bad mount option %s\n",
                               this_char);
@@ -2043,6 +2095,7 @@ static int shmem_fill_super(struct super_block *sb,
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
        sb->s_magic = TMPFS_MAGIC;
        sb->s_op = &shmem_ops;
+       sb->s_time_gran = 1;
 
        inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
        if (!inode)
@@ -2062,7 +2115,7 @@ failed:
        return err;
 }
 
-static kmem_cache_t *shmem_inode_cachep;
+static struct kmem_cache *shmem_inode_cachep;
 
 static struct inode *shmem_alloc_inode(struct super_block *sb)
 {
@@ -2082,7 +2135,8 @@ static void shmem_destroy_inode(struct inode *inode)
        kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
 }
 
-static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache *cachep,
+                     unsigned long flags)
 {
        struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
 
@@ -2115,6 +2169,7 @@ static struct address_space_operations shmem_aops = {
        .prepare_write  = shmem_prepare_write,
        .commit_write   = simple_commit_write,
 #endif
+       .migratepage    = migrate_page,
 };
 
 static struct file_operations shmem_file_operations = {
@@ -2170,10 +2225,10 @@ static struct vm_operations_struct shmem_vm_ops = {
 };
 
 
-static struct super_block *shmem_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data)
+static int shmem_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-       return get_sb_nodev(fs_type, flags, data, shmem_fill_super);
+       return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt);
 }
 
 static struct file_system_type tmpfs_fs_type = {