Very preliminary patch for Large Files on 32bit Linux
Subsystems (22)
This is my preliminary large file support patch.
This is still untested but I believe it meets the first goal, find everything that needs to be modified.
This has just been tested by compilation. I'm not in a situation where I can reboot my computer just now.
The following things are on my todo:
- Examine the performance consequences of making inode->i_size 64bit.
- Modify Ext2 to support large files on 32 bit platforms.
- Reexaming mmap. Making a 64bit safe mmap looks to be the biggest challenge.
- Implement a backing store structure that serves the same function as an inode does now except is smaller (with one embedded in inodes by default).
And for the long term. Plan to have this code ready for the start of 2.3 Whichever way I play it I see that mmap must be modified in some non-trivial ways...
Eric
arch/alpha/kernel/ptrace.c +1 -1
@@ -264,7 +264,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_index -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
arch/arm/kernel/ptrace.c +1 -1
@@ -179,7 +179,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_index -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
arch/i386/kernel/ptrace.c +1 -1
@@ -187,7 +187,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_index -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
arch/m68k/atari/stram.c +1 -1
@@ -716,7 +716,7 @@DPRINTK ("unswap_pte: page %08lx = entry %08lx was in swap cache; " "exchanging to %08lx\n" ,page_address (pg), entry, page ); - pg->offset = page; + pg->key = page;/* correct change? */ swap_free (entry);return 1 ; }
arch/m68k/kernel/ptrace.c +1 -1
@@ -210,7 +210,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_index -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
arch/mips/kernel/ptrace.c +1 -1
@@ -149,7 +149,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_index -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
arch/ppc/kernel/ptrace.c +1 -1
@@ -204,7 +204,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_index -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
arch/sparc/kernel/ptrace.c +1 -1
@@ -149,7 +149,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_index -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
arch/sparc64/kernel/ptrace.c +1 -1
@@ -180,7 +180,7 @@return NULL ;if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK ].rlim_cur)return NULL ; - vma->vm_offset -= vma->vm_start - addr; + vma->vm_offset -= (vma->vm_start - addr) >>PAGE_SHIFT ; vma->vm_start = addr;return vma; }
drivers/block/loop.c +3 -3
@@ -167,12 +167,12 @@int size;if (S_ISREG (lo->lo_inode->i_mode)) - size = (lo->lo_inode->i_size - lo->lo_offset) /BLOCK_SIZE ; + size = (lo->lo_inode->i_size - lo->lo_offset) >>BLOCK_SIZE_BITS ;else {kdev_t lodev = lo->lo_device;if (blk_size[MAJOR (lodev)]) - size = blk_size[MAJOR (lodev)][MINOR (lodev)] - - lo->lo_offset /BLOCK_SIZE ; + size = (blk_size[MAJOR (lodev)][MINOR (lodev)] - + lo->lo_offset) >>BLOCK_SIZE_BITS ;else size =MAX_DISK_SIZE ; }
drivers/char/fbmem.c +12 -5
@@ -199,25 +199,32 @@ } } -static int fb_mmap (struct file *file,struct vm_area_struct * vma) +static int fb_mmap (struct file *file,struct vm_area_struct * vma,loff_t offset) {struct fb_ops *fb = registered_fb[GET_FB_IDX (file->f_dentry->d_inode->i_rdev)];struct fb_fix_screeninfo fix; +unsigned long vm_offset; +if (offset >PAGE_MAX_MEMORY_OFFSET ) { +return -EINVAL ; + } + vm_offset = offset; + vma->vm_index = offset >>PAGE_SHIFT ;if (! fb)return -ENODEV ; fb->fb_get_fix (&fix,PROC_CONSOLE ()); -if ((vma->vm_end - vma->vm_start + vma->vm_offset) > fix.smem_len) +if ((vma->vm_end - vma->vm_start + vm_offset) > fix.smem_len)return -EINVAL ; - vma->vm_offset +=__pa (fix.smem_start); -if (vma->vm_offset & ~PAGE_MASK ) + vm_offset +=__pa (fix.smem_start); + vma->vm_index = vm_offset >>PAGE_SHIFT ; +if (vm_offset & ~PAGE_MASK )return -ENXIO ;if (CPU_IS_040_OR_060 ) {pgprot_val (vma->vm_page_prot) &= _CACHEMASK040;/* Use write-through cache mode */ pgprot_val (vma->vm_page_prot) |= _PAGE_NOCACHE_S; } -if (remap_page_range (vma->vm_start, vma->vm_offset, +if (remap_page_range (vma->vm_start, vm_offset, vma->vm_end - vma->vm_start, vma->vm_page_prot))return -EAGAIN ; vma->vm_file = file;
drivers/char/mem.c +8 -4
@@ -122,10 +122,14 @@return do_write_mem (file,__va (p), p, buf, count, ppos); } -static int mmap_mem (struct file * file,struct vm_area_struct * vma) +static int mmap_mem (struct file * file,struct vm_area_struct * vma,loff_t loff) { -unsigned long offset = vma->vm_offset; - +unsigned long offset; +if (loff >PAGE_MAX_MEMORY_OFFSET ) { +return -EINVAL ; + } + offset = loff; + vma->vm_index = offset >>PAGE_SHIFT ;if (offset & ~PAGE_MASK )return -ENXIO ;#if defined(__i386__)
@@ -339,7 +343,7 @@return written ? written : -EFAULT ; } -static int mmap_zero (struct file * file,struct vm_area_struct * vma) +static int mmap_zero (struct file * file,struct vm_area_struct * vma,loff_t offset) {if (vma->vm_flags &VM_SHARED )return -EINVAL ;
drivers/sbus/char/sunfb.c +0 -1
@@ -272,7 +272,6 @@FB_SETUP (ENXIO) fb = &fbinfo [minor]; -if (fb->mmap){int v;
drivers/sgi/char/graphics.c +10 -2
@@ -237,12 +237,20 @@ };int -sgi_graphics_mmap (struct inode *inode,struct file *file,struct vm_area_struct *vma) +sgi_graphics_mmap (struct inode *inode,struct file *file,struct vm_area_struct *vma, +loff_t offset) {uint size; +unsigned long vm_offset; + +if (offset >PAGE_MAX_MEMORY_OFFSET ) { +return -EINVAL ; + } + vm_offset = offset; + vma->vm_index = vm_offset >>PAGE_SHIFT ; size = vma->vm_end - vma->vm_start; -if (vma->vm_offset & ~PAGE_MASK ) +if (vm_offset & ~PAGE_MASK )return -ENXIO ;/* 1. Set our special graphic virtualizer */
drivers/sound/soundcard.c +3 -2
@@ -683,7 +683,7 @@return 0 ; } -static int sound_mmap (struct file *file,struct vm_area_struct *vma) +static int sound_mmap (struct file *file,struct vm_area_struct *vma,loff_t offset) {int dev_class;unsigned long size;
@@ -723,7 +723,7 @@/* printk("Sound: mmap() called twice for the same DMA buffer\n");*/ return -EIO ; } -if (vma->vm_offset !=0 ) +if (offset !=0 ) {/* printk("Sound: mmap() offset must be 0.\n");*/ return -EINVAL ;
@@ -740,6 +740,7 @@return -EAGAIN ; vma->vm_file = file; + vma->vm_index =0 ; file->f_count++; dmap->mapping_flags |=DMA_MAP_MAPPED ;
fs/buffer.c +2 -2
@@ -1336,7 +1336,7 @@#endif }if (test_and_clear_bit (PG_swap_unlock_after, &page->flags)) -swap_after_unlock_page (page->offset); +swap_after_unlock_page (page->key);if (test_and_clear_bit (PG_free_after, &page->flags))__free_page (page); }
@@ -1560,7 +1560,7 @@set_bit (PG_free_after, &page->flags); i =PAGE_SIZE >> inode->i_sb->s_blocksize_bits; - block = page->offset >> inode->i_sb->s_blocksize_bits; + block = page->key << (PAGE_SHIFT - inode->i_sb->s_blocksize_bits); p = nr; do { *p = inode->i_op->bmap(inode, block);
fs/coda/file.c +2 -2
@@ -95,8 +95,8 @@coda_prepare_openfile (coda_inode, coda_file, cii->c_ovp, &cont_file, &cont_dentry); -CDEBUG (D_INODE ,"coda ino: %ld, cached ino %ld, page offset: %lx\n" , - coda_inode->i_ino, cii->c_ovp->i_ino, page->offset); +CDEBUG (D_INODE ,"coda ino: %ld, cached ino %ld, page key: %lx\n" , + coda_inode->i_ino, cii->c_ovp->i_ino, page->key);generic_readpage (&cont_file, page);EXIT ;
fs/exec.c +1 -1
@@ -331,7 +331,7 @@ mpnt->vm_page_prot =PAGE_COPY ; mpnt->vm_flags =VM_STACK_FLAGS ; mpnt->vm_ops =NULL ; - mpnt->vm_offset =0 ; + mpnt->vm_index =0 ; mpnt->vm_file =NULL ; mpnt->vm_pte =0 ;insert_vm_struct (current->mm, mpnt);
fs/ext2/truncate.c +2 -2
@@ -68,8 +68,8 @@unsigned long free_count =0 ;int retry =0 ;int blocks = inode->i_sb->s_blocksize /512 ; -#define DIRECT_BLOCK ((inode->i_size + inode->i_sb->s_blocksize - 1) / \ - inode->i_sb->s_blocksize) +#define DIRECT_BLOCK ((inode->i_size + inode->i_sb->s_blocksize - 1) >> \ + inode->i_sb->s_blocksize_bits)int direct_block =DIRECT_BLOCK ; repeat:
fs/fat/mmap.c +7 -3
@@ -42,7 +42,7 @@if (!page)return page; address &=PAGE_MASK ; - pos = address - area->vm_start + area->vm_offset; + pos = address - area->vm_start + (area->vm_index <<PAGE_SHIFT ); clear =0 ; gap = inode->i_size - pos;
@@ -94,16 +94,19 @@* This is used for a general mmap of an msdos file * Returns 0 if ok, or a negative error code if not. */ -int fat_mmap (struct file * file,struct vm_area_struct * vma) +int fat_mmap (struct file * file,struct vm_area_struct * vma,loff_t offset) {struct inode *inode = file->f_dentry->d_inode; +if (offset >PAGE_MAX_MEMORY_OFFSET ) { +return -EINVAL ; + }if (MSDOS_SB (inode->i_sb)->cvf_format &&MSDOS_SB (inode->i_sb)->cvf_format->cvf_mmap)return MSDOS_SB (inode->i_sb)->cvf_format->cvf_mmap (file,vma);if (vma->vm_flags &VM_SHARED )/* only PAGE_COW or read-only supported now */ return -EINVAL ; -if (vma->vm_offset & (inode->i_sb->s_blocksize -1 )) +if (offset & ~PAGE_MASK )return -EINVAL ;if (!inode->i_sb || !S_ISREG (inode->i_mode))return -EACCES ;
@@ -112,6 +115,7 @@mark_inode_dirty (inode); } + vma->vm_index = offset >>PAGE_SHIFT ; vma->vm_file = file; file->f_count++; vma->vm_ops = &fat_file_mmap;
fs/ncpfs/mmap.c +8 -2
@@ -47,7 +47,7 @@if (!page)return page; address &=PAGE_MASK ; - pos = address - area->vm_start + area->vm_offset; + pos = address - area->vm_start + (area->vm_index <<PAGE_SIZE ); clear =0 ;if (address +PAGE_SIZE > area->vm_end) {
@@ -119,7 +119,7 @@/* This is used for a general mmap of a ncp file */ -int ncp_mmap (struct file *file,struct vm_area_struct *vma) +int ncp_mmap (struct file *file,struct vm_area_struct *vma,loff_t offset) {struct inode *inode = file->f_dentry->d_inode;
@@ -127,6 +127,12 @@if (!ncp_conn_valid (NCP_SERVER (inode))) {return -EIO ; + } +if (offset >PAGE_MAX_MEMORY_OFFSET ) { +return -EINVAL ; + } +if (offset & ~PAGE_MASK ) { +return -EINVAL ; }/* only PAGE_COW or read-only supported now */ if (vma->vm_flags &VM_SHARED )
fs/nfs/read.c +3 -3
@@ -69,7 +69,7 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page) { struct nfs_rreq rqst; -unsigned long offset = page->offset; +unsigned long offset = page->key <<PAGE_SHIFT ;char *buffer = (char *)page_address (page);int rsize =NFS_SERVER (inode)->rsize;int result, refresh =0 ;
@@ -183,7 +183,7 @@/* Initialize request */ /* N.B. Will the dentry remain valid for life of request? */ -nfs_readreq_setup (req,NFS_FH (dentry), page->offset, +nfs_readreq_setup (req,NFS_FH (dentry), page->key <<PAGE_SHIT , (void *) address,PAGE_SIZE ); req->ra_inode = inode; req->ra_page = page;/* count has been incremented by caller */
@@ -228,7 +228,7 @@int error =-1 ;dprintk ("NFS: nfs_readpage (%p %ld@%ld)\n" , - page,PAGE_SIZE , page->offset); + page,PAGE_SIZE , page->key <<PAGE_SHIFT );set_bit (PG_locked, &page->flags);atomic_inc (&page->count); if (!IS_SWAPFILE(inode) && !PageError(page) &&
fs/nfs/write.c +10 -10
@@ -97,7 +97,7 @@static inline void nfs_unlock_page (struct page *page) { -dprintk ("NFS: unlock %ld\n" , page->offset); +dprintk ("NFS: unlock %ld\n" , page->key <<PAGE_SHIFT );clear_bit (PG_locked, &page->flags);wake_up (&page->wait);
@@ -146,10 +146,10 @@dprintk ("NFS: nfs_writepage_sync(%s/%s %d@%ld)\n" , dentry->d_parent->d_name.name, dentry->d_name.name, - count, page->offset + offset); + count, (page->key <<PAGE_SHIFT ) + offset); buffer = (u8 *)page_address (page) + offset; - offset += page->offset; + offset += page->key <<PAGE_SHIFT ; do { if (count < wsize && !IS_SWAPFILE(inode))
@@ -377,7 +377,7 @@dprintk ("NFS: create_write_request(%s/%s, %ld+%d)\n" , dentry->d_parent->d_name.name, dentry->d_name.name, - page->offset + offset, bytes); + (page->key <<PAGE_SHIFT ) + offset, bytes);/* FIXME: Enforce hard limit on number of concurrent writes? */
@@ -517,7 +517,7 @@dprintk ("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n" , dentry->d_parent->d_name.name, dentry->d_name.name, - count, page->offset+offset, sync); + count, (page->key <<PAGE_SHIFT )+offset, sync);set_bit (PG_locked, &page->flags);
@@ -617,7 +617,7 @@#endif dprintk ("NFS: nfs_flush_request(%s/%s, @%ld)\n" , req->wb_dentry->d_parent->d_name.name, - req->wb_dentry->d_name.name, page->offset); + req->wb_dentry->d_name.name, page->key <<PAGE_SHIFT ); req->wb_flags |=NFS_WRITE_WANTLOCK ;if (!test_and_set_bit (PG_locked, &page->flags)) {
@@ -647,9 +647,9 @@ req->wb_task.tk_pid, req->wb_dentry->d_parent->d_name.name, req->wb_dentry->d_name.name, - req->wb_page->offset, req->wb_flags); + req->wb_page->key << PAGE_SHIFT, req->wb_flags); - rqoffset = req->wb_page->offset + req->wb_offset; + rqoffset = (req->wb_page->key <<PAGE_SHIFT ) + req->wb_offset; rqend = rqoffset + req->wb_bytes;if (rqoffset < end && offset < rqend && (pid ==0 || req->wb_pid == pid)) {
@@ -777,7 +777,7 @@ req = head =NFS_WRITEBACK (inode);while (req !=NULL ) { - rqoffset = req->wb_page->offset + req->wb_offset; + rqoffset = (req->wb_page->key <<PAGE_SHIFT ) + req->wb_offset;if (rqoffset >= offset) {nfs_cancel_request (req);
@@ -842,7 +842,7 @@/* Setup the task struct for a writeback call */ req->wb_args.fh =NFS_FH (dentry); - req->wb_args.offset = page->offset + req->wb_offset; + req->wb_args.offset = (page->key <<PAGE_SHIFT ) + req->wb_offset; req->wb_args.count = req->wb_bytes; req->wb_args.buffer = (void *) (page_address (page) + req->wb_offset);
fs/proc/array.c +1 -1
@@ -1094,7 +1094,7 @@ len =sprintf (line,sizeof (void *) ==4 ?MAPS_LINE_FORMAT4 :MAPS_LINE_FORMAT8 , - map->vm_start, map->vm_end, str, map->vm_offset, + map->vm_start, map->vm_end, str, map->vm_index,kdevname (dev), ino);if (map->vm_file) {
fs/proc/mem.c +10 -4
@@ -209,7 +209,7 @@/* * This isn't really reliable by any means.. */ -int mem_mmap (struct file * file,struct vm_area_struct * vma) +int mem_mmap (struct file * file,struct vm_area_struct * vma,loff_t offset) {struct task_struct *tsk;pgd_t *src_dir, *dest_dir;
@@ -218,6 +218,7 @@unsigned long stmp, dtmp;struct vm_area_struct *src_vma =NULL ;struct inode *inode = file->f_dentry->d_inode; +unsigned long vm_offset;/* Get the source's task information */
@@ -231,9 +232,14 @@moment because working out the vm_area_struct & nattach stuff isn't worth it. */ +if (offset >PAGE_MAX_MEMORY_OFFSET ) { +return -EINVAL ; + } + vm_offset = offset; + vma->vm_index = vm_offset >>PAGE_SHIFT ; src_vma = tsk->mm->mmap; - stmp = vma->vm_offset; -while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) { + stmp = vm_offset; +while (stmp < ((vma->vm_index <<PAGE_SHIFT ) + (vma->vm_end - vma->vm_start))) {while (src_vma && stmp > src_vma->vm_end) src_vma = src_vma->vm_next;if (!src_vma || (src_vma->vm_flags &VM_SHM ))
@@ -267,7 +273,7 @@ } src_vma = tsk->mm->mmap; - stmp = vma->vm_offset; + stmp = vma->vm_index <<PAGE_SHIFT ; dtmp = vma->vm_start;flush_cache_range (vma->vm_mm, vma->vm_start, vma->vm_end);
fs/romfs/inode.c +1 -1
@@ -401,7 +401,7 @@ buf =page_address (page);clear_bit (PG_uptodate, &page->flags);clear_bit (PG_error, &page->flags); - offset = page->offset; + offset = page->key <<PAGE_SHIFT ;if (offset < inode->i_size) { avail = inode->i_size-offset; readlen =min (avail,PAGE_SIZE );
fs/smbfs/file.c +3 -3
@@ -55,7 +55,7 @@ smb_readpage_sync(struct dentry *dentry, struct page *page) { char *buffer = (char *) page_address(page); -unsigned long offset = page->offset; +unsigned long offset = page->key <<PAGE_SHIFT ;int rsize =smb_get_rsize (server_from_dentry (dentry));int count =PAGE_SIZE ;int result;
@@ -132,7 +132,7 @@int wsize =smb_get_wsize (server_from_dentry (dentry));int result, written =0 ; - offset += page->offset; + offset += page->key <<PAGE_SHIFT ;#ifdef SMBFS_DEBUG_VERBOSE printk ("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n" , dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
@@ -204,7 +204,7 @@pr_debug ("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n" , dentry->d_parent->d_name.name, dentry->d_name.name, - count, page->offset+offset, sync); + count, (page->key <<PAGE_SHIFT )+offset, sync);#ifdef SMBFS_PARANOIA if (test_bit (PG_locked, &page->flags))
include/linux/fs.h +6 -6
@@ -300,7 +300,7 @@umode_t ia_mode;uid_t ia_uid;gid_t ia_gid; -off_t ia_size; +loff_t ia_size;time_t ia_atime;time_t ia_mtime;time_t ia_ctime;
@@ -331,7 +331,7 @@uid_t i_uid;gid_t i_gid;kdev_t i_rdev; -off_t i_size; +loff_t i_size;time_t i_atime;time_t i_mtime;time_t i_ctime;
@@ -441,8 +441,8 @@struct file *fl_file;unsigned char fl_flags;unsigned char fl_type; -off_t fl_start; -off_t fl_end; +loff_t fl_start; +loff_t fl_end;void (*fl_notify)(struct file_lock *);/* unblock callback */
@@ -581,7 +581,7 @@int (*readdir) (struct file *,void *,filldir_t );unsigned int (*poll) (struct file *,struct poll_table_struct *);int (*ioctl) (struct inode *,struct file *,unsigned int ,unsigned long ); -int (*mmap) (struct file *,struct vm_area_struct *); +int (*mmap) (struct file *,struct vm_area_struct *,loff_t off);int (*open) (struct inode *,struct file *);int (*release) (struct inode *,struct file *);int (*fsync) (struct file *,struct dentry *);
@@ -808,7 +808,7 @@extern int brw_page (int ,struct page *,kdev_t ,int [],int ,int );extern int generic_readpage (struct file *,struct page *); -extern int generic_file_mmap (struct file *,struct vm_area_struct *); +extern int generic_file_mmap (struct file *,struct vm_area_struct *,loff_t );extern ssize_t generic_file_read (struct file *,char *,size_t ,loff_t *);extern ssize_t generic_file_write (struct file *,const char *,size_t ,loff_t *);
include/linux/mm.h +21 -10
@@ -47,7 +47,7 @@struct vm_area_struct **vm_pprev_share;struct vm_operations_struct * vm_ops; -unsigned long vm_offset; +unsigned long vm_index;struct file * vm_file;unsigned long vm_pte;/* shared mem */ };
@@ -74,6 +74,10 @@#define VM_LOCKED 0x2000#define VM_IO 0x4000/* Memory mapped I/O or similar */ +#define VM_SPARSE_MERGE 0x8000/* Sparce VMA's with non continous +* indecies may be merged +*/ +#define VM_STACK_FLAGS 0x0177/*
@@ -98,6 +102,7 @@unsigned long (*nopage)(struct vm_area_struct * area,unsigned long address,int write_access);unsigned long (*wppage)(struct vm_area_struct * area,unsigned long address,unsigned long page); +/* swapin & swapout changed! */ int (*swapout)(struct vm_area_struct *,unsigned long ,pte_t *);pte_t (*swapin)(struct vm_area_struct *,unsigned long ,unsigned long ); };
@@ -115,7 +120,7 @@struct page *next;struct page *prev;struct inode *inode; -unsigned long offset; +unsigned long key;struct page *next_hash;atomic_t count;unsigned int age;
@@ -191,8 +196,9 @@* The following discussion applies only to them. * * A page may belong to an inode's memory mapping. In this case, -* page->inode is the inode, and page->offset is the file offset -* of the page (not necessarily a multiple of PAGE_SIZE). +* page->inode is the inode, and page->key is the index into a file. +* Generally the data for a page can be found in the page->inode at +* offset key*PAGE_SIZE. * * A page may have buffers allocated to it. In this case, * page->buffers is a circular list of these buffer heads. Else,
@@ -204,7 +210,7 @@* All pages belonging to an inode make up a doubly linked list * inode->i_pages, using the fields page->next and page->prev. (These * fields are also used for freelist management when page->count==0.) -* There is also a hash table mapping (inode,offset) to the page +* There is also a hash table mapping (inode,key) to the page * in memory if present. The lists for this hash table use the fields * page->next_hash and page->prev_hash. *
@@ -225,7 +231,7 @@* * For choosing which pages to swap out, inode pages carry a * page->referenced bit, which is set any time the system accesses -* that page through the (inode,offset) hash table. +* that page through the (inode,key) hash table. * There is also the page->age counter, which implements a linear * decay (why not an exponential decay?), see swapctl.h. */
@@ -288,7 +294,7 @@extern int remap_page_range (unsigned long from,unsigned long to,unsigned long size,pgprot_t prot);extern int zeromap_page_range (unsigned long from,unsigned long size,pgprot_t prot); -extern void vmtruncate (struct inode * inode,unsigned long offset); +extern void vmtruncate (struct inode * inode,loff_t offset);extern void handle_mm_fault (struct task_struct *tsk,struct vm_area_struct *vma,unsigned long address,int write_access);extern unsigned long paging_init (unsigned long start_mem,unsigned long end_mem);
@@ -300,7 +306,7 @@/* mmap.c */ extern void vma_init (void );extern unsigned long do_mmap (struct file * file,unsigned long addr,unsigned long len, -unsigned long prot,unsigned long flags,unsigned long off); +unsigned long prot,unsigned long flags,loff_t off);extern void merge_segments (struct mm_struct *,unsigned long ,unsigned long );extern void insert_vm_struct (struct mm_struct *,struct vm_area_struct *);extern void exit_mmap (struct mm_struct *);
@@ -310,7 +316,7 @@/* filemap.c */ extern unsigned long page_unuse (unsigned long );extern int shrink_mmap (int ,int ); -extern void truncate_inode_pages (struct inode *,unsigned long ); +extern void truncate_inode_pages (struct inode *,loff_t );extern unsigned long get_cached_page (struct inode *,unsigned long ,int );extern void put_cached_page (unsigned long );
@@ -350,7 +356,7 @@ > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur)return -ENOMEM ; vma->vm_start = address; - vma->vm_offset -= grow; + vma->vm_index -= (grow >>PAGE_SHIFT ); vma->vm_mm->total_vm += grow >>PAGE_SHIFT ;if (vma->vm_flags &VM_LOCKED ) vma->vm_mm->locked_vm += grow >>PAGE_SHIFT ;
@@ -385,6 +391,11 @@ vma =NULL ; return vma; } + +/* The old limit on mmap offsets */ +#define PAGE_MAX_MEMORY_OFFSET (-1UL) +/* The maximum file size we can mmap to one inode */ +#define PAGE_MAX_FILE_OFFSET (((-1UL) * (1ULL << PAGE_SHIFT)) + (PAGE_SIZE -1))#endif /* __KERNEL__ */
include/linux/pagemap.h +10 -10
@@ -31,10 +31,10 @@* inode pointer and offsets are distributed (ie, we * roughly know which bits are "significant") */ -static inline unsigned long _page_hashfn (struct inode * inode,unsigned long offset) +static inline unsigned long _page_hashfn (struct inode * inode,unsigned long key) {#define i (((unsigned long) inode)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1))) -#define o (offset >> PAGE_SHIFT) +#define o (key)#define s (x) ((x)+((x)>>PAGE_HASH_BITS))return s (i+o) & (PAGE_HASH_SIZE -1 );#undef i
@@ -42,9 +42,9 @@#undef s } -#define page_hash (inode,offset) (page_hash_table+_page_hashfn(inode,offset)) +#define page_hash (inode,key) (page_hash_table+_page_hashfn(inode,key)) -static inline struct page *__find_page (struct inode * inode,unsigned long offset,struct page *page) +static inline struct page *__find_page (struct inode * inode,unsigned long key,struct page *page) { goto inside;for (;;) {
@@ -54,7 +54,7 @@ goto not_found;if (page->inode != inode)continue ; -if (page->offset == offset) +if (page->key == key)break ; }/* Found the page. */
@@ -64,9 +64,9 @@return page; } -static inline struct page *find_page (struct inode * inode,unsigned long offset) +static inline struct page *find_page (struct inode * inode,unsigned long key) { -return __find_page (inode, offset, *page_hash (inode, offset)); +return __find_page (inode, key, *page_hash (inode, key)); }static inline void remove_page_from_hash_queue (struct page * page)
@@ -91,9 +91,9 @@ page->pprev_hash = p; } -static inline void add_page_to_hash_queue (struct page * page,struct inode * inode,unsigned long offset) +static inline void add_page_to_hash_queue (struct page * page,struct inode * inode,unsigned long key) { -__add_page_to_hash_queue (page,page_hash (inode,offset)); +__add_page_to_hash_queue (page,page_hash (inode,key)); }static inline void remove_page_from_inode_queue (struct page * page)
@@ -131,6 +131,6 @@ __wait_on_page(page); } -extern void update_vm_cache (struct inode *,unsigned long ,const char *,int ); +extern void update_vm_cache (struct inode *,loff_t ,const char *,int );#endif
include/linux/swap.h +1 -1
@@ -101,7 +101,7 @@extern inline unsigned long in_swap_cache (struct page *page) {if (PageSwapCache (page)) -return page->offset; +return page->key;return 0 ; }
include/linux/wrapper.h +1 -1
@@ -28,7 +28,7 @@#define vma_set_inode (v,i) v->vm_inode = i#define vma_get_flags (v) v->vm_flags -#define vma_get_offset (v) v->vm_offset +/* #define vma_get_offset(v) v->vm_offset */ #define vma_get_start (v) v->vm_start#define vma_get_end (v) v->vm_end#define vma_get_page_prot (v) v->vm_page_prot
ipc/shm.c +8 -8
@@ -386,7 +386,7 @@* shmd->vm_end multiple of SHMLBA * shmd->vm_next next attach for task * shmd->vm_next_share next attach for segment -* shmd->vm_offset offset into segment +* shmd->vm_index page index into segment * shmd->vm_pte signature for this attach */
@@ -447,7 +447,7 @@/* map page range */ error =0 ; shm_sgn = shmd->vm_pte + -SWP_ENTRY (0 , (shmd->vm_offset >>PAGE_SHIFT ) <<SHM_IDX_SHIFT ); +SWP_ENTRY (0 , shmd->vm_index <<SHM_IDX_SHIFT );flush_cache_range (shmd->vm_mm, shmd->vm_start, shmd->vm_end); for (tmp = shmd->vm_start; tmp < shmd->vm_end;
@@ -562,7 +562,7 @@ | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC | ((shmflg &SHM_RDONLY ) ?0 :VM_MAYWRITE |VM_WRITE ); shmd->vm_file =NULL ; - shmd->vm_offset =0 ; + shmd->vm_index =0 ; shmd->vm_ops = &shm_vm_ops; shp->shm_nattch++;/* prevent destruction */
@@ -636,7 +636,7 @@for (shmd = current->mm->mmap; shmd; shmd = shmdnext) { shmdnext = shmd->vm_next;if (shmd->vm_ops == &shm_vm_ops - && shmd->vm_start - shmd->vm_offset == (ulong ) shmaddr) + && shmd->vm_start - (shmd->vm_index <<PAGE_SHIFT ) == (ulong ) shmaddr)do_munmap (shmd->vm_start, shmd->vm_end - shmd->vm_start); }unlock_kernel ();
@@ -646,7 +646,7 @@/* * page not present ... go through shm_pages */ -static pte_t shm_swap_in (struct vm_area_struct * shmd,unsigned long offset,unsigned long code) +static pte_t shm_swap_in (struct vm_area_struct * shmd,unsigned long index,unsigned long code) {pte_t pte;struct shmid_ds *shp;
@@ -668,9 +668,9 @@return BAD_PAGE ; } idx = (SWP_OFFSET (code) >>SHM_IDX_SHIFT ) &SHM_IDX_MASK ; -if (idx != (offset >>PAGE_SHIFT )) { +if (idx != index) {printk ("shm_swap_in: code idx = %u and shmd idx = %lu differ\n" , - idx, offset >>PAGE_SHIFT ); + idx, index);return BAD_PAGE ; }if (idx >= shp->shm_npages) {
@@ -777,7 +777,7 @@ id, SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK);continue ; } - tmp = shmd->vm_start + (idx <<PAGE_SHIFT ) - shmd->vm_offset; + tmp = shmd->vm_start + (idx - shmd->vm_index) <<PAGE_SHIFT ;if (!(tmp >= shmd->vm_start && tmp < shmd->vm_end))continue ; page_dir =pgd_offset (shmd->vm_mm,tmp);
mm/filemap.c +80 -43
307 lines not on this page · raw message
mm/memory.c +15 -5
@@ -719,13 +719,21 @@* between the file and the memory map for a potential last * incomplete page. Ugly, but necessary. */ -void vmtruncate (struct inode * inode,unsigned long offset) +void vmtruncate (struct inode * inode,loff_t offset) { +unsigned long index; +unsigned long partial;struct vm_area_struct * mpnt;truncate_inode_pages (inode, offset); -if (!inode->i_mmap) +if ((!inode->i_mmap) || (offset >PAGE_MAX_FILE_OFFSET )) {return ; + } + index = offset >>PAGE_SHIFT ; + partial = offset &PAGE_MASK ; +if (!partial) { + index--; + } mpnt = inode->i_mmap; do { struct mm_struct *mm = mpnt->vm_mm;
@@ -735,14 +743,14 @@unsigned long diff;/* mapping wholly truncated? */ -if (mpnt->vm_offset >= offset) { +if (mpnt->vm_index > index) {flush_cache_range (mm, start, end);zap_page_range (mm, start, len);flush_tlb_range (mm, start, end);continue ; }/* mapping wholly unaffected? */ - diff = offset - mpnt->vm_offset; + diff = ((index - mpnt->vm_index) <<PAGE_SHIFT ) + partial;if (diff >= len)continue ;/* Ok, partially affected.. */
@@ -764,13 +772,15 @@ pte_t * page_table, pte_t entry, int write_access) { pte_t page; +unsigned long index;if (!vma->vm_ops || !vma->vm_ops->swapin) {swap_in (tsk, vma, page_table,pte_val (entry), write_access);flush_page_to_ram (pte_page (*page_table));return ; } - page = vma->vm_ops->swapin (vma, address - vma->vm_start + vma->vm_offset,pte_val (entry)); + index = ((address - vma->vm_start) >>PAGE_SHIFT ) + vma->vm_index; + page = vma->vm_ops->swapin (vma, index,pte_val (entry));if (pte_val (*page_table) !=pte_val (entry)) {free_page (pte_page (page));return ;
mm/mlock.c +4 -4
@@ -36,7 +36,7 @@ *n = *vma; vma->vm_start = end; n->vm_end = end; - vma->vm_offset += vma->vm_start - n->vm_start; + vma->vm_index += (vma->vm_start - n->vm_start) >>PAGE_SHIFT ; n->vm_flags = newflags;if (n->vm_file) n->vm_file->f_count++;
@@ -57,7 +57,7 @@ *n = *vma; vma->vm_end = start; n->vm_start = start; - n->vm_offset += n->vm_start - vma->vm_start; + n->vm_index += (n->vm_start - vma->vm_start) >>PAGE_SHIFT ; n->vm_flags = newflags;if (n->vm_file) n->vm_file->f_count++;
@@ -86,8 +86,8 @@ vma->vm_start = start; vma->vm_end = end; right->vm_start = end; - vma->vm_offset += vma->vm_start - left->vm_start; - right->vm_offset += right->vm_start - left->vm_start; + vma->vm_index += (vma->vm_start - left->vm_start) >>PAGE_SHIFT ; + right->vm_index += (right->vm_start - left->vm_start) >>PAGE_SHIFT ; vma->vm_flags = newflags;if (vma->vm_file) vma->vm_file->f_count +=2 ;
mm/mmap.c +9 -8
@@ -158,7 +158,7 @@ }unsigned long do_mmap (struct file * file,unsigned long addr,unsigned long len, -unsigned long prot,unsigned long flags,unsigned long off) +unsigned long prot,unsigned long flags,loff_t off) {struct mm_struct * mm = current->mm;struct vm_area_struct * vma;
@@ -261,7 +261,7 @@ vma->vm_flags |=VM_MAYREAD |VM_MAYWRITE |VM_MAYEXEC ; vma->vm_page_prot = protection_map[vma->vm_flags &0x0f ]; vma->vm_ops =NULL ; - vma->vm_offset = off; + vma->vm_index =0 ; vma->vm_file =NULL ; vma->vm_pte =0 ;
@@ -297,7 +297,7 @@ } }if (!error) - error = file->f_op->mmap (file, vma); + error = file->f_op->mmap (file, vma, off); }/* Fix up the count if necessary, then check for an error */
@@ -404,7 +404,7 @@if (end == area->vm_end) area->vm_end = addr;else if (addr == area->vm_start) { - area->vm_offset += (end - area->vm_start); + area->vm_index += ((end - area->vm_start) >>PAGE_SHIFT ); area->vm_start = end; }else {/* Unmapping a hole: area->vm_start < addr <= end < area->vm_end */
@@ -418,7 +418,7 @@ mpnt->vm_page_prot = area->vm_page_prot; mpnt->vm_flags = area->vm_flags; mpnt->vm_ops = area->vm_ops; - mpnt->vm_offset = area->vm_offset + (end - area->vm_start); + mpnt->vm_index = area->vm_index + ((end - area->vm_start) >>PAGE_SHIFT ); mpnt->vm_file = area->vm_file;if (mpnt->vm_file) mpnt->vm_file->f_count++;
@@ -673,8 +673,9 @@* the offsets must be contiguous.. */ if ((mpnt->vm_file !=NULL ) || (mpnt->vm_flags &VM_SHM )) { -unsigned long off = prev->vm_offset+prev->vm_end-prev->vm_start; -if (off != mpnt->vm_offset) +unsigned long off = prev->vm_index + + ((prev->vm_end - prev->vm_start) >>PAGE_SHIFT ); +if (off != mpnt->vm_index)continue ; }
@@ -688,7 +689,7 @@ prev->vm_end = mpnt->vm_end;if (mpnt->vm_ops && mpnt->vm_ops->close) { - mpnt->vm_offset += mpnt->vm_end - mpnt->vm_start; + mpnt->vm_index += (mpnt->vm_end - mpnt->vm_start) >>PAGE_SHIFT ; mpnt->vm_start = mpnt->vm_end; mpnt->vm_ops->close (mpnt); }
mm/mprotect.c +4 -4
@@ -107,7 +107,7 @@ *n = *vma; vma->vm_start = end; n->vm_end = end; - vma->vm_offset += vma->vm_start - n->vm_start; + vma->vm_index += (vma->vm_start - n->vm_start) >>PAGE_SHIFT ; n->vm_flags = newflags; n->vm_page_prot = prot;if (n->vm_file)
@@ -130,7 +130,7 @@ *n = *vma; vma->vm_end = start; n->vm_start = start; - n->vm_offset += n->vm_start - vma->vm_start; + n->vm_index += (n->vm_start - vma->vm_start) >>PAGE_SHIFT ; n->vm_flags = newflags; n->vm_page_prot = prot;if (n->vm_file)
@@ -161,8 +161,8 @@ vma->vm_start = start; vma->vm_end = end; right->vm_start = end; - vma->vm_offset += vma->vm_start - left->vm_start; - right->vm_offset += right->vm_start - left->vm_start; + vma->vm_index += (vma->vm_index - left->vm_start) >>PAGE_SHIFT ; + right->vm_index += (right->vm_start - left->vm_start) >>PAGE_SHIFT ; vma->vm_flags = newflags; vma->vm_page_prot = prot;if (vma->vm_file)
mm/mremap.c +1 -1
@@ -139,7 +139,7 @@ *new_vma = *vma; new_vma->vm_start = new_addr; new_vma->vm_end = new_addr+new_len; - new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start); + new_vma->vm_index = vma->vm_index + ((addr - vma->vm_start) >>PAGE_SHIFT ); new_vma->vm_file = vma->vm_file;if (new_vma->vm_file) new_vma->vm_file->f_count++;
mm/page_io.c +2 -2
@@ -114,7 +114,7 @@printk ("VM: swap page is not in swap cache\n" );return ; } -if (page->offset != entry) { +if (page->key != entry) {printk ("swap entry mismatch" );return ; }
@@ -234,7 +234,7 @@return ; } page->inode = &swapper_inode; - page->offset = entry; + page->key = entry;atomic_inc (&page->count);/* Protect from shrink_mmap() */ rw_swap_page (rw, entry, buffer,1 );atomic_dec (&page->count);
mm/swap_state.c +4 -4
@@ -65,7 +65,7 @@if (PageTestandSetSwapCache (page)) {printk ("swap_cache: replacing non-empty entry %08lx " "on page %08lx\n" , - page->offset,page_address (page)); + page->key,page_address (page));return 0 ; }if (page->inode) {
@@ -75,7 +75,7 @@ }atomic_inc (&page->count); page->inode = &swapper_inode; - page->offset = entry; + page->key = entry;add_page_to_hash_queue (page, &swapper_inode, entry);add_page_to_inode_queue (&swapper_inode, page);#ifdef SWAP_CACHE_INFO
@@ -172,7 +172,7 @@ swap_cache_find_total++;#endif if (PageSwapCache (page)) { -long entry = page->offset; +long entry = page->key;#ifdef SWAP_CACHE_INFO swap_cache_find_success++;#endif
@@ -188,7 +188,7 @@ swap_cache_del_total++;#endif if (PageSwapCache (page)) { -long entry = page->offset; +long entry = page->key;#ifdef SWAP_CACHE_INFO swap_cache_del_success++;#endif
mm/vmscan.c +3 -2
@@ -133,9 +133,10 @@if (pte_dirty (pte)) {if (vma->vm_ops && vma->vm_ops->swapout) { +unsigned long index = ((address - vma->vm_start) >>PAGE_SHIFT ) + vma->vm_index;pid_t pid = tsk->pid; vma->vm_mm->rss--; -if (vma->vm_ops->swapout (vma, address - vma->vm_start + vma->vm_offset, page_table)) +if (vma->vm_ops->swapout (vma, index, page_table))kill_proc (pid,SIGBUS ,1 ); }else {/*
@@ -145,7 +146,7 @@* page with that swap entry. */ if (PageSwapCache (page_map)) { - entry = page_map->offset; + entry = page_map->key; }else { entry =get_swap_page ();if (!entry)