--- linux/mm/shmem.c 2004-06-15 09:51:54.000000000 +0400 +++ linux/mm/shmem.c 2004-06-15 17:03:04.000000000 +0400 @@ -169,6 +169,7 @@ static struct inode_operations shmem_inode_operations; static struct inode_operations shmem_dir_inode_operations; static struct vm_operations_struct shmem_vm_ops; +static struct vm_operations_struct shmem_zero_vm_ops; static struct backing_dev_info shmem_backing_dev_info = { .ra_pages = 0, /* No readahead */ @@ -1095,6 +1096,27 @@ return page; } +struct page *shmem_zero_nopage(struct vm_area_struct *vma, unsigned long address, int *type) +{ + struct inode *inode = vma->vm_file->f_dentry->d_inode; + loff_t vm_size = address + PAGE_SIZE - vma->vm_start; + loff_t i_size = i_size_read(inode); + + if (i_size < vm_size) { + int error; + error = shmem_acct_size(SHMEM_I(inode)->flags, vm_size - i_size); + if (error) + return NOPAGE_SIGBUS; + down(&inode->i_sem); + error = vmtruncate(inode, vm_size); + up(&inode->i_sem); + if (error) + return NOPAGE_SIGBUS; + } + + return shmem_nopage(vma, address, type); +} + static int shmem_populate(struct vm_area_struct *vma, unsigned long addr, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock) @@ -1970,6 +1992,15 @@ #endif }; +static struct vm_operations_struct shmem_zero_vm_ops = { + .nopage = shmem_zero_nopage, + .populate = shmem_populate, +#ifdef CONFIG_NUMA + .set_policy = shmem_set_policy, + .get_policy = shmem_get_policy, +#endif +}; + static struct super_block *shmem_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -2101,7 +2132,7 @@ if (vma->vm_file) fput(vma->vm_file); vma->vm_file = file; - vma->vm_ops = &shmem_vm_ops; + vma->vm_ops = &shmem_zero_vm_ops; return 0; }