Skip to contentSkip to conversation

cache large files in the page cache

PATCH In review Eric W. Biederman 4 participants 6 messages May 23, 1999 – May 30, 1999

Subsystems (27)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cache large files in the page cache

Linus,
Since Ingo has been working on the page cache as well, I'm stopping
here. Any changes up to this point are straight forward to resolve,
and this patch is the really challenging one to port from kernel to kernel.

Allow large files in the page cache, by sqeezing out the extra bits. This does not export any of this potential to user space, that's a different can of worms.

Details:

This patch replaces vm_offset with vm_index, with the relationship:
vm_offset == (vm_index << PAGE_SHIFT). Except vm_index can hold larger offsets.

This patch makes inode->i_size a loff_t, to allow very large files. So in some places division and multiplcations with inode->i_size have been replaced by shifts.

The inode operation mmap takes an additional argument of loff_t loff and has to fill in vma->vm_index itself. Combined with my vm_store patch you have the ability to mmap absolutely enormous files, or unaligned offsets if you need to.

page->offset has bee replaced with page->key. page->key is an arbitrary value but for the generic code in filemap.c
page->offset == page->key << PAGE_CACHE_SHIFT

I have defined PAGE_MAX_MEMORY_OFFSET & PAGE_MAX_FILE_OFFSET so I can make some sanity checks that things aren't too huge. This may be incomplete.

Added a do_ldiv in lib/vsprintf.c It's kind of a hack but it gets the job done for displaying long longs

Added checks in the stat routines to see if the values we are copying out are too big.

Move PAGE_CACHE_SHIFT & co to asm-xxx/page.h, anywhere else and you can get into awkward head include situations.

filemap.c could possibly be made to reduce the use of loff_t a little more but that is tricky. And note, anything that really requires 64bits to handle it, loff_t is more efficient than using double talk to get around it.

Note: increasing PAGE_CACHE_SIZE really can't increase the amount you can cache. page->key is allows it but vma->vm_index can't so you can't mmap it. PAGE_CACHE_SIZE caught me off balance when it appeared in 2.3.3

Eric

arch/alpha/kernel/ptrace.c +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/alpha/kernel/ptrace.c linux-2.3.3.eb5/arch/alpha/kernel/ptrace.c
@@ -261,7 +261,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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/arm/kernel/ptrace.c linux-2.3.3.eb5/arch/arm/kernel/ptrace.c
@@ -178,7 +178,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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/i386/kernel/ptrace.c linux-2.3.3.eb5/arch/i386/kernel/ptrace.c
@@ -186,7 +186,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/kernel/ptrace.c +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/m68k/kernel/ptrace.c linux-2.3.3.eb5/arch/m68k/kernel/ptrace.c
@@ -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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/mips/kernel/ptrace.c linux-2.3.3.eb5/arch/mips/kernel/ptrace.c
@@ -157,7 +157,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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/ppc/kernel/ptrace.c linux-2.3.3.eb5/arch/ppc/kernel/ptrace.c
@@ -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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/sparc/kernel/ptrace.c linux-2.3.3.eb5/arch/sparc/kernel/ptrace.c
@@ -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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/arch/sparc64/kernel/ptrace.c linux-2.3.3.eb5/arch/sparc64/kernel/ptrace.c
@@ -219,7 +219,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;
 }
drivers/block/loop.c +2 -2
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/drivers/block/loop.c linux-2.3.3.eb5/drivers/block/loop.c
@@ -137,12 +137,12 @@
 	int	size;
 
 	if (S_ISREG(lo->lo_dentry->d_inode->i_mode))
-		size = (lo->lo_dentry->d_inode->i_size - lo->lo_offset) / BLOCK_SIZE;
+		size = (lo->lo_dentry->d_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;
+                                (lo->lo_offset >> BLOCK_SIZE_BITS);
 		else
 			size = MAX_DISK_SIZE;
 	}
drivers/char/ftape/lowlevel/ftape-ctl.c +2 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/drivers/char/ftape/lowlevel/ftape-ctl.c linux-2.3.3.eb5/drivers/char/ftape/lowlevel/ftape-ctl.c
@@ -704,9 +704,11 @@
 	if ((vma_get_flags(vma) & (VM_READ|VM_WRITE)) == 0) {
 		TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access");
 	}
+#if 0
 	if (vma_get_offset (vma) != 0) {
 		TRACE_ABORT(-EINVAL, ft_t_err, "offset must be 0");
 	}
+#endif
 	if ((vma_get_end (vma) - vma_get_start (vma)) % FT_BUFF_SIZE != 0) {
 		TRACE_ABORT(-EINVAL, ft_t_err,
 			    "size = %ld, should be a multiple of %d",
drivers/char/mem.c +11 -4
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/drivers/char/mem.c linux-2.3.3.eb5/drivers/char/mem.c
@@ -183,10 +183,17 @@
 #endif
 }
 
-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;
+	if ((offset + (vma->vm_end - vma->vm_start)) > PAGE_MAX_MEMORY_OFFSET) {
+		return -EINVAL;
+	}
+	vma->vm_index = offset >> PAGE_SHIFT;
 	if (offset & ~PAGE_MASK)
 		return -ENXIO;
 
@@ -410,7 +417,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/sgi/char/graphics.c +12 -3
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/drivers/sgi/char/graphics.c linux-2.3.3.eb5/drivers/sgi/char/graphics.c
@@ -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  */
@@ -252,7 +260,8 @@
 	vma->vm_page_prot = PAGE_USERIO;
 		
 	/* final setup */
-	vma->vm_dentry = dget (file->f_dentry);
+	vma->vm_file = file;
+	file->f_count++;
 	return 0;
 }
 	
drivers/sound/soundcard.c +2 -2
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/drivers/sound/soundcard.c linux-2.3.3.eb5/drivers/sound/soundcard.c
@@ -699,7 +699,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;
@@ -739,7 +739,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;
fs/adfs/inode.c +3 -3
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/adfs/inode.c linux-2.3.3.eb5/fs/adfs/inode.c
@@ -180,8 +180,8 @@
 		inode->i_mode	 = S_IRWXUGO | S_IFDIR;
 		inode->i_nlink	 = 2;
 		inode->i_size	 = ADFS_NEWDIR_SIZE;
-		inode->i_blksize = PAGE_SIZE;
-		inode->i_blocks  = inode->i_size / sb->s_blocksize;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks  = inode->i_size >> sb->s_blocksize_bits;
 		inode->i_mtime   =
 		inode->i_atime   =
 		inode->i_ctime   = 0;
@@ -203,7 +203,7 @@
 		inode->i_mode	 = adfs_atts2mode(sb, ide.mode, ide.filetype);
 		inode->i_nlink	 = 2;
 		inode->i_size    = ide.size;
-		inode->i_blksize = PAGE_SIZE;
+		inode->i_blksize = PAGE_CACHE_SIZE;
 		inode->i_blocks	 = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 		inode->i_mtime	 =
 		inode->i_atime   =
fs/affs/file.c +9 -9
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/affs/file.c linux-2.3.3.eb5/fs/affs/file.c
@@ -618,7 +618,7 @@
 				written = -ENOSPC;
 			break;
 		}
-		c = blocksize - (pos % blocksize);
+		c = blocksize - (pos & (blocksize -1));
 		if (c > count - written)
 			c = count - written;
 		if (c != blocksize && !buffer_uptodate(bh)) {
@@ -631,7 +631,7 @@
 				break;
 			}
 		}
-		p  = (pos % blocksize) + bh->b_data;
+		p  = (pos & (blocksize -1)) + bh->b_data;
 		c -= copy_from_user(p,buf,c);
 		if (!c) {
 			affs_brelse(bh);
@@ -698,7 +698,7 @@
 				written = -ENOSPC;
 			break;
 		}
-		c = blocksize - (pos % blocksize);
+		c = blocksize - (pos & (blocksize -1));
 		if (c > count - written)
 			c = count - written;
 		if (c != blocksize && !buffer_uptodate(bh)) {
@@ -711,7 +711,7 @@
 				break;
 			}
 		}
-		p  = (pos % blocksize) + bh->b_data + 24;
+		p  = (pos & (blocksize -1)) + bh->b_data + 24;
 		c -= copy_from_user(p,buf,c);
 		if (!c) {
 			affs_brelse(bh);
@@ -780,10 +780,10 @@
 	int	 rem;
 	int	 ext;
 
-	pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
+	pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,(unsigned long)inode->i_size);
 
 	net_blocksize = blocksize - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0);
-	first = (inode->i_size + net_blocksize - 1) / net_blocksize;
+	first = (unsigned long)(inode->i_size + net_blocksize - 1) / net_blocksize;
 	if (inode->u.affs_i.i_lastblock < first - 1) {
 		/* There has to be at least one new block to be allocated */
 		if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) {
@@ -795,7 +795,7 @@
 			affs_warning(inode->i_sb,"truncate","Cannot extend file");
 			inode->i_size = net_blocksize * (inode->u.affs_i.i_lastblock + 1);
 		} else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
-			rem = inode->i_size % net_blocksize;
+			rem = ((unsigned long)inode->i_size) & (net_blocksize -1);
 			DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : net_blocksize);
 			affs_fix_checksum(blocksize,bh->b_data,5);
 			mark_buffer_dirty(bh,0);
@@ -862,7 +862,7 @@
 			affs_free_block(inode->i_sb,ekey);
 		ekey = key;
 	}
-	block = ((inode->i_size + net_blocksize - 1) / net_blocksize) - 1;
+	block = (((unsigned long)inode->i_size + net_blocksize - 1) / net_blocksize) - 1;
 	inode->u.affs_i.i_lastblock = block;
 
 	/* If the file is not truncated to a block boundary,
@@ -870,7 +870,7 @@
 	 * so it cannot become accessible again.
 	 */
 
-	rem = inode->i_size % net_blocksize;
+	rem = inode->i_size & (net_blocksize -1);
 	if (rem) {
 		if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) 
 			rem += 24;
fs/affs/inode.c +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/affs/inode.c linux-2.3.3.eb5/fs/affs/inode.c
@@ -146,7 +146,7 @@
 				block = AFFS_I2BSIZE(inode) - 24;
 			else
 				block = AFFS_I2BSIZE(inode);
-			inode->u.affs_i.i_lastblock = ((inode->i_size + block - 1) / block) - 1;
+			inode->u.affs_i.i_lastblock = (((unsigned long)inode->i_size + block - 1) / block) - 1;
 			break;
 		case ST_SOFTLINK:
 			inode->i_mode |= S_IFLNK;
fs/buffer.c +3 -3
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/buffer.c linux-2.3.3.eb5/fs/buffer.c
@@ -1115,7 +1115,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);
 }
@@ -1338,8 +1338,8 @@
 	set_bit(PG_locked, &page->flags);
 	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;
+	i = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
+	block = page->key << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 	p = nr;
 	do {
 		*p = inode->i_op->bmap(inode, block);
fs/coda/file.c +2 -2
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/coda/file.c linux-2.3.3.eb5/fs/coda/file.c
@@ -98,8 +98,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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/exec.c linux-2.3.3.eb5/fs/exec.c
@@ -314,7 +314,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/inode.c +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/ext2/inode.c linux-2.3.3.eb5/fs/ext2/inode.c
@@ -538,7 +538,7 @@
 	inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
 	inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
 	inode->u.ext2_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
-	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
+	inode->i_blksize = PAGE_CACHE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
 	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
 	inode->i_version = ++event;
 	inode->u.ext2_i.i_new_inode = 0;
fs/ext2/truncate.c +2 -2
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/ext2/truncate.c linux-2.3.3.eb5/fs/ext2/truncate.c
@@ -54,8 +54,8 @@
  * there's no need to test for changes during the operation.
  */
 #define DIRECT_BLOCK(inode) \
-	((inode->i_size + inode->i_sb->s_blocksize - 1) / \
-			  inode->i_sb->s_blocksize)
+	((inode->i_size + inode->i_sb->s_blocksize - 1) >> \
+			  inode->i_sb->s_blocksize_bits)
 #define INDIRECT_BLOCK(inode,offset) ((int)DIRECT_BLOCK(inode) - offset)
 #define DINDIRECT_BLOCK(inode,offset) \
 	(INDIRECT_BLOCK(inode,offset) / addr_per_block)
fs/fat/mmap.c +11 -3
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/fat/mmap.c linux-2.3.3.eb5/fs/fat/mmap.c
@@ -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;
@@ -95,16 +95,22 @@
  * 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 loffset)
 {
 	struct inode *inode = file->f_dentry->d_inode;
+	unsigned long offset;
+	/* fat is strictly a 32 bit filesystem */
+	if ((loffset > ((u32) -1)) || ((loffset + (vma->vm_end - vma->vm_start)) > ((u32) -1))) {
+		return -EINVAL;
+	}
+	offset = loffset;
 	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 +118,8 @@
 		inode->i_atime = CURRENT_TIME;
 		mark_inode_dirty(inode);
 	}
+
+	vma->vm_index = offset >> PAGE_SHIFT;
 
 	vma->vm_ops = &fat_file_mmap;
 	return 0;
fs/isofs/inode.c +2 -2
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/isofs/inode.c linux-2.3.3.eb5/fs/isofs/inode.c
@@ -912,7 +912,7 @@
 	    if( b_off >= max_legal_read_offset )
 	      {
 
-		printk("_isofs_bmap: block>= EOF(%d, %ld)\n", block,
+		printk("_isofs_bmap: block>= EOF(%d, %Ld)\n", block,
 		       inode->i_size);
 	      }
 	    return 0;
@@ -1152,7 +1152,7 @@
 #endif
 
 #ifdef DEBUG
-	printk("Get inode %x: %d %d: %d\n",inode->i_ino, block,
+	printk("Get inode %x: %d %d: %Ld\n",inode->i_ino, block,
 	       ((int)pnt) & 0x3ff, inode->i_size);
 #endif
 
fs/ncpfs/mmap.c +20 -6
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/ncpfs/mmap.c linux-2.3.3.eb5/fs/ncpfs/mmap.c
@@ -46,10 +46,10 @@
 	if (!page)
 		return page;
 	address &= PAGE_MASK;
-	pos = address - area->vm_start + area->vm_offset;
+	pos = (address - area->vm_start) + (area->vm_index << PAGE_SHFT);
 
-	count = PAGE_SIZE;
-	if (address + PAGE_SIZE > area->vm_end) {
+	count = PAGE_CACHE_SIZE;
+	if (address + PAGE_CACHE_SIZE > area->vm_end) {
 		count = area->vm_end - address;
 	}
 	/* what we can read in one go */
@@ -82,9 +82,9 @@
 
 	}
 
-	if (already_read < PAGE_SIZE)
+	if (already_read < PAGE_CACHE_SIZE)
 		memset((char*)(page + already_read), 0, 
-		       PAGE_SIZE - already_read);
+		       PAGE_CACHE_SIZE - already_read);
 	return page;
 }
 
@@ -104,15 +104,28 @@
 
 
 /* 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 loffset)
 {
 	struct inode *inode = file->f_dentry->d_inode;
+	unsigned long offset;
+	
+	/* ncp is stricty a 32 bit filesystem */
+	if ((loffset > ((u32) -1)) || ((loffset + (vma->vm_end - vma->vm_start)) > ((u32) -1))) {
+		return -EINVAL;
+	}
+	offset = loffset;
 	
 	DPRINTK(KERN_DEBUG "ncp_mmap: called\n");
 
 	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)
 		return -EINVAL;
@@ -122,6 +135,7 @@
 		inode->i_atime = CURRENT_TIME;
 	}
 
+	vma->vm_index = offset >> PAGE_SHIFT;
 	vma->vm_ops = &ncp_file_mmap;
 	return 0;
 }
fs/nfs/read.c +8 -8
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/nfs/read.c linux-2.3.3.eb5/fs/nfs/read.c
@@ -69,11 +69,11 @@
 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_CACHE_SHIFT;
 	char		*buffer = (char *) page_address(page);
 	int		rsize = NFS_SERVER(inode)->rsize;
 	int		result, refresh = 0;
-	int		count = PAGE_SIZE;
+	int		count = PAGE_CACHE_SIZE;
 	int		flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0;
 
 	dprintk("NFS: nfs_readpage_sync(%p)\n", page);
@@ -142,8 +142,8 @@
 
 	if (result >= 0) {
 		result = req->ra_res.count;
-		if (result < PAGE_SIZE) {
-			memset((char *) address + result, 0, PAGE_SIZE - result);
+		if (result < PAGE_CACHE_SIZE) {
+			memset((char *) address + result, 0, PAGE_CACHE_SIZE - result);
 		}
 		nfs_refresh_inode(req->ra_inode, &req->ra_fattr);
 		set_bit(PG_uptodate, &page->flags);
@@ -183,8 +183,8 @@
 
 	/* Initialize request */
 	/* N.B. Will the dentry remain valid for life of request? */
-	nfs_readreq_setup(req, NFS_FH(dentry), page->offset,
-				(void *) address, PAGE_SIZE);
+	nfs_readreq_setup(req, NFS_FH(dentry), page->key << PAGE_CACHE_SHIFT,
+				(void *) address, PAGE_CACHE_SIZE);
 	req->ra_inode = inode;
 	req->ra_page = page; /* count has been incremented by caller */
 
@@ -228,7 +228,7 @@
 	int		error;
 
 	dprintk("NFS: nfs_readpage (%p %ld@%ld)\n",
-		page, PAGE_SIZE, page->offset);
+		page, PAGE_CACHE_SIZE, page->key << PAGE_CACHE_SHIFT);
 	atomic_inc(&page->count);
 	set_bit(PG_locked, &page->flags);
 
@@ -245,7 +245,7 @@
 
 	error = -1;
 	if (!IS_SWAPFILE(inode) && !PageError(page) &&
-	    NFS_SERVER(inode)->rsize >= PAGE_SIZE)
+	    NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE)
 		error = nfs_readpage_async(dentry, inode, page);
 	if (error >= 0)
 		goto out;
fs/nfs/write.c +8 -8
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/nfs/write.c linux-2.3.3.eb5/fs/nfs/write.c
@@ -95,10 +95,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_CACHE_SHIFT) + offset);
 
 	buffer = (u8 *) page_address(page) + offset;
-	offset += page->offset;
+	offset += page->key << PAGE_CACHE_SHIFT;
 
 	do {
 		if (count < wsize && !IS_SWAPFILE(inode))
@@ -271,7 +271,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_CACHE_SHIFT) + offset, bytes);
 
 	/* FIXME: Enforce hard limit on number of concurrent writes? */
 	wreq = (struct nfs_wreq *) kmalloc(sizeof(*wreq), GFP_KERNEL);
@@ -398,7 +398,7 @@
 nfs_writepage(struct file * file, struct page *page)
 {
 	struct dentry *dentry = file->f_dentry;
-	return nfs_writepage_sync(dentry, dentry->d_inode, page, 0, PAGE_SIZE);
+	return nfs_writepage_sync(dentry, dentry->d_inode, page, 0, PAGE_CACHE_SIZE);
 }
 
 /*
@@ -418,7 +418,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_CACHE_SHIFT)+offset, sync);
 
 	/*
 	 * Try to find a corresponding request on the writeback queue.
@@ -438,7 +438,7 @@
 	 * If wsize is smaller than page size, update and write
 	 * page synchronously.
 	 */
-	if (NFS_SERVER(inode)->wsize < PAGE_SIZE)
+	if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE)
 		return nfs_writepage_sync(dentry, inode, page, offset, count);
 
 	/* Create the write request. */
@@ -457,7 +457,7 @@
 	synchronous = schedule_write_request(req, sync);
 
 updated:
-	if (req->wb_bytes == PAGE_SIZE)
+	if (req->wb_bytes == PAGE_CACHE_SIZE)
 		set_bit(PG_uptodate, &page->flags);
 
 	retval = count;
@@ -604,7 +604,7 @@
 	/* Setup the task struct for a writeback call */
 	req->wb_flags |= NFS_WRITE_INPROGRESS;
 	req->wb_args.fh     = NFS_FH(dentry);
-	req->wb_args.offset = page->offset + req->wb_offset;
+	req->wb_args.offset = (page->key << PAGE_CACHE_SHIFT) + req->wb_offset;
 	req->wb_args.count  = req->wb_bytes;
 	req->wb_args.buffer = (void *) (page_address(page) + req->wb_offset);
 
fs/open.c +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/open.c linux-2.3.3.eb5/fs/open.c
@@ -63,7 +63,7 @@
 	return error;
 }
 
-int do_truncate(struct dentry *dentry, unsigned long length)
+int do_truncate(struct dentry *dentry, loff_t length)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
fs/proc/array.c +4 -3
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/proc/array.c linux-2.3.3.eb5/fs/proc/array.c
@@ -1075,8 +1075,8 @@
  *         + (index into the line)
  */
 /* for systems with sizeof(void*) == 4: */
-#define MAPS_LINE_FORMAT4	  "%08lx-%08lx %s %08lx %s %lu"
-#define MAPS_LINE_MAX4	49 /* sum of 8  1  8  1 4 1 8 1 5 1 10 1 */
+#define MAPS_LINE_FORMAT4	  "%08lx-%08lx %s %016Lx %s %lu"
+#define MAPS_LINE_MAX4	57 /* sum of 8  1  8  1 4 1 16 1 5 1 10 1 */
 
 /* for systems with sizeof(void*) == 8: */
 #define MAPS_LINE_FORMAT8	  "%016lx-%016lx %s %016lx %s %lu"
@@ -1163,7 +1163,8 @@
 
 		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, 
+			      (((loff_t)map->vm_index) << PAGE_SHIFT),
 			      kdevname(dev), ino);
 
 		if(map->vm_file) {
fs/proc/mem.c +12 -4
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/proc/mem.c linux-2.3.3.eb5/fs/proc/mem.c
@@ -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, mapnr;
 	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,16 @@
 	 moment because working out the vm_area_struct & nattach stuff isn't
 	 worth it. */
 
+	if ((offset > PAGE_MAX_MEMORY_OFFSET) || 
+	    ((offset + (vma->vm_end - vma->vm_start)) > 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 +275,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 +5 -5
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/romfs/inode.c linux-2.3.3.eb5/fs/romfs/inode.c
@@ -395,13 +395,13 @@
 	buf = page_address(page);
 	clear_bit(PG_uptodate, &page->flags);
 	clear_bit(PG_error, &page->flags);
-	offset = page->offset;
+	offset = page->key << PAGE_CACHE_SHIFT;
 	if (offset < inode->i_size) {
 		avail = inode->i_size-offset;
-		readlen = min(avail, PAGE_SIZE);
+		readlen = min(avail, PAGE_CACHE_SIZE);
 		if (romfs_copyfrom(inode, (void *)buf, inode->u.romfs_i.i_dataoffset+offset, readlen) == readlen) {
-			if (readlen < PAGE_SIZE) {
-				memset((void *)(buf+readlen),0,PAGE_SIZE-readlen);
+			if (readlen < PAGE_CACHE_SIZE) {
+				memset((void *)(buf+readlen),0,PAGE_CACHE_SIZE-readlen);
 			}
 			set_bit(PG_uptodate, &page->flags);
 			result = 0;
@@ -409,7 +409,7 @@
 	}
 	if (result) {
 		set_bit(PG_error, &page->flags);
-		memset((void *)buf, 0, PAGE_SIZE);
+		memset((void *)buf, 0, PAGE_CACHE_SIZE);
 	}
 
 	clear_bit(PG_locked, &page->flags);
fs/smbfs/file.c +5 -5
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/fs/smbfs/file.c linux-2.3.3.eb5/fs/smbfs/file.c
@@ -55,9 +55,9 @@
 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_CACHE_SHIFT;
 	int rsize = smb_get_rsize(server_from_dentry(dentry));
-	int count = PAGE_SIZE;
+	int count = PAGE_CACHE_SIZE;
 	int result;
 
 	clear_bit(PG_error, &page->flags);
@@ -132,7 +132,7 @@
 	int wsize = smb_get_wsize(server_from_dentry(dentry));
 	int result, written = 0;
 
-	offset += page->offset;
+	offset += page->key << PAGE_CACHE_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);
@@ -181,7 +181,7 @@
 #endif
 	set_bit(PG_locked, &page->flags);
 	atomic_inc(&page->count);
-	result = smb_writepage_sync(dentry, page, 0, PAGE_SIZE);
+	result = smb_writepage_sync(dentry, page, 0, PAGE_CACHE_SIZE);
 	smb_unlock_page(page);
 	free_page(page_address(page));
 	return result;
@@ -194,7 +194,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_CACHE_SHIFT)+offset, sync);
 
 	return smb_writepage_sync(dentry, page, offset, count);
 }
fs/stat.c +38 -26

89 lines not on this page · raw message

include/asm-alpha/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-alpha/page.h linux-2.3.3.eb5/include/asm-alpha/page.h
@@ -10,6 +10,10 @@
 
 #ifndef __ASSEMBLY__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 #define STRICT_MM_TYPECHECKS
 
 /*
include/asm-arm/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-arm/page.h linux-2.3.3.eb5/include/asm-arm/page.h
@@ -6,6 +6,10 @@
 
 #ifdef __KERNEL__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
 #define free_user_page(page, addr)	free_page(addr)
 #define clear_page(page)		memzero((void *)(page), PAGE_SIZE)
include/asm-i386/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-i386/page.h linux-2.3.3.eb5/include/asm-i386/page.h
@@ -9,6 +9,10 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 #define STRICT_MM_TYPECHECKS
 
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
include/asm-m68k/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-m68k/page.h linux-2.3.3.eb5/include/asm-m68k/page.h
@@ -10,6 +10,10 @@
 
 #ifdef __KERNEL__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 #include <asm/setup.h>
 
 #define STRICT_MM_TYPECHECKS
include/asm-mips/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-mips/page.h linux-2.3.3.eb5/include/asm-mips/page.h
@@ -17,6 +17,10 @@
 
 #ifdef __KERNEL__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 #define STRICT_MM_TYPECHECKS
 
 #ifndef __LANGUAGE_ASSEMBLY__
include/asm-ppc/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-ppc/page.h linux-2.3.3.eb5/include/asm-ppc/page.h
@@ -14,6 +14,10 @@
 #ifndef __ASSEMBLY__
 #ifdef __KERNEL__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 #define STRICT_MM_TYPECHECKS
 
 #ifdef STRICT_MM_TYPECHECKS
include/asm-sparc/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-sparc/page.h linux-2.3.3.eb5/include/asm-sparc/page.h
@@ -28,6 +28,10 @@
 
 #ifndef __ASSEMBLY__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 #define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
 
include/asm-sparc64/page.h +4 -0
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/asm-sparc64/page.h linux-2.3.3.eb5/include/asm-sparc64/page.h
@@ -18,6 +18,10 @@
 
 #ifndef __ASSEMBLY__
 
+#define PAGE_CACHE_SHIFT	PAGE_SHIFT
+#define PAGE_CACHE_SIZE		(1UL << PAGE_CACHE_SHIFT)
+#define PAGE_CACHE_MASK		(~(PAGE_CACHE_SIZE-1))
+
 extern void clear_page(unsigned long page);
 extern void copy_page(unsigned long to, unsigned long from);
 
include/linux/fs.h +7 -7
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/linux/fs.h linux-2.3.3.eb5/include/linux/fs.h
@@ -314,7 +314,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;
@@ -349,7 +349,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;
@@ -466,8 +466,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 */
 
@@ -594,7 +594,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 (*flush) (struct file *);
 	int (*release) (struct inode *, struct file *);
@@ -702,7 +702,7 @@
 
 asmlinkage int sys_open(const char *, int, int);
 asmlinkage int sys_close(unsigned int);		/* yes, it's really unsigned */
-extern int do_truncate(struct dentry *, unsigned long);
+extern int do_truncate(struct dentry *, loff_t);
 extern int get_unused_fd(void);
 extern void put_unused_fd(unsigned int);
 
@@ -875,7 +875,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 -11
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/linux/mm.h linux-2.3.3.eb5/include/linux/mm.h
@@ -54,7 +54,11 @@
 	struct vm_area_struct **vm_pprev_share;
 
 	struct vm_operations_struct * vm_ops;
-	unsigned long vm_offset;
+	unsigned long vm_index;
+	/* The old vm_offset value is logically
+	 * (vm_index << PAGE_SHIFT) 
+	 * except the value is potentially too large for the old vm_offset field.
+	 */
 	struct file * vm_file;
 	unsigned long vm_pte;			/* shared mem */
 };
@@ -105,6 +109,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 *, struct page *);
 	pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
 };
@@ -122,7 +127,7 @@
 	struct page *next;
 	struct page *prev;
 	struct inode *inode;
-	unsigned long offset;
+	unsigned long key;
 	struct page *next_hash;
 	atomic_t count;
 	unsigned long flags;	/* atomic flags, some possibly updated asynchronously */
@@ -210,8 +215,8 @@
  * The following discussion applies only to them.
  *
  * A page may belong to an inode's memory mapping. In this case,
- * page->inode is the pointer to the inode, and page->offset is the
- * file offset of the page (not necessarily a multiple of PAGE_SIZE).
+ * page->inode is the pointer to the inode, and page->key is the
+ * offset into the file (divided by PAGE_CACHE_SIZE).
  *
  * A page may have buffers allocated to it. In this case,
  * PageBuffer(page) is true and page->generic_pp is a circular list of
@@ -223,7 +228,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->pprev_hash.
  *
@@ -244,7 +249,7 @@
  *
  * For choosing which pages to swap out, inode pages carry a
  * PG_referenced bit, which is set any time the system accesses
- * that page through the (inode,offset) hash table.
+ * that page through the (inode,index) hash table.
  *
  * PG_skip is used on sparc/sparc64 architectures to "skip" certain
  * parts of the address space.
@@ -294,7 +299,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 int handle_mm_fault(struct task_struct *tsk,struct vm_area_struct *vma, unsigned long address, int write_access);
 extern void make_pages_present(unsigned long addr, unsigned long end);
 
@@ -316,14 +321,14 @@
 extern unsigned long get_unmapped_area(unsigned long, unsigned long);
 
 extern unsigned long do_mmap(struct file *, unsigned long, unsigned long,
-	unsigned long, unsigned long, unsigned long);
+	unsigned long, unsigned long, loff_t);
 extern int do_munmap(unsigned long, size_t);
 
 /* filemap.c */
 extern void remove_inode_page(struct page *);
 extern unsigned long page_unuse(struct page *);
 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);
 
@@ -365,8 +370,8 @@
 	    > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur)
 		return -ENOMEM;
 	vma->vm_start = address;
-	vma->vm_offset -= grow;
-	vma->vm_mm->total_vm += grow >> PAGE_SHIFT;
+	vma->vm_index -= grow >> PAGE_SHIFT;
+	vma->vm_mm->total_vm += grow;
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow >> PAGE_SHIFT;
 	return 0;
@@ -385,6 +390,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))
 
 #define buffer_under_min()	((buffermem >> PAGE_SHIFT) * 100 < \
 				buffer_mem.min_percent * num_physpages)
include/linux/pagemap.h +14 -12
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/linux/pagemap.h linux-2.3.3.eb5/include/linux/pagemap.h
@@ -24,10 +24,13 @@
  * space in smaller chunks for same flexibility).
  *
  * Or rather, it _will_ be done in larger chunks.
- */
+ *
+ * To start with:
 #define PAGE_CACHE_SHIFT	PAGE_SHIFT
 #define PAGE_CACHE_SIZE		PAGE_SIZE
 #define PAGE_CACHE_MASK		PAGE_MASK
+ */
+
 
 #define page_cache_alloc()	__get_free_page(GFP_USER)
 #define page_cache_free(x)	free_page(x)
@@ -50,10 +53,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
@@ -61,9 +64,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 (;;) {
@@ -73,7 +76,7 @@
 			goto not_found;
 		if (page->inode != inode)
 			continue;
-		if (page->offset == offset)
+		if (page->key == key)
 			break;
 	}
 	/* Found the page. */
@@ -82,10 +85,9 @@
 not_found:
 	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)
@@ -108,9 +110,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)
@@ -148,6 +150,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 +2 -2
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/linux/swap.h linux-2.3.3.eb5/include/linux/swap.h
@@ -162,7 +162,7 @@
 extern inline unsigned long in_swap_cache(struct page *page)
 {
 	if (PageSwapCache(page))
-		return page->offset;
+		return page->key;
 	return 0;
 }
 
@@ -179,7 +179,7 @@
 		return 1;
 	count = atomic_read(&page->count);
 	if (PageSwapCache(page))
-		count += swap_count(page->offset) - 2;
+		count += swap_count(page->key) - 2;
 	if (PageFreeAfter(page))
 		count--;
 	return  count > 1;
include/linux/wrapper.h +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/include/linux/wrapper.h linux-2.3.3.eb5/include/linux/wrapper.h
@@ -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 +5 -4
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/ipc/shm.c linux-2.3.3.eb5/ipc/shm.c
@@ -363,7 +363,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
  */
 
@@ -513,7 +513,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->u.shm_nattch++;            /* prevent destruction */
@@ -589,7 +589,8 @@
 	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();
@@ -620,7 +621,7 @@
 	unsigned int id, idx;
 
 	id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK;
-	idx = (address - shmd->vm_start + shmd->vm_offset) >> PAGE_SHIFT;
+	idx = ((address - shmd->vm_start) >> PAGE_SHIFT) + shmd->vm_index;
 
 #ifdef DEBUG_SHM
 	if (id > max_shmid) {
lib/vsprintf.c +105 -0

117 lines not on this page · raw message

mm/filemap.c +148 -99

636 lines not on this page · raw message

mm/memory.c +17 -9
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/memory.c linux-2.3.3.eb5/mm/memory.c
@@ -647,7 +647,7 @@
 	case 2:
 		if (!PageSwapCache(page_map))
 			break;
-		if (swap_count(page_map->offset) != 1)
+		if (swap_count(page_map->key) != 1)
 			break;
 		delete_from_swap_cache(page_map);
 		/* FallThrough */
@@ -733,13 +733,19 @@
  * 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, trunk_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_CACHE_SHIFT;
+	partial = offset & PAGE_CACHE_MASK;
+	trunk_index = index + (partial)? 1 : 0;
 	mpnt = inode->i_mmap;
 	do {
 		struct mm_struct *mm = mpnt->vm_mm;
@@ -749,22 +755,22 @@
 		unsigned long diff;
 
 		/* mapping wholly truncated? */
-		if (mpnt->vm_offset >= offset) {
+		if ((mpnt->vm_index >> (PAGE_CACHE_SHIFT - PAGE_SHIFT)) >= trunk_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 << PAGE_CACHE_SHIFT) - (mpnt->vm_index << PAGE_SHIFT)) + partial;
 		if (diff >= len)
 			continue;
 		/* Ok, partially affected.. */
 		start += diff;
-		len = (len - diff) & PAGE_MASK;
-		if (start & ~PAGE_MASK) {
+		len = (len - diff) & PAGE_CACHE_MASK;
+		if (start & ~PAGE_CACHE_MASK) {
 			partial_clear(mpnt, start);
-			start = (start + ~PAGE_MASK) & PAGE_MASK;
+			start = (start + ~PAGE_CACHE_MASK) & PAGE_CACHE_MASK;
 		}
 		flush_cache_range(mm, start, end);
 		zap_page_range(mm, start, len);
@@ -785,7 +791,9 @@
 		swap_in(tsk, vma, page_table, pte_val(entry), write_access);
 		flush_page_to_ram(pte_page(*page_table));
 	} else {
-		pte_t page = vma->vm_ops->swapin(vma, address - vma->vm_start + vma->vm_offset, pte_val(entry));
+		unsigned long index = ((address - vma->vm_start) >> PAGE_SHIFT)	
+			+ vma->vm_index;
+		pte_t page = vma->vm_ops->swapin(vma, index, pte_val(entry));
 		if (pte_val(*page_table) != pte_val(entry)) {
 			free_page(pte_page(page));
 		} else {
mm/mlock.c +4 -6
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/mlock.c linux-2.3.3.eb5/mm/mlock.c
@@ -28,7 +28,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++;
@@ -42,14 +42,13 @@
 	unsigned long start, int newflags)
 {
 	struct vm_area_struct * n;
-
 	n = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!n)
 		return -EAGAIN;
 	*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++;
@@ -63,7 +62,6 @@
 	unsigned long start, unsigned long end, int newflags)
 {
 	struct vm_area_struct * left, * right;
-
 	left = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!left)
 		return -EAGAIN;
@@ -78,8 +76,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
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/mmap.c linux-2.3.3.eb5/mm/mmap.c
@@ -170,7 +170,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;
@@ -278,7 +278,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;
 
@@ -313,7 +313,7 @@
 			file->f_dentry->d_inode->i_writecount--;
 			correct_wcount = 1;
 		}
-		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 */
 		if (correct_wcount)
 			file->f_dentry->d_inode->i_writecount++;
@@ -514,7 +514,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 */
@@ -528,7 +528,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;
 		mpnt->vm_pte = area->vm_pte;
 		if (mpnt->vm_file)
@@ -830,8 +830,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;
 		}
 
@@ -844,7 +845,7 @@
 		prev->vm_end = mpnt->vm_end;
 		prev->vm_next = mpnt->vm_next;
 		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 +5 -4
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/mprotect.c linux-2.3.3.eb5/mm/mprotect.c
@@ -99,7 +99,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)
@@ -122,7 +122,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)
@@ -138,6 +138,7 @@
 	int newflags, pgprot_t prot)
 {
 	struct vm_area_struct * left, * right;
+	unsigned long shift;
 
 	left = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!left)
@@ -153,8 +154,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;
 	vma->vm_page_prot = prot;
 	if (vma->vm_file)
mm/mremap.c +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/mremap.c linux-2.3.3.eb5/mm/mremap.c
@@ -133,7 +133,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);
 			if (new_vma->vm_file)
 				new_vma->vm_file->f_count++;
 			if (new_vma->vm_ops && new_vma->vm_ops->open)
mm/page_io.c +3 -3
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/page_io.c linux-2.3.3.eb5/mm/page_io.c
@@ -99,7 +99,7 @@
 		 * as if it were: we are not allowed to manipulate the inode
 		 * hashing for locked pages.
 		 */
-		if (page->offset != entry) {
+		if (page->key != entry) {
 			printk ("swap entry mismatch");
 			return;
 		}
@@ -252,7 +252,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;
 	}
@@ -279,7 +279,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 +3 -3
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/swap_state.c linux-2.3.3.eb5/mm/swap_state.c
@@ -54,7 +54,7 @@
 	if (PageTestandSetSwapCache(page)) {
 		printk(KERN_ERR "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) {
@@ -64,7 +64,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);
 	return 1;
@@ -203,7 +203,7 @@
  */
 void delete_from_swap_cache(struct page *page)
 {
-	long entry = page->offset;
+	long entry = page->key;
 
 #ifdef SWAP_CACHE_INFO
 	swap_cache_del_total++;
mm/vmscan.c +1 -1
diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/mm/vmscan.c linux-2.3.3.eb5/mm/vmscan.c
@@ -71,7 +71,7 @@
 	 * memory, and we should just continue our scan.
 	 */
 	if (PageSwapCache(page_map)) {
-		entry = page_map->offset;
+		entry = page_map->key;
 		swap_duplicate(entry);
 		set_pte(page_table, __pte(entry));
 drop_pte:

--
To unsubscribe, send a message with 'unsubscribe linux-mm my@address' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#1 lore raw
Quoted 27 lines · Eric W. Biederman

diff -uNrX /home/eric/projects/linux/linux-ignore-files linux-2.3.3.eb4/drivers/sgi/char/graphics.c linux-2.3.3.eb5/drivers/sgi/char/graphics.c

drivers/sgi/char/graphics.c +0 -0
@@ -237,12 +237,20 @@
 };
 

int

drivers/sgi/char/graphics.c +2 -1
-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;
drivers/sgi/char/graphics.c +7 -0
+	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;
drivers/sgi/char/graphics.c +1 -1
-	if (vma->vm_offset & ~PAGE_MASK)
+	if (vm_offset & ~PAGE_MASK)
		return -ENXIO;

	/* 1. Set our special graphic virtualizer  */

drivers/sgi/char/graphics.c line 265

Quoted 7 lines
drivers/sgi/char/graphics.c +2 -1
@@ -252,7 +260,8 @@
 	vma->vm_page_prot = PAGE_USERIO;
 
 	/* final setup */
-	vma->vm_dentry = dget (file->f_dentry);
+	vma->vm_file = file;
+	file->f_count++;
 	return 0;

vm_file a and f_count should be just handled by do_mmap().

drivers/sgi/char/graphics.c line 374

Quoted 8 lines
drivers/sgi/char/graphics.c +2 -2
@@ -365,8 +370,8 @@
 	    > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur)
 		return -ENOMEM;
 	vma->vm_start = address;
-	vma->vm_offset -= grow;
-	vma->vm_mm->total_vm += grow >> PAGE_SHIFT;
+	vma->vm_index -= grow >> PAGE_SHIFT;
+	vma->vm_mm->total_vm += grow;
				^^^^

grow should still be shifted right of PAGE_SHIFT I think.

I have not understood why PAGE_MAX_MEMORY_OFFSET & PAGE_MAX_FILE_OFFSET are useful. We should check against too large offset or too high mmap in the standard code, no? Maybe the offset limit is to forbid somebody to create a too much large file even if the fs would permit? I am not sure if it will be useful, at least if it's choosen at compile time and it's not a sysctl.

Andrea Arcangeli

--
To unsubscribe, send a message with 'unsubscribe linux-mm my@address' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#2 lore raw
In reply to Eric W. Biederman
Quoted 5 lines

Details:

This patch replaces vm_offset with vm_index, with the relationship:
vm_offset == (vm_index << PAGE_SHIFT). Except vm_index can hold larger offsets.

I have minor suggestion to the patch. Instead of using vm_index << PAGE_SHIFT and page->key << PAGE_CACHE_SHIFT shifts either choose different constant names for this shifting (VM_INDEX_SHIFT and PAGE_KEY_SHIFT) or hide these shifts by some pretty macros (you'll need two for each for both directions in that case - if you go the macro way, maybe it would be a good idea to make vm_index and key type some structure with a single member like mm_segment_t for more strict typechecking). This would have the advantage of avoiding shifting on 64bit archs, where it really is not necessary as no filesystem will support 16000EB filesizes in the near future. I know shifts are not expensive, on the other side count how many there will be and IMHO it should be considered. It could make the code more readable at the same time. VM_INDEX_SHIFT would be defined to 0 on alpha,sparc64 (merced,mips64,ppc64) and PAGE_SHIFT on other platforms. The same with PAGE_KEY_SHIFT.

Cheers,
Jakub
___________________________________________________________________
Jakub Jelinek | [email protected] | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux | http://ultra.linux.cz/ | http://ultra.penguin.cz/
Linux version 2.3.3 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________
--
To unsubscribe, send a message with 'unsubscribe linux-mm my@address' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#3 lore raw
Quoted 8 lines · Jakub Jelinek

I have minor suggestion to the patch. Instead of using vm_index << PAGE_SHIFT and page->key << PAGE_CACHE_SHIFT shifts either choose different constant names for this shifting (VM_INDEX_SHIFT and PAGE_KEY_SHIFT) or hide these shifts by some pretty macros (you'll need two for each for both directions in that case - if you go the macro way, maybe it would be a good idea to make vm_index and key type some structure with a single member like mm_segment_t for more strict typechecking).

Indeed. An dI would suggest that the shift be limited to at most 9 anyway:
right now I applied the part that disallows non-page-aligned offsets, but I think that we may in the future allow anonymous mappings again at finer granularity (somebody made a really good argument about wine for this).

Thinking that the VM mapping shift has to be the same as the page shift is not necessarily the right thing. With just 9 bits of shift, you still get large files - 41 bits of files on a 32-bit architecture, and by the time you want more you _really_ can say that you had better upgrade your CPU.

Linus

--
To unsubscribe, send a message with 'unsubscribe linux-mm my@address' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#4 lore raw
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"LT" == Linus Torvalds <[email protected]> writes:

Quoted 8 lines · Jakub Jelinek
Quoted 8 lines

I have minor suggestion to the patch. Instead of using vm_index << PAGE_SHIFT and page->key << PAGE_CACHE_SHIFT shifts either choose different constant names for this shifting (VM_INDEX_SHIFT and PAGE_KEY_SHIFT) or hide these shifts by some pretty macros (you'll need two for each for both directions in that case - if you go the macro way, maybe it would be a good idea to make vm_index and key type some structure with a single member like mm_segment_t for more strict typechecking).

LT> Indeed. An dI would suggest that the shift be limited to at most 9 anyway:
LT> right now I applied the part that disallows non-page-aligned offsets, but LT> I think that we may in the future allow anonymous mappings again at finer LT> granularity (somebody made a really good argument about wine for this).

I'd love to hear the argument. Something that would negate the disadvantage
of ntuple buffering, and the need for reverse page maps, and isn't portable.

LT> Thinking that the VM mapping shift has to be the same as the page shift is LT> not necessarily the right thing. With just 9 bits of shift, you still get LT> large files - 41 bits of files on a 32-bit architecture, and by the time LT> you want more you _really_ can say that you had better upgrade your CPU.

Well, currectly supporting non-aligned mappings needs more than just a few extra bits. The code to update all mappings on write, and the ability to ensure that a given byte is only faulted in for a single
offset at a time. (Admittedly if everything is a read mapping you
can be a smidge more lax).

My solution to the issue of potentials was the idea of the vm_store. The idea of using something besides struct inode for the page cache. For unaligned mappings or really huge files you could have multiple vm_store's per inode, (plus the code to keep them in sync).

And it shouldn't incur a noticeable performance penalty as it is in an outer loop.

To date all I've implemented is the existence of such a structure. And the seperation of what is the page cache from all the other junk in filemap.c

My current patch follows seperately for review.

Eric
--
To unsubscribe, send a message with 'unsubscribe linux-mm my@address' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

#5 lore raw
Quoted 8 lines · Eric W. Biederman

LT> Indeed. An dI would suggest that the shift be limited to at most 9 anyway:
LT> right now I applied the part that disallows non-page-aligned offsets, but LT> I think that we may in the future allow anonymous mappings again at finer LT> granularity (somebody made a really good argument about wine for this).

I'd love to hear the argument. Something that would negate the disadvantage
of ntuple buffering, and the need for reverse page maps, and isn't portable.

Wine.

Mapping windows binaries in a Linux address space.

Portability is a non-issue: this would only work on a 386, and only on Linux anyway (MAYBE on other architectures Wine supports, but that's their problem).

Windows binaries are _not_ nicely aligned like the Linux ones. They are often 512-byte aligned.

Yes, we can read them in. That is slow as hell, and doesn't allow sharing. Bad.

Quoted 5 lines

Well, currectly supporting non-aligned mappings needs more than just a few extra bits. The code to update all mappings on write, and the ability to ensure that a given byte is only faulted in for a single
offset at a time. (Admittedly if everything is a read mapping you
can be a smidge more lax).

We would not guarantee write coherency for anything but the page-aligned case.

Linus

--
To unsubscribe, send a message with 'unsubscribe linux-mm my@address' in the body to [email protected]. For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/