X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=mm%2Fshmem.c;h=9ffbea9b79e15370b540ffcce2207e5714091e0e;hb=558481f038e587b22d02167af58914c814ce9de5;hp=0b591c669b2de67527763e1f59c79d59021a1586;hpb=52cd3b074050dd664380b5e8cfc85d4a6ed8ad48;p=linux-2.6 diff --git a/mm/shmem.c b/mm/shmem.c index 0b591c669b..9ffbea9b79 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -201,7 +201,7 @@ static struct vm_operations_struct shmem_vm_ops; static struct backing_dev_info shmem_backing_dev_info __read_mostly = { .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, .unplug_io_fn = default_unplug_io_fn, }; @@ -1079,108 +1079,28 @@ redirty: #ifdef CONFIG_NUMA #ifdef CONFIG_TMPFS -static int shmem_parse_mpol(char *value, unsigned short *policy, - unsigned short *mode_flags, nodemask_t *policy_nodes) +static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol) { - char *nodelist = strchr(value, ':'); - char *flags = strchr(value, '='); - int err = 1; + char buffer[64]; - if (nodelist) { - /* NUL-terminate policy string */ - *nodelist++ = '\0'; - if (nodelist_parse(nodelist, *policy_nodes)) - goto out; - if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY])) - goto out; - } - if (flags) - *flags++ = '\0'; - 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 online nodes with memory if no nodelist - */ - if (!nodelist) - *policy_nodes = node_states[N_HIGH_MEMORY]; - err = 0; - } + if (!mpol || mpol->mode == MPOL_DEFAULT) + return; /* show nothing */ - *mode_flags = 0; - if (flags) { - /* - * Currently, we only support two mutually exclusive - * mode flags. - */ - if (!strcmp(flags, "static")) - *mode_flags |= MPOL_F_STATIC_NODES; - else if (!strcmp(flags, "relative")) - *mode_flags |= MPOL_F_RELATIVE_NODES; - else - err = 1; /* unrecognized flag */ - } -out: - /* Restore string for error message */ - if (nodelist) - *--nodelist = ':'; - if (flags) - *--flags = '='; - return err; + mpol_to_str(buffer, sizeof(buffer), mpol, 1); + + seq_printf(seq, ",mpol=%s", buffer); } -static void shmem_show_mpol(struct seq_file *seq, unsigned short policy, - unsigned short flags, const nodemask_t policy_nodes) +static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) { - char *policy_string; - - switch (policy) { - case MPOL_PREFERRED: - policy_string = "prefer"; - break; - case MPOL_BIND: - policy_string = "bind"; - break; - case MPOL_INTERLEAVE: - policy_string = "interleave"; - break; - default: - /* MPOL_DEFAULT */ - return; - } - - seq_printf(seq, ",mpol=%s", policy_string); - - if (policy != MPOL_INTERLEAVE || - !nodes_equal(policy_nodes, node_states[N_HIGH_MEMORY])) { - char buffer[64]; - int len; - - len = nodelist_scnprintf(buffer, sizeof(buffer), policy_nodes); - if (len < sizeof(buffer)) - seq_printf(seq, ":%s", buffer); - else - seq_printf(seq, ":?"); + struct mempolicy *mpol = NULL; + if (sbinfo->mpol) { + spin_lock(&sbinfo->stat_lock); /* prevent replace/use races */ + mpol = sbinfo->mpol; + mpol_get(mpol); + spin_unlock(&sbinfo->stat_lock); } + return mpol; } #endif /* CONFIG_TMPFS */ @@ -1221,14 +1141,7 @@ static struct page *shmem_alloc_page(gfp_t gfp, } #else /* !CONFIG_NUMA */ #ifdef CONFIG_TMPFS -static inline int shmem_parse_mpol(char *value, unsigned short *policy, - unsigned short *mode_flags, nodemask_t *policy_nodes) -{ - return 1; -} - -static inline void shmem_show_mpol(struct seq_file *seq, unsigned short policy, - unsigned short flags, const nodemask_t policy_nodes) +static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *p) { } #endif /* CONFIG_TMPFS */ @@ -1246,6 +1159,13 @@ static inline struct page *shmem_alloc_page(gfp_t gfp, } #endif /* CONFIG_NUMA */ +#if !defined(CONFIG_NUMA) || !defined(CONFIG_TMPFS) +static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) +{ + return NULL; +} +#endif + /* * shmem_getpage - either get the page from swap or allocate a new one * @@ -1600,8 +1520,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) case S_IFREG: inode->i_op = &shmem_inode_operations; inode->i_fop = &shmem_file_operations; - mpol_shared_policy_init(&info->policy, sbinfo->policy, - sbinfo->flags, &sbinfo->policy_nodes); + mpol_shared_policy_init(&info->policy, + shmem_get_sbmpol(sbinfo)); break; case S_IFDIR: inc_nlink(inode); @@ -1615,8 +1535,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) * Must not load anything in the rbtree, * mpol_free_shared_policy will not be called. */ - mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, 0, - NULL); + mpol_shared_policy_init(&info->policy, NULL); break; } } else @@ -1771,26 +1690,38 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ file_accessed(filp); } -static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) +static ssize_t shmem_file_aio_read(struct kiocb *iocb, + const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - read_descriptor_t desc; + struct file *filp = iocb->ki_filp; + ssize_t retval; + unsigned long seg; + size_t count; + loff_t *ppos = &iocb->ki_pos; - if ((ssize_t) count < 0) - return -EINVAL; - if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; - if (!count) - return 0; + retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); + if (retval) + return retval; - desc.written = 0; - desc.count = count; - desc.arg.buf = buf; - desc.error = 0; + for (seg = 0; seg < nr_segs; seg++) { + read_descriptor_t desc; - do_shmem_file_read(filp, ppos, &desc, file_read_actor); - if (desc.written) - return desc.written; - return desc.error; + desc.written = 0; + desc.arg.buf = iov[seg].iov_base; + desc.count = iov[seg].iov_len; + if (desc.count == 0) + continue; + desc.error = 0; + do_shmem_file_read(filp, ppos, &desc, file_read_actor); + retval += desc.written; + if (desc.error) { + retval = retval ?: desc.error; + break; + } + if (desc.count > 0) + break; + } + return retval; } static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) @@ -2231,8 +2162,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo, if (*rest) goto bad_val; } else if (!strcmp(this_char,"mpol")) { - if (shmem_parse_mpol(value, &sbinfo->policy, - &sbinfo->flags, &sbinfo->policy_nodes)) + if (mpol_parse_str(value, &sbinfo->mpol, 1)) goto bad_val; } else { printk(KERN_ERR "tmpfs: Bad mount option %s\n", @@ -2283,9 +2213,9 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) sbinfo->free_blocks = config.max_blocks - blocks; sbinfo->max_inodes = config.max_inodes; sbinfo->free_inodes = config.max_inodes - inodes; - sbinfo->policy = config.policy; - sbinfo->flags = config.flags; - sbinfo->policy_nodes = config.policy_nodes; + + mpol_put(sbinfo->mpol); + sbinfo->mpol = config.mpol; /* transfers initial ref */ out: spin_unlock(&sbinfo->stat_lock); return error; @@ -2306,8 +2236,7 @@ static int shmem_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_printf(seq, ",uid=%u", sbinfo->uid); if (sbinfo->gid != 0) seq_printf(seq, ",gid=%u", sbinfo->gid); - shmem_show_mpol(seq, sbinfo->policy, sbinfo->flags, - sbinfo->policy_nodes); + shmem_show_mpol(seq, sbinfo->mpol); return 0; } #endif /* CONFIG_TMPFS */ @@ -2337,9 +2266,7 @@ static int shmem_fill_super(struct super_block *sb, sbinfo->mode = S_IRWXUGO | S_ISVTX; sbinfo->uid = current->fsuid; sbinfo->gid = current->fsgid; - sbinfo->policy = MPOL_DEFAULT; - sbinfo->flags = 0; - sbinfo->policy_nodes = node_states[N_HIGH_MEMORY]; + sbinfo->mpol = NULL; sb->s_fs_info = sbinfo; #ifdef CONFIG_TMPFS @@ -2454,8 +2381,9 @@ static const struct file_operations shmem_file_operations = { .mmap = shmem_mmap, #ifdef CONFIG_TMPFS .llseek = generic_file_llseek, - .read = shmem_file_read, + .read = do_sync_read, .write = do_sync_write, + .aio_read = shmem_file_aio_read, .aio_write = generic_file_aio_write, .fsync = simple_sync_file, .splice_read = generic_file_splice_read,