[PATCH] xip: ext2: execute in place

These are the ext2 related parts. Ext2 now uses the xip_* file operations
along with the get_xip_page aop when mounted with -o xip.

Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Carsten Otte and committed by Linus Torvalds 6d79125b ceffc078

+223 -20
+17
fs/Kconfig
··· 50 50 If you are not using a security module that requires using 51 51 extended attributes for file security labels, say N. 52 52 53 + config EXT2_FS_XIP 54 + bool "Ext2 execute in place support" 55 + depends on EXT2_FS 56 + help 57 + Execute in place can be used on memory-backed block devices. If you 58 + enable this option, you can select to mount block devices which are 59 + capable of this feature without using the page cache. 60 + 61 + If you do not use a block device that is capable of using this, 62 + or if unsure, say N. 63 + 64 + config FS_XIP 65 + # execute in place 66 + bool 67 + depends on EXT2_FS_XIP 68 + default y 69 + 53 70 config EXT3_FS 54 71 tristate "Ext3 journalling file system support" 55 72 help
+1
fs/ext2/Makefile
··· 10 10 ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o 11 11 ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o 12 12 ext2-$(CONFIG_EXT2_FS_SECURITY) += xattr_security.o 13 + ext2-$(CONFIG_EXT2_FS_XIP) += xip.o
+2
fs/ext2/ext2.h
··· 147 147 /* file.c */ 148 148 extern struct inode_operations ext2_file_inode_operations; 149 149 extern struct file_operations ext2_file_operations; 150 + extern struct file_operations ext2_xip_file_operations; 150 151 151 152 /* inode.c */ 152 153 extern struct address_space_operations ext2_aops; 154 + extern struct address_space_operations ext2_aops_xip; 153 155 extern struct address_space_operations ext2_nobh_aops; 154 156 155 157 /* namei.c */
+18
fs/ext2/file.c
··· 55 55 .sendfile = generic_file_sendfile, 56 56 }; 57 57 58 + #ifdef CONFIG_EXT2_FS_XIP 59 + struct file_operations ext2_xip_file_operations = { 60 + .llseek = generic_file_llseek, 61 + .read = do_sync_read, 62 + .write = do_sync_write, 63 + .aio_read = xip_file_aio_read, 64 + .aio_write = xip_file_aio_write, 65 + .ioctl = ext2_ioctl, 66 + .mmap = xip_file_mmap, 67 + .open = generic_file_open, 68 + .release = ext2_release_file, 69 + .fsync = ext2_sync_file, 70 + .readv = xip_file_readv, 71 + .writev = xip_file_writev, 72 + .sendfile = xip_file_sendfile, 73 + }; 74 + #endif 75 + 58 76 struct inode_operations ext2_file_inode_operations = { 59 77 .truncate = ext2_truncate, 60 78 #ifdef CONFIG_EXT2_FS_XATTR
+27 -4
fs/ext2/inode.c
··· 33 33 #include <linux/mpage.h> 34 34 #include "ext2.h" 35 35 #include "acl.h" 36 + #include "xip.h" 36 37 37 38 MODULE_AUTHOR("Remy Card and others"); 38 39 MODULE_DESCRIPTION("Second Extended Filesystem"); ··· 595 594 if (err) 596 595 goto cleanup; 597 596 597 + if (ext2_use_xip(inode->i_sb)) { 598 + /* 599 + * we need to clear the block 600 + */ 601 + err = ext2_clear_xip_target (inode, 602 + le32_to_cpu(chain[depth-1].key)); 603 + if (err) 604 + goto cleanup; 605 + } 606 + 598 607 if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0) 599 608 goto changed; 600 609 ··· 700 689 .bmap = ext2_bmap, 701 690 .direct_IO = ext2_direct_IO, 702 691 .writepages = ext2_writepages, 692 + }; 693 + 694 + struct address_space_operations ext2_aops_xip = { 695 + .bmap = ext2_bmap, 696 + .get_xip_page = ext2_get_xip_page, 703 697 }; 704 698 705 699 struct address_space_operations ext2_nobh_aops = { ··· 926 910 iblock = (inode->i_size + blocksize-1) 927 911 >> EXT2_BLOCK_SIZE_BITS(inode->i_sb); 928 912 929 - if (test_opt(inode->i_sb, NOBH)) 913 + if (mapping_is_xip(inode->i_mapping)) 914 + xip_truncate_page(inode->i_mapping, inode->i_size); 915 + else if (test_opt(inode->i_sb, NOBH)) 930 916 nobh_truncate_page(inode->i_mapping, inode->i_size); 931 917 else 932 918 block_truncate_page(inode->i_mapping, ··· 1128 1110 1129 1111 if (S_ISREG(inode->i_mode)) { 1130 1112 inode->i_op = &ext2_file_inode_operations; 1131 - inode->i_fop = &ext2_file_operations; 1132 - if (test_opt(inode->i_sb, NOBH)) 1113 + if (ext2_use_xip(inode->i_sb)) { 1114 + inode->i_mapping->a_ops = &ext2_aops_xip; 1115 + inode->i_fop = &ext2_xip_file_operations; 1116 + } else if (test_opt(inode->i_sb, NOBH)) { 1133 1117 inode->i_mapping->a_ops = &ext2_nobh_aops; 1134 - else 1118 + inode->i_fop = &ext2_file_operations; 1119 + } else { 1135 1120 inode->i_mapping->a_ops = &ext2_aops; 1121 + inode->i_fop = &ext2_file_operations; 1122 + } 1136 1123 } else if (S_ISDIR(inode->i_mode)) { 1137 1124 inode->i_op = &ext2_dir_inode_operations; 1138 1125 inode->i_fop = &ext2_dir_operations;
+9 -3
fs/ext2/namei.c
··· 34 34 #include "ext2.h" 35 35 #include "xattr.h" 36 36 #include "acl.h" 37 + #include "xip.h" 37 38 38 39 /* 39 40 * Couple of helper functions - make the code slightly cleaner. ··· 128 127 int err = PTR_ERR(inode); 129 128 if (!IS_ERR(inode)) { 130 129 inode->i_op = &ext2_file_inode_operations; 131 - inode->i_fop = &ext2_file_operations; 132 - if (test_opt(inode->i_sb, NOBH)) 130 + if (ext2_use_xip(inode->i_sb)) { 131 + inode->i_mapping->a_ops = &ext2_aops_xip; 132 + inode->i_fop = &ext2_xip_file_operations; 133 + } else if (test_opt(inode->i_sb, NOBH)) { 133 134 inode->i_mapping->a_ops = &ext2_nobh_aops; 134 - else 135 + inode->i_fop = &ext2_file_operations; 136 + } else { 135 137 inode->i_mapping->a_ops = &ext2_aops; 138 + inode->i_fop = &ext2_file_operations; 139 + } 136 140 mark_inode_dirty(inode); 137 141 err = ext2_add_nondir(dentry, inode); 138 142 }
+26 -1
fs/ext2/super.c
··· 31 31 #include "ext2.h" 32 32 #include "xattr.h" 33 33 #include "acl.h" 34 + #include "xip.h" 34 35 35 36 static void ext2_sync_super(struct super_block *sb, 36 37 struct ext2_super_block *es); ··· 258 257 Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, 259 258 Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, 260 259 Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, 261 - Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, 260 + Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip, 262 261 Opt_ignore, Opt_err, 263 262 }; 264 263 ··· 287 286 {Opt_nouser_xattr, "nouser_xattr"}, 288 287 {Opt_acl, "acl"}, 289 288 {Opt_noacl, "noacl"}, 289 + {Opt_xip, "xip"}, 290 290 {Opt_ignore, "grpquota"}, 291 291 {Opt_ignore, "noquota"}, 292 292 {Opt_ignore, "quota"}, ··· 399 397 printk("EXT2 (no)acl options not supported\n"); 400 398 break; 401 399 #endif 400 + case Opt_xip: 401 + #ifdef CONFIG_EXT2_FS_XIP 402 + set_opt (sbi->s_mount_opt, XIP); 403 + #else 404 + printk("EXT2 xip option not supported\n"); 405 + #endif 406 + break; 402 407 case Opt_ignore: 403 408 break; 404 409 default: ··· 649 640 ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? 650 641 MS_POSIXACL : 0); 651 642 643 + ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset 644 + EXT2_MOUNT_XIP if not */ 645 + 652 646 if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV && 653 647 (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) || 654 648 EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) || ··· 679 667 } 680 668 681 669 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); 670 + 671 + if ((ext2_use_xip(sb)) && ((blocksize != PAGE_SIZE) || 672 + (sb->s_blocksize != blocksize))) { 673 + if (!silent) 674 + printk("XIP: Unsupported blocksize\n"); 675 + goto failed_mount; 676 + } 682 677 683 678 /* If the blocksize doesn't match, re-read the thing.. */ 684 679 if (sb->s_blocksize != blocksize) { ··· 935 916 { 936 917 struct ext2_sb_info * sbi = EXT2_SB(sb); 937 918 struct ext2_super_block * es; 919 + unsigned long old_mount_opt = sbi->s_mount_opt; 938 920 939 921 /* 940 922 * Allow the "check" option to be passed as a remount option. ··· 947 927 ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); 948 928 949 929 es = sbi->s_es; 930 + if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) != 931 + (old_mount_opt & EXT2_MOUNT_XIP)) && 932 + invalidate_inodes(sb)) 933 + ext2_warning(sb, __FUNCTION__, "busy inodes while remounting "\ 934 + "xip remain in cache (no functional problem)"); 950 935 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) 951 936 return 0; 952 937 if (*flags & MS_RDONLY) {
+80
fs/ext2/xip.c
··· 1 + /* 2 + * linux/fs/ext2/xip.c 3 + * 4 + * Copyright (C) 2005 IBM Corporation 5 + * Author: Carsten Otte (cotte@de.ibm.com) 6 + */ 7 + 8 + #include <linux/mm.h> 9 + #include <linux/fs.h> 10 + #include <linux/genhd.h> 11 + #include <linux/buffer_head.h> 12 + #include <linux/ext2_fs_sb.h> 13 + #include <linux/ext2_fs.h> 14 + #include "ext2.h" 15 + #include "xip.h" 16 + 17 + static inline int 18 + __inode_direct_access(struct inode *inode, sector_t sector, unsigned long *data) { 19 + BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access); 20 + return inode->i_sb->s_bdev->bd_disk->fops 21 + ->direct_access(inode->i_sb->s_bdev,sector,data); 22 + } 23 + 24 + int 25 + ext2_clear_xip_target(struct inode *inode, int block) { 26 + sector_t sector = block*(PAGE_SIZE/512); 27 + unsigned long data; 28 + int rc; 29 + 30 + rc = __inode_direct_access(inode, sector, &data); 31 + if (rc) 32 + return rc; 33 + clear_page((void*)data); 34 + return 0; 35 + } 36 + 37 + void ext2_xip_verify_sb(struct super_block *sb) 38 + { 39 + struct ext2_sb_info *sbi = EXT2_SB(sb); 40 + 41 + if ((sbi->s_mount_opt & EXT2_MOUNT_XIP)) { 42 + if ((sb->s_bdev == NULL) || 43 + sb->s_bdev->bd_disk == NULL || 44 + sb->s_bdev->bd_disk->fops == NULL || 45 + sb->s_bdev->bd_disk->fops->direct_access == NULL) { 46 + sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); 47 + ext2_warning(sb, __FUNCTION__, 48 + "ignoring xip option - not supported by bdev"); 49 + } 50 + } 51 + } 52 + 53 + struct page* 54 + ext2_get_xip_page(struct address_space *mapping, sector_t blockno, 55 + int create) 56 + { 57 + int rc; 58 + unsigned long data; 59 + struct buffer_head tmp; 60 + 61 + tmp.b_state = 0; 62 + tmp.b_blocknr = 0; 63 + rc = ext2_get_block(mapping->host, blockno/(PAGE_SIZE/512) , &tmp, 64 + create); 65 + if (rc) 66 + return ERR_PTR(rc); 67 + if (tmp.b_blocknr == 0) { 68 + /* SPARSE block */ 69 + BUG_ON(create); 70 + return ERR_PTR(-ENODATA); 71 + } 72 + 73 + rc = __inode_direct_access 74 + (mapping->host,tmp.b_blocknr*(PAGE_SIZE/512) ,&data); 75 + if (rc) 76 + return ERR_PTR(rc); 77 + 78 + SetPageUptodate(virt_to_page(data)); 79 + return virt_to_page(data); 80 + }
+25
fs/ext2/xip.h
··· 1 + /* 2 + * linux/fs/ext2/xip.h 3 + * 4 + * Copyright (C) 2005 IBM Corporation 5 + * Author: Carsten Otte (cotte@de.ibm.com) 6 + */ 7 + 8 + #ifdef CONFIG_EXT2_FS_XIP 9 + extern void ext2_xip_verify_sb (struct super_block *); 10 + extern int ext2_clear_xip_target (struct inode *, int); 11 + 12 + static inline int ext2_use_xip (struct super_block *sb) 13 + { 14 + struct ext2_sb_info *sbi = EXT2_SB(sb); 15 + return (sbi->s_mount_opt & EXT2_MOUNT_XIP); 16 + } 17 + struct page* ext2_get_xip_page (struct address_space *, sector_t, int); 18 + #define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page) 19 + #else 20 + #define mapping_is_xip(map) 0 21 + #define ext2_xip_verify_sb(sb) do { } while (0) 22 + #define ext2_use_xip(sb) 0 23 + #define ext2_clear_xip_target(inode, chain) 0 24 + #define ext2_get_xip_page NULL 25 + #endif
+13 -12
include/linux/ext2_fs.h
··· 300 300 /* 301 301 * Mount flags 302 302 */ 303 - #define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ 304 - #define EXT2_MOUNT_OLDALLOC 0x0002 /* Don't use the new Orlov allocator */ 305 - #define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ 306 - #define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ 307 - #define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ 308 - #define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ 309 - #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ 310 - #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ 311 - #define EXT2_MOUNT_NOBH 0x0100 /* No buffer_heads */ 312 - #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ 313 - #define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ 314 - #define EXT2_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ 303 + #define EXT2_MOUNT_CHECK 0x000001 /* Do mount-time checks */ 304 + #define EXT2_MOUNT_OLDALLOC 0x000002 /* Don't use the new Orlov allocator */ 305 + #define EXT2_MOUNT_GRPID 0x000004 /* Create files with directory's group */ 306 + #define EXT2_MOUNT_DEBUG 0x000008 /* Some debugging messages */ 307 + #define EXT2_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */ 308 + #define EXT2_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */ 309 + #define EXT2_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */ 310 + #define EXT2_MOUNT_MINIX_DF 0x000080 /* Mimics the Minix statfs */ 311 + #define EXT2_MOUNT_NOBH 0x000100 /* No buffer_heads */ 312 + #define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */ 313 + #define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */ 314 + #define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */ 315 + #define EXT2_MOUNT_XIP 0x010000 /* Execute in place */ 315 316 316 317 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt 317 318 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
+5
include/linux/fs.h
··· 1513 1513 extern ssize_t xip_file_writev(struct file *file, const struct iovec *iov, 1514 1514 unsigned long nr_segs, loff_t *ppos); 1515 1515 extern int xip_truncate_page(struct address_space *mapping, loff_t from); 1516 + #else 1517 + static inline int xip_truncate_page(struct address_space *mapping, loff_t from) 1518 + { 1519 + return 0; 1520 + } 1516 1521 #endif 1517 1522 1518 1523 static inline void do_generic_file_read(struct file * filp, loff_t *ppos,