diff options
| author | Andrew Morton <akpm@digeo.com> | 2002-10-31 04:09:50 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-31 04:09:50 -0800 |
| commit | 0a4b1945f589ddcedbc7188f7be7e4bc9bea1d90 (patch) | |
| tree | 07e3d1310efdd78a417595112491e4183dd61fe2 | |
| parent | d16dc20cd376abd542aabc44c917278d8c58785c (diff) | |
[PATCH] tmpfs support for remap_file_pages
From Hugh
Instate Ingo's shmem_populate on top of the previous patches, now using
shmem_getpage(,,,SGP_QUICK) for the nonblocking case (its find_lock_page
may block, but rarely for long). Note install_page will need redefining
if PAGE_CACHE_SIZE departs from PAGE_SIZE; note pgoff to populate must
be in terms of PAGE_SIZE; note page_cache_release if install_page fails.
filemap_populate similarly needs page_cache_release when install_page
fails, but filemap.c not included in this patch since we started out
from 2.5.43 rather than 2.5.43-mm2: whereas patches 1-8 could go
directly to 2.5.43, this 9/9 belongs with Ingo's population work.
| -rw-r--r-- | mm/shmem.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 77c30daf60ec..4d1b0463e7be 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -53,6 +53,7 @@ /* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */ enum sgp_type { + SGP_QUICK, /* don't try more than file page cache lookup */ SGP_READ, /* don't exceed i_size, don't allocate page */ SGP_CACHE, /* don't exceed i_size, may allocate page */ SGP_WRITE, /* may exceed i_size, may allocate page */ @@ -757,6 +758,8 @@ repeat: if (filepage && PageUptodate(filepage)) goto done; error = 0; + if (sgp == SGP_QUICK) + goto failed; spin_lock(&info->lock); shmem_recalc_inode(inode); @@ -949,6 +952,42 @@ struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int return page; } +static int shmem_populate(struct vm_area_struct *vma, + unsigned long addr, unsigned long len, + unsigned long prot, unsigned long pgoff, int nonblock) +{ + struct inode *inode = vma->vm_file->f_dentry->d_inode; + struct mm_struct *mm = vma->vm_mm; + enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE; + unsigned long size; + + size = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size) + return -EINVAL; + + while ((long) len > 0) { + struct page *page = NULL; + int err; + /* + * Will need changing if PAGE_CACHE_SIZE != PAGE_SIZE + */ + err = shmem_getpage(inode, pgoff, &page, sgp); + if (err) + return err; + if (page) { + err = install_page(mm, vma, addr, page, prot); + if (err) { + page_cache_release(page); + return err; + } + } + len -= PAGE_SIZE; + addr += PAGE_SIZE; + pgoff++; + } + return 0; +} + void shmem_lock(struct file *file, int lock) { struct inode *inode = file->f_dentry->d_inode; @@ -1821,6 +1860,7 @@ static struct super_operations shmem_ops = { static struct vm_operations_struct shmem_vm_ops = { .nopage = shmem_nopage, + .populate = shmem_populate, }; static struct super_block *shmem_get_sb(struct file_system_type *fs_type, |
