函数源码

Linux Kernel

v5.5.9

Brick Technologies Co., Ltd

Source File:fs\ramfs\file-nommu.c Create Date:2022-07-29 11:11:54
首页 Copyright©Brick

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*****************************************************************************/
/*
 * try to determine where a shared mapping can be made
 * - we require that:
 *   - the pages to be mapped must exist
 *   - the pages be physically contiguous in sequence
 */
static unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
                        unsigned long addr, unsigned long len,
                        unsigned long pgoff, unsigned long flags)
{
    unsigned long maxpages, lpages, nr, loop, ret;
    struct inode *inode = file_inode(file);
    struct page **pages = NULL, **ptr, *page;
    loff_t isize;
 
    /* the mapping mustn't extend beyond the EOF */
    lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
    isize = i_size_read(inode);
 
    ret = -ENOSYS;
    maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT;
    if (pgoff >= maxpages)
        goto out;
 
    if (maxpages - pgoff < lpages)
        goto out;
 
    /* gang-find the pages */
    pages = kcalloc(lpages, sizeof(struct page *), GFP_KERNEL);
    if (!pages)
        goto out_free;
 
    nr = find_get_pages(inode->i_mapping, &pgoff, lpages, pages);
    if (nr != lpages)
        goto out_free_pages; /* leave if some pages were missing */
 
    /* check the pages for physical adjacency */
    ptr = pages;
    page = *ptr++;
    page++;
    for (loop = lpages; loop > 1; loop--)
        if (*ptr++ != page++)
            goto out_free_pages;
 
    /* okay - all conditions fulfilled */
    ret = (unsigned long) page_address(pages[0]);
 
out_free_pages:
    ptr = pages;
    for (loop = nr; loop > 0; loop--)
        put_page(*ptr++);
out_free:
    kfree(pages);
out:
    return ret;
}