~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to fs/ramfs/file-nommu.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* file-nommu.c: no-MMU version of ramfs
 
2
 *
 
3
 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
 
4
 * Written by David Howells (dhowells@redhat.com)
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version
 
9
 * 2 of the License, or (at your option) any later version.
 
10
 */
 
11
 
 
12
#include <linux/module.h>
 
13
#include <linux/fs.h>
 
14
#include <linux/mm.h>
 
15
#include <linux/pagemap.h>
 
16
#include <linux/highmem.h>
 
17
#include <linux/init.h>
 
18
#include <linux/string.h>
 
19
#include <linux/backing-dev.h>
 
20
#include <linux/ramfs.h>
 
21
#include <linux/pagevec.h>
 
22
#include <linux/mman.h>
 
23
#include <linux/sched.h>
 
24
#include <linux/slab.h>
 
25
 
 
26
#include <asm/uaccess.h>
 
27
#include "internal.h"
 
28
 
 
29
static int ramfs_nommu_setattr(struct dentry *, struct iattr *);
 
30
 
 
31
const struct address_space_operations ramfs_aops = {
 
32
        .readpage               = simple_readpage,
 
33
        .write_begin            = simple_write_begin,
 
34
        .write_end              = simple_write_end,
 
35
        .set_page_dirty         = __set_page_dirty_no_writeback,
 
36
};
 
37
 
 
38
const struct file_operations ramfs_file_operations = {
 
39
        .mmap                   = ramfs_nommu_mmap,
 
40
        .get_unmapped_area      = ramfs_nommu_get_unmapped_area,
 
41
        .read                   = do_sync_read,
 
42
        .aio_read               = generic_file_aio_read,
 
43
        .write                  = do_sync_write,
 
44
        .aio_write              = generic_file_aio_write,
 
45
        .fsync                  = noop_fsync,
 
46
        .splice_read            = generic_file_splice_read,
 
47
        .splice_write           = generic_file_splice_write,
 
48
        .llseek                 = generic_file_llseek,
 
49
};
 
50
 
 
51
const struct inode_operations ramfs_file_inode_operations = {
 
52
        .setattr                = ramfs_nommu_setattr,
 
53
        .getattr                = simple_getattr,
 
54
};
 
55
 
 
56
/*****************************************************************************/
 
57
/*
 
58
 * add a contiguous set of pages into a ramfs inode when it's truncated from
 
59
 * size 0 on the assumption that it's going to be used for an mmap of shared
 
60
 * memory
 
61
 */
 
62
int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
 
63
{
 
64
        unsigned long npages, xpages, loop;
 
65
        struct page *pages;
 
66
        unsigned order;
 
67
        void *data;
 
68
        int ret;
 
69
 
 
70
        /* make various checks */
 
71
        order = get_order(newsize);
 
72
        if (unlikely(order >= MAX_ORDER))
 
73
                return -EFBIG;
 
74
 
 
75
        ret = inode_newsize_ok(inode, newsize);
 
76
        if (ret)
 
77
                return ret;
 
78
 
 
79
        i_size_write(inode, newsize);
 
80
 
 
81
        /* allocate enough contiguous pages to be able to satisfy the
 
82
         * request */
 
83
        pages = alloc_pages(mapping_gfp_mask(inode->i_mapping), order);
 
84
        if (!pages)
 
85
                return -ENOMEM;
 
86
 
 
87
        /* split the high-order page into an array of single pages */
 
88
        xpages = 1UL << order;
 
89
        npages = (newsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
90
 
 
91
        split_page(pages, order);
 
92
 
 
93
        /* trim off any pages we don't actually require */
 
94
        for (loop = npages; loop < xpages; loop++)
 
95
                __free_page(pages + loop);
 
96
 
 
97
        /* clear the memory we allocated */
 
98
        newsize = PAGE_SIZE * npages;
 
99
        data = page_address(pages);
 
100
        memset(data, 0, newsize);
 
101
 
 
102
        /* attach all the pages to the inode's address space */
 
103
        for (loop = 0; loop < npages; loop++) {
 
104
                struct page *page = pages + loop;
 
105
 
 
106
                ret = add_to_page_cache_lru(page, inode->i_mapping, loop,
 
107
                                        GFP_KERNEL);
 
108
                if (ret < 0)
 
109
                        goto add_error;
 
110
 
 
111
                /* prevent the page from being discarded on memory pressure */
 
112
                SetPageDirty(page);
 
113
 
 
114
                unlock_page(page);
 
115
                put_page(page);
 
116
        }
 
117
 
 
118
        return 0;
 
119
 
 
120
add_error:
 
121
        while (loop < npages)
 
122
                __free_page(pages + loop++);
 
123
        return ret;
 
124
}
 
125
 
 
126
/*****************************************************************************/
 
127
/*
 
128
 *
 
129
 */
 
130
static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size)
 
131
{
 
132
        int ret;
 
133
 
 
134
        /* assume a truncate from zero size is going to be for the purposes of
 
135
         * shared mmap */
 
136
        if (size == 0) {
 
137
                if (unlikely(newsize >> 32))
 
138
                        return -EFBIG;
 
139
 
 
140
                return ramfs_nommu_expand_for_mapping(inode, newsize);
 
141
        }
 
142
 
 
143
        /* check that a decrease in size doesn't cut off any shared mappings */
 
144
        if (newsize < size) {
 
145
                ret = nommu_shrink_inode_mappings(inode, size, newsize);
 
146
                if (ret < 0)
 
147
                        return ret;
 
148
        }
 
149
 
 
150
        truncate_setsize(inode, newsize);
 
151
        return 0;
 
152
}
 
153
 
 
154
/*****************************************************************************/
 
155
/*
 
156
 * handle a change of attributes
 
157
 * - we're specifically interested in a change of size
 
158
 */
 
159
static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
 
160
{
 
161
        struct inode *inode = dentry->d_inode;
 
162
        unsigned int old_ia_valid = ia->ia_valid;
 
163
        int ret = 0;
 
164
 
 
165
        /* POSIX UID/GID verification for setting inode attributes */
 
166
        ret = inode_change_ok(inode, ia);
 
167
        if (ret)
 
168
                return ret;
 
169
 
 
170
        /* pick out size-changing events */
 
171
        if (ia->ia_valid & ATTR_SIZE) {
 
172
                loff_t size = inode->i_size;
 
173
 
 
174
                if (ia->ia_size != size) {
 
175
                        ret = ramfs_nommu_resize(inode, ia->ia_size, size);
 
176
                        if (ret < 0 || ia->ia_valid == ATTR_SIZE)
 
177
                                goto out;
 
178
                } else {
 
179
                        /* we skipped the truncate but must still update
 
180
                         * timestamps
 
181
                         */
 
182
                        ia->ia_valid |= ATTR_MTIME|ATTR_CTIME;
 
183
                }
 
184
        }
 
185
 
 
186
        setattr_copy(inode, ia);
 
187
 out:
 
188
        ia->ia_valid = old_ia_valid;
 
189
        return ret;
 
190
}
 
191
 
 
192
/*****************************************************************************/
 
193
/*
 
194
 * try to determine where a shared mapping can be made
 
195
 * - we require that:
 
196
 *   - the pages to be mapped must exist
 
197
 *   - the pages be physically contiguous in sequence
 
198
 */
 
199
unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
 
200
                                            unsigned long addr, unsigned long len,
 
201
                                            unsigned long pgoff, unsigned long flags)
 
202
{
 
203
        unsigned long maxpages, lpages, nr, loop, ret;
 
204
        struct inode *inode = file->f_path.dentry->d_inode;
 
205
        struct page **pages = NULL, **ptr, *page;
 
206
        loff_t isize;
 
207
 
 
208
        if (!(flags & MAP_SHARED))
 
209
                return addr;
 
210
 
 
211
        /* the mapping mustn't extend beyond the EOF */
 
212
        lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
213
        isize = i_size_read(inode);
 
214
 
 
215
        ret = -EINVAL;
 
216
        maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
217
        if (pgoff >= maxpages)
 
218
                goto out;
 
219
 
 
220
        if (maxpages - pgoff < lpages)
 
221
                goto out;
 
222
 
 
223
        /* gang-find the pages */
 
224
        ret = -ENOMEM;
 
225
        pages = kzalloc(lpages * sizeof(struct page *), GFP_KERNEL);
 
226
        if (!pages)
 
227
                goto out_free;
 
228
 
 
229
        nr = find_get_pages(inode->i_mapping, pgoff, lpages, pages);
 
230
        if (nr != lpages)
 
231
                goto out_free_pages; /* leave if some pages were missing */
 
232
 
 
233
        /* check the pages for physical adjacency */
 
234
        ptr = pages;
 
235
        page = *ptr++;
 
236
        page++;
 
237
        for (loop = lpages; loop > 1; loop--)
 
238
                if (*ptr++ != page++)
 
239
                        goto out_free_pages;
 
240
 
 
241
        /* okay - all conditions fulfilled */
 
242
        ret = (unsigned long) page_address(pages[0]);
 
243
 
 
244
out_free_pages:
 
245
        ptr = pages;
 
246
        for (loop = nr; loop > 0; loop--)
 
247
                put_page(*ptr++);
 
248
out_free:
 
249
        kfree(pages);
 
250
out:
 
251
        return ret;
 
252
}
 
253
 
 
254
/*****************************************************************************/
 
255
/*
 
256
 * set up a mapping for shared memory segments
 
257
 */
 
258
int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma)
 
259
{
 
260
        if (!(vma->vm_flags & VM_SHARED))
 
261
                return -ENOSYS;
 
262
 
 
263
        file_accessed(file);
 
264
        vma->vm_ops = &generic_file_vm_ops;
 
265
        return 0;
 
266
}