diff options
Diffstat (limited to 'fs')
231 files changed, 3453 insertions, 1314 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 378767c07bf..5cf22134826 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -41,10 +41,10 @@ #include "v9fs_vfs.h" #include "fid.h" -static struct inode_operations v9fs_dir_inode_operations; -static struct inode_operations v9fs_dir_inode_operations_ext; -static struct inode_operations v9fs_file_inode_operations; -static struct inode_operations v9fs_symlink_inode_operations; +static const struct inode_operations v9fs_dir_inode_operations; +static const struct inode_operations v9fs_dir_inode_operations_ext; +static const struct inode_operations v9fs_file_inode_operations; +static const struct inode_operations v9fs_symlink_inode_operations; /** * unixmode2p9mode - convert unix mode bits to plan 9 @@ -1303,7 +1303,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) return retval; } -static struct inode_operations v9fs_dir_inode_operations_ext = { +static const struct inode_operations v9fs_dir_inode_operations_ext = { .create = v9fs_vfs_create, .lookup = v9fs_vfs_lookup, .symlink = v9fs_vfs_symlink, @@ -1318,7 +1318,7 @@ static struct inode_operations v9fs_dir_inode_operations_ext = { .setattr = v9fs_vfs_setattr, }; -static struct inode_operations v9fs_dir_inode_operations = { +static const struct inode_operations v9fs_dir_inode_operations = { .create = v9fs_vfs_create, .lookup = v9fs_vfs_lookup, .unlink = v9fs_vfs_unlink, @@ -1330,12 +1330,12 @@ static struct inode_operations v9fs_dir_inode_operations = { .setattr = v9fs_vfs_setattr, }; -static struct inode_operations v9fs_file_inode_operations = { +static const struct inode_operations v9fs_file_inode_operations = { .getattr = v9fs_vfs_getattr, .setattr = v9fs_vfs_setattr, }; -static struct inode_operations v9fs_symlink_inode_operations = { +static const struct inode_operations v9fs_symlink_inode_operations = { .readlink = v9fs_vfs_readlink, .follow_link = v9fs_vfs_follow_link, .put_link = v9fs_vfs_put_link, diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 63320d4e15d..0ec42f66545 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -45,7 +45,7 @@ #include "fid.h" static void v9fs_clear_inode(struct inode *); -static struct super_operations v9fs_super_ops; +static const struct super_operations v9fs_super_ops; /** * v9fs_clear_inode - release an inode @@ -263,7 +263,7 @@ v9fs_umount_begin(struct vfsmount *vfsmnt, int flags) v9fs_session_cancel(v9ses); } -static struct super_operations v9fs_super_ops = { +static const struct super_operations v9fs_super_ops = { .statfs = simple_statfs, .clear_inode = v9fs_clear_inode, .show_options = v9fs_show_options, diff --git a/fs/Kconfig b/fs/Kconfig index 11c59329ed0..488521ed9e9 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1088,7 +1088,7 @@ config AFFS_FS config ECRYPT_FS tristate "eCrypt filesystem layer support (EXPERIMENTAL)" - depends on EXPERIMENTAL && KEYS && CRYPTO + depends on EXPERIMENTAL && KEYS && CRYPTO && NET help Encrypted filesystem that operates on the VFS layer. See <file:Documentation/ecryptfs.txt> to learn more about diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index 29217ff36d4..936f2af39c4 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -84,7 +84,7 @@ void __adfs_error(struct super_block *sb, const char *function, */ /* dir_*.c */ -extern struct inode_operations adfs_dir_inode_operations; +extern const struct inode_operations adfs_dir_inode_operations; extern const struct file_operations adfs_dir_operations; extern struct dentry_operations adfs_dentry_operations; extern struct adfs_dir_ops adfs_f_dir_ops; @@ -93,7 +93,7 @@ extern struct adfs_dir_ops adfs_fplus_dir_ops; extern int adfs_dir_update(struct super_block *sb, struct object_info *obj); /* file.c */ -extern struct inode_operations adfs_file_inode_operations; +extern const struct inode_operations adfs_file_inode_operations; extern const struct file_operations adfs_file_operations; static inline __u32 signed_asl(__u32 val, signed int shift) diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 2b8903893d3..fc1a8dc64d7 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -295,7 +295,7 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) /* * directories can handle most operations... */ -struct inode_operations adfs_dir_inode_operations = { +const struct inode_operations adfs_dir_inode_operations = { .lookup = adfs_lookup, .setattr = adfs_notify_change, }; diff --git a/fs/adfs/file.c b/fs/adfs/file.c index 6101ea679cb..f544a285592 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c @@ -36,6 +36,6 @@ const struct file_operations adfs_file_operations = { .sendfile = generic_file_sendfile, }; -struct inode_operations adfs_file_inode_operations = { +const struct inode_operations adfs_file_inode_operations = { .setattr = adfs_notify_change, }; diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 5023351a7af..2e5f2c8371e 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -254,7 +254,7 @@ static void destroy_inodecache(void) kmem_cache_destroy(adfs_inode_cachep); } -static struct super_operations adfs_sops = { +static const struct super_operations adfs_sops = { .alloc_inode = adfs_alloc_inode, .destroy_inode = adfs_destroy_inode, .write_inode = adfs_write_inode, diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 1dc8438ef38..7db2d287e9f 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h @@ -188,9 +188,9 @@ extern void affs_dir_truncate(struct inode *); /* jump tables */ -extern struct inode_operations affs_file_inode_operations; -extern struct inode_operations affs_dir_inode_operations; -extern struct inode_operations affs_symlink_inode_operations; +extern const struct inode_operations affs_file_inode_operations; +extern const struct inode_operations affs_dir_inode_operations; +extern const struct inode_operations affs_symlink_inode_operations; extern const struct file_operations affs_file_operations; extern const struct file_operations affs_file_operations_ofs; extern const struct file_operations affs_dir_operations; diff --git a/fs/affs/dir.c b/fs/affs/dir.c index cad3ee34006..6e3f282424b 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -26,7 +26,7 @@ const struct file_operations affs_dir_operations = { /* * directories can handle most operations... */ -struct inode_operations affs_dir_inode_operations = { +const struct inode_operations affs_dir_inode_operations = { .create = affs_create, .lookup = affs_lookup, .link = affs_link, diff --git a/fs/affs/file.c b/fs/affs/file.c index 05b5e22de75..4aa8079e71b 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -38,7 +38,7 @@ const struct file_operations affs_file_operations = { .sendfile = generic_file_sendfile, }; -struct inode_operations affs_file_inode_operations = { +const struct inode_operations affs_file_inode_operations = { .truncate = affs_truncate, .setattr = affs_notify_change, }; diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 44d439cb69f..fce6848a464 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -12,7 +12,7 @@ #include "affs.h" -extern struct inode_operations affs_symlink_inode_operations; +extern const struct inode_operations affs_symlink_inode_operations; extern struct timezone sys_tz; void diff --git a/fs/affs/super.c b/fs/affs/super.c index 3de93e79994..a324045d855 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -112,7 +112,7 @@ static void destroy_inodecache(void) kmem_cache_destroy(affs_inode_cachep); } -static struct super_operations affs_sops = { +static const struct super_operations affs_sops = { .alloc_inode = affs_alloc_inode, .destroy_inode = affs_destroy_inode, .read_inode = affs_read_inode, diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index f802256a593..41782539c90 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -70,7 +70,7 @@ const struct address_space_operations affs_symlink_aops = { .readpage = affs_symlink_readpage, }; -struct inode_operations affs_symlink_inode_operations = { +const struct inode_operations affs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 4acd0413405..9908462bcad 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -37,7 +37,7 @@ const struct file_operations afs_dir_file_operations = { .readdir = afs_dir_readdir, }; -struct inode_operations afs_dir_inode_operations = { +const struct inode_operations afs_dir_inode_operations = { .lookup = afs_dir_lookup, .getattr = afs_inode_getattr, #if 0 /* TODO */ diff --git a/fs/afs/file.c b/fs/afs/file.c index 2e8c42639ea..eeff14c3f74 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -30,7 +30,7 @@ static int afs_file_readpage(struct file *file, struct page *page); static void afs_file_invalidatepage(struct page *page, unsigned long offset); static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); -struct inode_operations afs_file_inode_operations = { +const struct inode_operations afs_file_inode_operations = { .getattr = afs_inode_getattr, }; diff --git a/fs/afs/internal.h b/fs/afs/internal.h index e88b3b65ae4..5151d5da2c2 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -63,14 +63,14 @@ extern struct cachefs_index_def afs_cache_cell_index_def; /* * dir.c */ -extern struct inode_operations afs_dir_inode_operations; +extern const struct inode_operations afs_dir_inode_operations; extern const struct file_operations afs_dir_file_operations; /* * file.c */ extern const struct address_space_operations afs_fs_aops; -extern struct inode_operations afs_file_inode_operations; +extern const struct inode_operations afs_file_inode_operations; #ifdef AFS_CACHING_SUPPORT extern int afs_cache_get_page_cookie(struct page *page, @@ -104,7 +104,7 @@ extern struct cachefs_netfs afs_cache_netfs; /* * mntpt.c */ -extern struct inode_operations afs_mntpt_inode_operations; +extern const struct inode_operations afs_mntpt_inode_operations; extern const struct file_operations afs_mntpt_file_operations; extern struct afs_timer afs_mntpt_expiry_timer; extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 8f74e845082..fdf23b2a211 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -36,7 +36,7 @@ const struct file_operations afs_mntpt_file_operations = { .open = afs_mntpt_open, }; -struct inode_operations afs_mntpt_inode_operations = { +const struct inode_operations afs_mntpt_inode_operations = { .lookup = afs_mntpt_lookup, .follow_link = afs_mntpt_follow_link, .readlink = page_readlink, diff --git a/fs/afs/super.c b/fs/afs/super.c index 18d9b77ba40..eb7e32349da 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -56,7 +56,7 @@ struct file_system_type afs_fs_type = { .fs_flags = FS_BINARY_MOUNTDATA, }; -static struct super_operations afs_super_ops = { +static const struct super_operations afs_super_ops = { .statfs = simple_statfs, .alloc_inode = afs_alloc_inode, .drop_inode = generic_delete_inode, diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 906ba5ce226..4ef544434b5 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -142,8 +142,8 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info /* Operations structures */ -extern struct inode_operations autofs_root_inode_operations; -extern struct inode_operations autofs_symlink_inode_operations; +extern const struct inode_operations autofs_root_inode_operations; +extern const struct inode_operations autofs_symlink_inode_operations; extern const struct file_operations autofs_root_operations; /* Initializing function */ diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index f968d134280..aa0b61ff827 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -52,7 +52,7 @@ out_kill_sb: static void autofs_read_inode(struct inode *inode); -static struct super_operations autofs_sops = { +static const struct super_operations autofs_sops = { .read_inode = autofs_read_inode, .statfs = simple_statfs, }; diff --git a/fs/autofs/root.c b/fs/autofs/root.c index e698c51d2b0..f2597205939 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -32,7 +32,7 @@ const struct file_operations autofs_root_operations = { .ioctl = autofs_root_ioctl, }; -struct inode_operations autofs_root_inode_operations = { +const struct inode_operations autofs_root_inode_operations = { .lookup = autofs_root_lookup, .unlink = autofs_root_unlink, .symlink = autofs_root_symlink, diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c index c74f2eb6577..7ce9cb2c9ce 100644 --- a/fs/autofs/symlink.c +++ b/fs/autofs/symlink.c @@ -20,7 +20,7 @@ static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations autofs_symlink_inode_operations = { +const struct inode_operations autofs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = autofs_follow_link }; diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 216b1a364cc..6b4cec3f272 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -168,11 +168,11 @@ int autofs4_expire_multi(struct super_block *, struct vfsmount *, /* Operations structures */ -extern struct inode_operations autofs4_symlink_inode_operations; -extern struct inode_operations autofs4_dir_inode_operations; -extern struct inode_operations autofs4_root_inode_operations; -extern struct inode_operations autofs4_indirect_root_inode_operations; -extern struct inode_operations autofs4_direct_root_inode_operations; +extern const struct inode_operations autofs4_symlink_inode_operations; +extern const struct inode_operations autofs4_dir_inode_operations; +extern const struct inode_operations autofs4_root_inode_operations; +extern const struct inode_operations autofs4_indirect_root_inode_operations; +extern const struct inode_operations autofs4_direct_root_inode_operations; extern const struct file_operations autofs4_dir_operations; extern const struct file_operations autofs4_root_operations; diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index e8f6c5ad3e9..5e458e096ef 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -196,7 +196,7 @@ static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) return 0; } -static struct super_operations autofs4_sops = { +static const struct super_operations autofs4_sops = { .statfs = simple_statfs, .show_options = autofs4_show_options, }; diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 8d05b9f7578..47fee96c218 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -47,7 +47,7 @@ const struct file_operations autofs4_dir_operations = { .readdir = autofs4_dir_readdir, }; -struct inode_operations autofs4_indirect_root_inode_operations = { +const struct inode_operations autofs4_indirect_root_inode_operations = { .lookup = autofs4_lookup, .unlink = autofs4_dir_unlink, .symlink = autofs4_dir_symlink, @@ -55,7 +55,7 @@ struct inode_operations autofs4_indirect_root_inode_operations = { .rmdir = autofs4_dir_rmdir, }; -struct inode_operations autofs4_direct_root_inode_operations = { +const struct inode_operations autofs4_direct_root_inode_operations = { .lookup = autofs4_lookup, .unlink = autofs4_dir_unlink, .mkdir = autofs4_dir_mkdir, @@ -63,7 +63,7 @@ struct inode_operations autofs4_direct_root_inode_operations = { .follow_link = autofs4_follow_link, }; -struct inode_operations autofs4_dir_inode_operations = { +const struct inode_operations autofs4_dir_inode_operations = { .lookup = autofs4_lookup, .unlink = autofs4_dir_unlink, .symlink = autofs4_dir_symlink, diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index 2ea2c98fd84..b4ea82934d2 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c @@ -19,7 +19,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations autofs4_symlink_inode_operations = { +const struct inode_operations autofs4_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = autofs4_follow_link }; diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 869f5193ecc..efeab2fab40 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -291,7 +291,7 @@ static int bad_inode_removexattr(struct dentry *dentry, const char *name) return -EIO; } -static struct inode_operations bad_inode_ops = +static const struct inode_operations bad_inode_ops = { .create = bad_inode_create, .lookup = bad_inode_lookup, diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 481e59b9d91..cc6cc8ed2e3 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -68,7 +68,7 @@ static const struct file_operations befs_dir_operations = { .readdir = befs_readdir, }; -static struct inode_operations befs_dir_inode_operations = { +static const struct inode_operations befs_dir_inode_operations = { .lookup = befs_lookup, }; @@ -78,7 +78,7 @@ static const struct address_space_operations befs_aops = { .bmap = befs_bmap, }; -static struct inode_operations befs_symlink_inode_operations = { +static const struct inode_operations befs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = befs_follow_link, .put_link = befs_put_link, diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 31973bbbf05..130f6c66c5b 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h @@ -48,12 +48,12 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode) /* file.c */ -extern struct inode_operations bfs_file_inops; +extern const struct inode_operations bfs_file_inops; extern const struct file_operations bfs_file_operations; extern const struct address_space_operations bfs_aops; /* dir.c */ -extern struct inode_operations bfs_dir_inops; +extern const struct inode_operations bfs_dir_inops; extern const struct file_operations bfs_dir_operations; #endif /* _FS_BFS_BFS_H */ diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 2a746e688df..097f1497f74 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -260,7 +260,7 @@ end_rename: return error; } -struct inode_operations bfs_dir_inops = { +const struct inode_operations bfs_dir_inops = { .create = bfs_create, .lookup = bfs_lookup, .link = bfs_link, diff --git a/fs/bfs/file.c b/fs/bfs/file.c index a9164a87f8d..ef4d1fa04e6 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -164,4 +164,4 @@ const struct address_space_operations bfs_aops = { .bmap = bfs_bmap, }; -struct inode_operations bfs_file_inops; +const struct inode_operations bfs_file_inops; diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 134c99941a6..93d6219243a 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -270,7 +270,7 @@ static void destroy_inodecache(void) kmem_cache_destroy(bfs_inode_cachep); } -static struct super_operations bfs_sops = { +static const struct super_operations bfs_sops = { .alloc_inode = bfs_alloc_inode, .destroy_inode = bfs_destroy_inode, .read_inode = bfs_read_inode, diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index c2e08252af3..e6f57990b12 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -719,7 +719,7 @@ static const struct file_operations bm_status_operations = { /* Superblock handling */ -static struct super_operations s_ops = { +static const struct super_operations s_ops = { .statfs = simple_statfs, .clear_inode = bm_clear_inode, }; diff --git a/fs/block_dev.c b/fs/block_dev.c index fc7028b685f..0c59b703e9d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -489,7 +489,7 @@ static void bdev_clear_inode(struct inode *inode) spin_unlock(&bdev_lock); } -static struct super_operations bdev_sops = { +static const struct super_operations bdev_sops = { .statfs = simple_statfs, .alloc_inode = bdev_alloc_inode, .destroy_inode = bdev_destroy_inode, diff --git a/fs/buffer.c b/fs/buffer.c index 7ff6e9346fa..f99c509697c 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1283,11 +1283,11 @@ static void bh_lru_install(struct buffer_head *bh) * Look up the bh in this cpu's LRU. If it's there, move it to the head. */ static struct buffer_head * -lookup_bh_lru(struct block_device *bdev, sector_t block, int size) +lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size) { struct buffer_head *ret = NULL; struct bh_lru *lru; - int i; + unsigned int i; check_irqs_on(); bh_lru_lock(); @@ -1319,7 +1319,7 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, int size) * NULL */ struct buffer_head * -__find_get_block(struct block_device *bdev, sector_t block, int size) +__find_get_block(struct block_device *bdev, sector_t block, unsigned size) { struct buffer_head *bh = lookup_bh_lru(bdev, block, size); @@ -1347,7 +1347,7 @@ EXPORT_SYMBOL(__find_get_block); * attempt is failing. FIXME, perhaps? */ struct buffer_head * -__getblk(struct block_device *bdev, sector_t block, int size) +__getblk(struct block_device *bdev, sector_t block, unsigned size) { struct buffer_head *bh = __find_get_block(bdev, block, size); @@ -1361,7 +1361,7 @@ EXPORT_SYMBOL(__getblk); /* * Do async read-ahead on a buffer.. */ -void __breadahead(struct block_device *bdev, sector_t block, int size) +void __breadahead(struct block_device *bdev, sector_t block, unsigned size) { struct buffer_head *bh = __getblk(bdev, block, size); if (likely(bh)) { @@ -1381,7 +1381,7 @@ EXPORT_SYMBOL(__breadahead); * It returns NULL if the block was unreadable. */ struct buffer_head * -__bread(struct block_device *bdev, sector_t block, int size) +__bread(struct block_device *bdev, sector_t block, unsigned size) { struct buffer_head *bh = __getblk(bdev, block, size); @@ -1440,6 +1440,7 @@ static void discard_buffer(struct buffer_head * bh) clear_buffer_req(bh); clear_buffer_new(bh); clear_buffer_delay(bh); + clear_buffer_unwritten(bh); unlock_buffer(bh); } @@ -1823,6 +1824,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page, continue; } if (!buffer_uptodate(bh) && !buffer_delay(bh) && + !buffer_unwritten(bh) && (block_start < from || block_end > to)) { ll_rw_block(READ, 1, &bh); *wait_bh++=bh; @@ -2544,7 +2546,7 @@ int block_truncate_page(struct address_space *mapping, if (PageUptodate(page)) set_buffer_uptodate(bh); - if (!buffer_uptodate(bh) && !buffer_delay(bh)) { + if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) { err = -EIO; ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); diff --git a/fs/char_dev.c b/fs/char_dev.c index a885f46ca00..e6194e2b9bb 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -108,6 +108,13 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, /* temporary */ if (major == 0) { for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { + /* + * Disallow the LANANA-assigned LOCAL/EXPERIMENTAL + * majors + */ + if ((60 <= i && i <= 63) || (120 <= i && i <= 127) || + (240 <= i && i <= 254)) + continue; if (chrdevs[i] == NULL) break; } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 93ef09971d2..e8287c4c6eb 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -64,7 +64,7 @@ extern struct task_struct * oplockThread; /* remove sparse warning */ struct task_struct * oplockThread = NULL; extern struct task_struct * dnotifyThread; /* remove sparse warning */ struct task_struct * dnotifyThread = NULL; -static struct super_operations cifs_super_ops; +static const struct super_operations cifs_super_ops; unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; module_param(CIFSMaxBufSize, int, 0); MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); @@ -453,7 +453,7 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations cifs_super_ops = { +static const struct super_operations cifs_super_ops = { .read_inode = cifs_read_inode, .put_super = cifs_put_super, .statfs = cifs_statfs, @@ -533,7 +533,7 @@ static struct file_system_type cifs_fs_type = { .kill_sb = kill_anon_super, /* .fs_flags */ }; -struct inode_operations cifs_dir_inode_ops = { +const struct inode_operations cifs_dir_inode_ops = { .create = cifs_create, .lookup = cifs_lookup, .getattr = cifs_getattr, @@ -555,7 +555,7 @@ struct inode_operations cifs_dir_inode_ops = { #endif }; -struct inode_operations cifs_file_inode_ops = { +const struct inode_operations cifs_file_inode_ops = { /* revalidate:cifs_revalidate, */ .setattr = cifs_setattr, .getattr = cifs_getattr, /* do we need this anymore? */ @@ -569,7 +569,7 @@ struct inode_operations cifs_file_inode_ops = { #endif }; -struct inode_operations cifs_symlink_inode_ops = { +const struct inode_operations cifs_symlink_inode_ops = { .readlink = generic_readlink, .follow_link = cifs_follow_link, .put_link = cifs_put_link, diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 8aa66dcf13b..01ae24af9cf 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -36,13 +36,13 @@ extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; /* Functions related to super block operations */ -/* extern struct super_operations cifs_super_ops;*/ +/* extern const struct super_operations cifs_super_ops;*/ extern void cifs_read_inode(struct inode *); extern void cifs_delete_inode(struct inode *); /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */ /* Functions related to inodes */ -extern struct inode_operations cifs_dir_inode_ops; +extern const struct inode_operations cifs_dir_inode_ops; extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *); extern struct dentry * cifs_lookup(struct inode *, struct dentry *, @@ -58,8 +58,8 @@ extern int cifs_revalidate(struct dentry *); extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int cifs_setattr(struct dentry *, struct iattr *); -extern struct inode_operations cifs_file_inode_ops; -extern struct inode_operations cifs_symlink_inode_ops; +extern const struct inode_operations cifs_file_inode_ops; +extern const struct inode_operations cifs_symlink_inode_ops; /* Functions related to files and directories */ extern const struct file_operations cifs_file_ops; diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 4c9fecbfa91..28c872747f8 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -16,7 +16,7 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) return memcmp(fid1, fid2, sizeof(*fid1)) == 0; } -static struct inode_operations coda_symlink_inode_operations = { +static const struct inode_operations coda_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 0c6f7f3b3dd..9ddf5ed6216 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -66,7 +66,7 @@ static struct dentry_operations coda_dentry_operations = .d_delete = coda_dentry_delete, }; -struct inode_operations coda_dir_inode_operations = +const struct inode_operations coda_dir_inode_operations = { .create = coda_create, .lookup = coda_lookup, diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 01395defed8..614175a3b02 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -90,7 +90,7 @@ static int coda_remount(struct super_block *sb, int *flags, char *data) } /* exported operations */ -static struct super_operations coda_super_operations = +static const struct super_operations coda_super_operations = { .alloc_inode = coda_alloc_inode, .destroy_inode = coda_destroy_inode, @@ -271,7 +271,7 @@ int coda_setattr(struct dentry *de, struct iattr *iattr) return error; } -struct inode_operations coda_file_inode_operations = { +const struct inode_operations coda_file_inode_operations = { .permission = coda_permission, .getattr = coda_getattr, .setattr = coda_setattr, diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 214822be87b..2bf3026adc8 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -30,7 +30,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long user_data); /* exported from this file */ -struct inode_operations coda_ioctl_inode_operations = +const struct inode_operations coda_ioctl_inode_operations = { .permission = coda_ioctl_permission, .setattr = coda_setattr, diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index f92cd303d2c..7b48c034b31 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h @@ -75,8 +75,8 @@ extern struct super_block * configfs_sb; extern const struct file_operations configfs_dir_operations; extern const struct file_operations configfs_file_operations; extern const struct file_operations bin_fops; -extern struct inode_operations configfs_dir_inode_operations; -extern struct inode_operations configfs_symlink_inode_operations; +extern const struct inode_operations configfs_dir_inode_operations; +extern const struct inode_operations configfs_symlink_inode_operations; extern int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 9371ee20995..34750d5e4ff 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -930,7 +930,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) return 0; } -struct inode_operations configfs_dir_inode_operations = { +const struct inode_operations configfs_dir_inode_operations = { .mkdir = configfs_mkdir, .rmdir = configfs_rmdir, .symlink = configfs_symlink, diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index fb18917954a..2ec9beac17c 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -49,7 +49,7 @@ static struct backing_dev_info configfs_backing_dev_info = { .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, }; -static struct inode_operations configfs_inode_operations ={ +static const struct inode_operations configfs_inode_operations ={ .setattr = configfs_setattr, }; diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index ed678529ebb..6f573004cd7 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -41,7 +41,7 @@ struct super_block * configfs_sb = NULL; struct kmem_cache *configfs_dir_cachep; static int configfs_mnt_count = 0; -static struct super_operations configfs_ops = { +static const struct super_operations configfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, }; diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index fb65e0800a8..22700d2857d 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -272,7 +272,7 @@ static void configfs_put_link(struct dentry *dentry, struct nameidata *nd, } } -struct inode_operations configfs_symlink_inode_operations = { +const struct inode_operations configfs_symlink_inode_operations = { .follow_link = configfs_follow_link, .readlink = generic_readlink, .put_link = configfs_put_link, diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 6db03fb089d..facd0c89be8 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -27,8 +27,8 @@ #include <asm/uaccess.h> -static struct super_operations cramfs_ops; -static struct inode_operations cramfs_dir_inode_operations; +static const struct super_operations cramfs_ops; +static const struct inode_operations cramfs_dir_inode_operations; static const struct file_operations cramfs_directory_operations; static const struct address_space_operations cramfs_aops; @@ -518,11 +518,11 @@ static const struct file_operations cramfs_directory_operations = { .readdir = cramfs_readdir, }; -static struct inode_operations cramfs_dir_inode_operations = { +static const struct inode_operations cramfs_dir_inode_operations = { .lookup = cramfs_lookup, }; -static struct super_operations cramfs_ops = { +static const struct super_operations cramfs_ops = { .put_super = cramfs_put_super, .remount_fs = cramfs_remount, .statfs = cramfs_statfs, diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index bf3901ab174..8d130cc8532 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -254,7 +254,7 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf, blob->size); } -static struct file_operations fops_blob = { +static const struct file_operations fops_blob = { .read = read_file_blob, .open = default_open, }; diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 5f7b5a6025b..643e57b622b 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -91,7 +91,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations devpts_sops = { +static const struct super_operations devpts_sops = { .statfs = simple_statfs, .remount_fs = devpts_remount, }; diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index ca94a837a5b..61ba670b9e0 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c @@ -287,7 +287,7 @@ static int rsb_open(struct inode *inode, struct file *file) return 0; } -static struct file_operations rsb_fops = { +static const struct file_operations rsb_fops = { .owner = THIS_MODULE, .open = rsb_open, .read = seq_read, @@ -331,7 +331,7 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf, return rv; } -static struct file_operations waiters_fops = { +static const struct file_operations waiters_fops = { .owner = THIS_MODULE, .open = waiters_open, .read = waiters_read diff --git a/fs/dlm/user.c b/fs/dlm/user.c index d378b7fe2a1..40db61dc95f 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -25,7 +25,7 @@ static const char *name_prefix="dlm"; static struct miscdevice ctl_device; -static struct file_operations device_fops; +static const struct file_operations device_fops; #ifdef CONFIG_COMPAT @@ -759,7 +759,7 @@ static int ctl_device_close(struct inode *inode, struct file *file) return 0; } -static struct file_operations device_fops = { +static const struct file_operations device_fops = { .open = device_open, .release = device_close, .read = device_read, @@ -768,7 +768,7 @@ static struct file_operations device_fops = { .owner = THIS_MODULE, }; -static struct file_operations ctl_device_fops = { +static const struct file_operations ctl_device_fops = { .open = ctl_device_open, .release = ctl_device_close, .write = device_write, diff --git a/fs/dquot.c b/fs/dquot.c index a561fb29e20..9eb166f9148 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -79,6 +79,7 @@ #include <linux/buffer_head.h> #include <linux/capability.h> #include <linux/quotaops.h> +#include <linux/writeback.h> /* for inode_lock, oddly enough.. */ #include <asm/uaccess.h> @@ -687,23 +688,27 @@ static int dqinit_needed(struct inode *inode, int type) /* This routine is guarded by dqonoff_mutex mutex */ static void add_dquot_ref(struct super_block *sb, int type) { - struct list_head *p; + struct inode *inode; restart: - file_list_lock(); - list_for_each(p, &sb->s_files) { - struct file *filp = list_entry(p, struct file, f_u.fu_list); - struct inode *inode = filp->f_path.dentry->d_inode; - if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { - struct dentry *dentry = dget(filp->f_path.dentry); - file_list_unlock(); - sb->dq_op->initialize(inode, type); - dput(dentry); - /* As we may have blocked we had better restart... */ - goto restart; - } + spin_lock(&inode_lock); + list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { + if (!atomic_read(&inode->i_writecount)) + continue; + if (!dqinit_needed(inode, type)) + continue; + if (inode->i_state & (I_FREEING|I_WILL_FREE)) + continue; + + __iget(inode); + spin_unlock(&inode_lock); + + sb->dq_op->initialize(inode, type); + iput(inode); + /* As we may have blocked we had better restart... */ + goto restart; } - file_list_unlock(); + spin_unlock(&inode_lock); } /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ @@ -755,15 +760,30 @@ static void put_dquot_list(struct list_head *tofree_head) } } +static void remove_dquot_ref(struct super_block *sb, int type, + struct list_head *tofree_head) +{ + struct inode *inode; + + spin_lock(&inode_lock); + list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { + if (!IS_NOQUOTA(inode)) + remove_inode_dquot_ref(inode, type, tofree_head); + } + spin_unlock(&inode_lock); +} + /* Gather all references from inodes and drop them */ static void drop_dquot_ref(struct super_block *sb, int type) { LIST_HEAD(tofree_head); - down_write(&sb_dqopt(sb)->dqptr_sem); - remove_dquot_ref(sb, type, &tofree_head); - up_write(&sb_dqopt(sb)->dqptr_sem); - put_dquot_list(&tofree_head); + if (sb->dq_op) { + down_write(&sb_dqopt(sb)->dqptr_sem); + remove_dquot_ref(sb, type, &tofree_head); + up_write(&sb_dqopt(sb)->dqptr_sem); + put_dquot_list(&tofree_head); + } } static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number) diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile index ca6562451ee..1f1107237ea 100644 --- a/fs/ecryptfs/Makefile +++ b/fs/ecryptfs/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o -ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o debug.o +ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 75bbfae5508..6ac630625b7 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -3,7 +3,7 @@ * * Copyright (C) 1997-2004 Erez Zadok * Copyright (C) 2001-2004 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. + * Copyright (C) 2004-2007 International Business Machines Corp. * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> * Michael C. Thompson <mcthomps@us.ibm.com> * @@ -207,7 +207,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) mutex_init(&crypt_stat->cs_mutex); mutex_init(&crypt_stat->cs_tfm_mutex); mutex_init(&crypt_stat->cs_hash_tfm_mutex); - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED); + crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED; } /** @@ -305,8 +305,7 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, int rc = 0; BUG_ON(!crypt_stat || !crypt_stat->tfm - || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, - ECRYPTFS_STRUCT_INITIALIZED)); + || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)); if (unlikely(ecryptfs_verbosity > 0)) { ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n", crypt_stat->key_size); @@ -429,10 +428,10 @@ static int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx, goto out; } } else { - rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, - lower_inode, - lower_page_idx); - if (rc) { + *lower_page = grab_cache_page(lower_inode->i_mapping, + lower_page_idx); + if (!(*lower_page)) { + rc = -EINVAL; ecryptfs_printk( KERN_ERR, "Error attempting to grab and map " "lower page with index [0x%.16x]; rc = [%d]\n", @@ -485,7 +484,7 @@ int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx) lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host); inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host); crypt_stat = &inode_info->crypt_stat; - if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) { + if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode, ctx->param.lower_file); if (rc) @@ -617,7 +616,7 @@ int ecryptfs_decrypt_page(struct file *file, struct page *page) crypt_stat = &(ecryptfs_inode_to_private( page->mapping->host)->crypt_stat); lower_inode = ecryptfs_inode_to_lower(page->mapping->host); - if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) { + if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { rc = ecryptfs_do_readpage(file, page, page->index); if (rc) ecryptfs_printk(KERN_ERR, "Error attempting to copy " @@ -863,7 +862,10 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat) ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; } else crypt_stat->header_extent_size = PAGE_CACHE_SIZE; - crypt_stat->num_header_extents_at_front = 1; + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) + crypt_stat->num_header_extents_at_front = 0; + else + crypt_stat->num_header_extents_at_front = 1; } /** @@ -879,7 +881,7 @@ int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat) BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE); BUG_ON(crypt_stat->iv_bytes <= 0); - if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID)) { + if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { rc = -EINVAL; ecryptfs_printk(KERN_WARNING, "Session key not valid; " "cannot generate root IV\n"); @@ -896,8 +898,7 @@ int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat) out: if (rc) { memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes); - ECRYPTFS_SET_FLAG(crypt_stat->flags, - ECRYPTFS_SECURITY_WARNING); + crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING; } return rc; } @@ -905,7 +906,7 @@ out: static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) { get_random_bytes(crypt_stat->key, crypt_stat->key_size); - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); + crypt_stat->flags |= ECRYPTFS_KEY_VALID; ecryptfs_compute_root_iv(crypt_stat); if (unlikely(ecryptfs_verbosity > 0)) { ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n"); @@ -915,6 +916,22 @@ static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) } /** + * ecryptfs_copy_mount_wide_flags_to_inode_flags + * + * This function propagates the mount-wide flags to individual inode + * flags. + */ +static void ecryptfs_copy_mount_wide_flags_to_inode_flags( + struct ecryptfs_crypt_stat *crypt_stat, + struct ecryptfs_mount_crypt_stat *mount_crypt_stat) +{ + if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) + crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; + if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) + crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED; +} + +/** * ecryptfs_set_default_crypt_stat_vals * @crypt_stat * @@ -924,10 +941,12 @@ static void ecryptfs_set_default_crypt_stat_vals( struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_mount_crypt_stat *mount_crypt_stat) { + ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, + mount_crypt_stat); ecryptfs_set_default_sizes(crypt_stat); strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER); crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES; - ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); + crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID); crypt_stat->file_version = ECRYPTFS_FILE_VERSION; crypt_stat->mount_crypt_stat = mount_crypt_stat; } @@ -967,8 +986,10 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) if (mount_crypt_stat->global_auth_tok) { ecryptfs_printk(KERN_DEBUG, "Initializing context for new " "file using mount_crypt_stat\n"); - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); + crypt_stat->flags |= ECRYPTFS_ENCRYPTED; + crypt_stat->flags |= ECRYPTFS_KEY_VALID; + ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, + mount_crypt_stat); memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++], mount_crypt_stat->global_auth_tok_sig, ECRYPTFS_SIG_SIZE_HEX); @@ -1001,7 +1022,7 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) * * Returns one if marker found; zero if not found */ -int contains_ecryptfs_marker(char *data) +static int contains_ecryptfs_marker(char *data) { u32 m_1, m_2; @@ -1027,7 +1048,8 @@ struct ecryptfs_flag_map_elem { /* Add support for additional flags by adding elements here. */ static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = { {0x00000001, ECRYPTFS_ENABLE_HMAC}, - {0x00000002, ECRYPTFS_ENCRYPTED} + {0x00000002, ECRYPTFS_ENCRYPTED}, + {0x00000004, ECRYPTFS_METADATA_IN_XATTR} }; /** @@ -1050,11 +1072,9 @@ static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat, for (i = 0; i < ((sizeof(ecryptfs_flag_map) / sizeof(struct ecryptfs_flag_map_elem))); i++) if (flags & ecryptfs_flag_map[i].file_flag) { - ECRYPTFS_SET_FLAG(crypt_stat->flags, - ecryptfs_flag_map[i].local_flag); + crypt_stat->flags |= ecryptfs_flag_map[i].local_flag; } else - ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, - ecryptfs_flag_map[i].local_flag); + crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag); /* Version is in top 8 bits of the 32-bit flag vector */ crypt_stat->file_version = ((flags >> 24) & 0xFF); (*bytes_read) = 4; @@ -1091,8 +1111,7 @@ write_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat, for (i = 0; i < ((sizeof(ecryptfs_flag_map) / sizeof(struct ecryptfs_flag_map_elem))); i++) - if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, - ecryptfs_flag_map[i].local_flag)) + if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag) flags |= ecryptfs_flag_map[i].file_flag; /* Version is in top 8 bits of the 32-bit flag vector */ flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000); @@ -1187,8 +1206,8 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code) * * Returns zero on success; non-zero otherwise */ -int ecryptfs_read_header_region(char *data, struct dentry *dentry, - struct vfsmount *mnt) +static int ecryptfs_read_header_region(char *data, struct dentry *dentry, + struct vfsmount *mnt) { struct file *lower_file; mm_segment_t oldfs; @@ -1217,9 +1236,25 @@ out: return rc; } -static void -write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat, - size_t *written) +int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry, + struct vfsmount *mnt) +{ + int rc; + + rc = ecryptfs_read_header_region(data, dentry, mnt); + if (rc) + goto out; + if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) + rc = -EINVAL; +out: + return rc; +} + + +void +ecryptfs_write_header_metadata(char *virt, + struct ecryptfs_crypt_stat *crypt_stat, + size_t *written) { u32 header_extent_size; u16 num_header_extents_at_front; @@ -1268,9 +1303,9 @@ struct kmem_cache *ecryptfs_header_cache_2; * * Returns zero on success */ -int ecryptfs_write_headers_virt(char *page_virt, - struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry) +static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, + struct ecryptfs_crypt_stat *crypt_stat, + struct dentry *ecryptfs_dentry) { int rc; size_t written; @@ -1281,7 +1316,8 @@ int ecryptfs_write_headers_virt(char *page_virt, offset += written; write_ecryptfs_flags((page_virt + offset), crypt_stat, &written); offset += written; - write_header_metadata((page_virt + offset), crypt_stat, &written); + ecryptfs_write_header_metadata((page_virt + offset), crypt_stat, + &written); offset += written; rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, ecryptfs_dentry, &written, @@ -1289,11 +1325,70 @@ int ecryptfs_write_headers_virt(char *page_virt, if (rc) ecryptfs_printk(KERN_WARNING, "Error generating key packet " "set; rc = [%d]\n", rc); + if (size) { + offset += written; + *size = offset; + } + return rc; +} + +static int ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, + struct file *lower_file, + char *page_virt) +{ + mm_segment_t oldfs; + int current_header_page; + int header_pages; + ssize_t size; + int rc = 0; + + lower_file->f_pos = 0; + oldfs = get_fs(); + set_fs(get_ds()); + size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE, + &lower_file->f_pos); + if (size < 0) { + rc = (int)size; + printk(KERN_ERR "Error attempting to write lower page; " + "rc = [%d]\n", rc); + set_fs(oldfs); + goto out; + } + header_pages = ((crypt_stat->header_extent_size + * crypt_stat->num_header_extents_at_front) + / PAGE_CACHE_SIZE); + memset(page_virt, 0, PAGE_CACHE_SIZE); + current_header_page = 1; + while (current_header_page < header_pages) { + size = vfs_write(lower_file, (char __user *)page_virt, + PAGE_CACHE_SIZE, &lower_file->f_pos); + if (size < 0) { + rc = (int)size; + printk(KERN_ERR "Error attempting to write lower page; " + "rc = [%d]\n", rc); + set_fs(oldfs); + goto out; + } + current_header_page++; + } + set_fs(oldfs); +out: + return rc; +} + +static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, + struct ecryptfs_crypt_stat *crypt_stat, + char *page_virt, size_t size) +{ + int rc; + + rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt, + size, 0); return rc; } /** - * ecryptfs_write_headers + * ecryptfs_write_metadata * @lower_file: The lower file struct, which was returned from dentry_open * * Write the file headers out. This will likely involve a userspace @@ -1304,22 +1399,18 @@ int ecryptfs_write_headers_virt(char *page_virt, * * Returns zero on success; non-zero on error */ -int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, - struct file *lower_file) +int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, + struct file *lower_file) { - mm_segment_t oldfs; struct ecryptfs_crypt_stat *crypt_stat; char *page_virt; - int current_header_page; - int header_pages; + size_t size; int rc = 0; crypt_stat = &ecryptfs_inode_to_private( ecryptfs_dentry->d_inode)->crypt_stat; - if (likely(ECRYPTFS_CHECK_FLAG(crypt_stat->flags, - ECRYPTFS_ENCRYPTED))) { - if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, - ECRYPTFS_KEY_VALID)) { + if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { + if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { ecryptfs_printk(KERN_DEBUG, "Key is " "invalid; bailing out\n"); rc = -EINVAL; @@ -1338,48 +1429,36 @@ int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, rc = -ENOMEM; goto out; } - - rc = ecryptfs_write_headers_virt(page_virt, crypt_stat, - ecryptfs_dentry); + rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat, + ecryptfs_dentry); if (unlikely(rc)) { ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n"); memset(page_virt, 0, PAGE_CACHE_SIZE); goto out_free; } - ecryptfs_printk(KERN_DEBUG, - "Writing key packet set to underlying file\n"); - lower_file->f_pos = 0; - oldfs = get_fs(); - set_fs(get_ds()); - ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->" - "write() w/ header page; lower_file->f_pos = " - "[0x%.16x]\n", lower_file->f_pos); - lower_file->f_op->write(lower_file, (char __user *)page_virt, - PAGE_CACHE_SIZE, &lower_file->f_pos); - header_pages = ((crypt_stat->header_extent_size - * crypt_stat->num_header_extents_at_front) - / PAGE_CACHE_SIZE); - memset(page_virt, 0, PAGE_CACHE_SIZE); - current_header_page = 1; - while (current_header_page < header_pages) { - ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->" - "write() w/ zero'd page; lower_file->f_pos = " - "[0x%.16x]\n", lower_file->f_pos); - lower_file->f_op->write(lower_file, (char __user *)page_virt, - PAGE_CACHE_SIZE, &lower_file->f_pos); - current_header_page++; + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) + rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, + crypt_stat, page_virt, + size); + else + rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file, + page_virt); + if (rc) { + printk(KERN_ERR "Error writing metadata out to lower file; " + "rc = [%d]\n", rc); + goto out_free; } - set_fs(oldfs); - ecryptfs_printk(KERN_DEBUG, - "Done writing key packet set to underlying file.\n"); out_free: kmem_cache_free(ecryptfs_header_cache_0, page_virt); out: return rc; } +#define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0 +#define ECRYPTFS_VALIDATE_HEADER_SIZE 1 static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, - char *virt, int *bytes_read) + char *virt, int *bytes_read, + int validate_header_size) { int rc = 0; u32 header_extent_size; @@ -1394,9 +1473,10 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, crypt_stat->num_header_extents_at_front = (int)num_header_extents_at_front; (*bytes_read) = 6; - if ((crypt_stat->header_extent_size - * crypt_stat->num_header_extents_at_front) - < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) { + if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) + && ((crypt_stat->header_extent_size + * crypt_stat->num_header_extents_at_front) + < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { rc = -EINVAL; ecryptfs_printk(KERN_WARNING, "Invalid header extent size: " "[%d]\n", crypt_stat->header_extent_size); @@ -1427,7 +1507,8 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) */ static int ecryptfs_read_headers_virt(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry) + struct dentry *ecryptfs_dentry, + int validate_header_size) { int rc = 0; int offset; @@ -1461,7 +1542,7 @@ static int ecryptfs_read_headers_virt(char *page_virt, offset += bytes_read; if (crypt_stat->file_version >= 1) { rc = parse_header_metadata(crypt_stat, (page_virt + offset), - &bytes_read); + &bytes_read, validate_header_size); if (rc) { ecryptfs_printk(KERN_WARNING, "Error reading header " "metadata; rc = [%d]\n", rc); @@ -1476,12 +1557,60 @@ out: } /** - * ecryptfs_read_headers + * ecryptfs_read_xattr_region + * + * Attempts to read the crypto metadata from the extended attribute + * region of the lower file. + */ +int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry) +{ + ssize_t size; + int rc = 0; + + size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, + page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); + if (size < 0) { + printk(KERN_DEBUG "Error attempting to read the [%s] " + "xattr from the lower file; return value = [%zd]\n", + ECRYPTFS_XATTR_NAME, size); + rc = -EINVAL; + goto out; + } +out: + return rc; +} + +int ecryptfs_read_and_validate_xattr_region(char *page_virt, + struct dentry *ecryptfs_dentry) +{ + int rc; + + rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry); + if (rc) + goto out; + if (!contains_ecryptfs_marker(page_virt + ECRYPTFS_FILE_SIZE_BYTES)) { + printk(KERN_WARNING "Valid data found in [%s] xattr, but " + "the marker is invalid\n", ECRYPTFS_XATTR_NAME); + rc = -EINVAL; + } +out: + return rc; +} + +/** + * ecryptfs_read_metadata + * + * Common entry point for reading file metadata. From here, we could + * retrieve the header information from the header region of the file, + * the xattr region of the file, or some other repostory that is + * stored separately from the file itself. The current implementation + * supports retrieving the metadata information from the file contents + * and from the xattr region. * * Returns zero if valid headers found and parsed; non-zero otherwise */ -int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, - struct file *lower_file) +int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, + struct file *lower_file) { int rc = 0; char *page_virt = NULL; @@ -1489,7 +1618,12 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, ssize_t bytes_read; struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat = + &ecryptfs_superblock_to_private( + ecryptfs_dentry->d_sb)->mount_crypt_stat; + ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, + mount_crypt_stat); /* Read the first page from the underlying file */ page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER); if (!page_virt) { @@ -1510,11 +1644,36 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, goto out; } rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, - ecryptfs_dentry); + ecryptfs_dentry, + ECRYPTFS_VALIDATE_HEADER_SIZE); if (rc) { - ecryptfs_printk(KERN_DEBUG, "Valid eCryptfs headers not " - "found\n"); - rc = -EINVAL; + rc = ecryptfs_read_xattr_region(page_virt, + ecryptfs_dentry); + if (rc) { + printk(KERN_DEBUG "Valid eCryptfs headers not found in " + "file header region or xattr region\n"); + rc = -EINVAL; + goto out; + } + rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, + ecryptfs_dentry, + ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); + if (rc) { + printk(KERN_DEBUG "Valid eCryptfs headers not found in " + "file xattr region either\n"); + rc = -EINVAL; + } + if (crypt_stat->mount_crypt_stat->flags + & ECRYPTFS_XATTR_METADATA_ENABLED) { + crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; + } else { + printk(KERN_WARNING "Attempt to access file with " + "crypto metadata only in the extended attribute " + "region, but eCryptfs was mounted without " + "xattr support enabled. eCryptfs will not treat " + "this like an encrypted file.\n"); + rc = -EINVAL; + } } out: if (page_virt) { diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c index 61f8e894284..434c7efd80f 100644 --- a/fs/ecryptfs/debug.c +++ b/fs/ecryptfs/debug.c @@ -36,7 +36,7 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok) ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n", auth_tok); - if (ECRYPTFS_CHECK_FLAG(auth_tok->flags, ECRYPTFS_PRIVATE_KEY)) { + if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) { ecryptfs_printk(KERN_DEBUG, " * private key type\n"); ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT " "IN ECRYPTFS VERSION 0.1)\n"); @@ -46,8 +46,8 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok) ECRYPTFS_SALT_SIZE); salt[ECRYPTFS_SALT_SIZE * 2] = '\0'; ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt); - if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags, - ECRYPTFS_PERSISTENT_PASSWORD)) { + if (auth_tok->token.password.flags & + ECRYPTFS_PERSISTENT_PASSWORD) { ecryptfs_printk(KERN_DEBUG, " * persistent\n"); } memcpy(sig, auth_tok->token.password.signature, diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 0f897109759..b3609b7cdf1 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -4,8 +4,10 @@ * * Copyright (C) 1997-2003 Erez Zadok * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. + * Copyright (C) 2004-2007 International Business Machines Corp. * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> + * Trevor S. Highland <trevor.highland@gmail.com> + * Tyler Hicks <tyhicks@ou.edu> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -31,22 +33,25 @@ #include <linux/fs_stack.h> #include <linux/namei.h> #include <linux/scatterlist.h> +#include <linux/hash.h> /* Version verification for shared data structures w/ userspace */ #define ECRYPTFS_VERSION_MAJOR 0x00 #define ECRYPTFS_VERSION_MINOR 0x04 -#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x01 +#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x02 /* These flags indicate which features are supported by the kernel * module; userspace tools such as the mount helper read * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine * how to behave. */ -#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001 -#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002 +#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001 +#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002 #define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004 -#define ECRYPTFS_VERSIONING_POLICY 0x00000008 +#define ECRYPTFS_VERSIONING_POLICY 0x00000008 +#define ECRYPTFS_VERSIONING_XATTR 0x00000010 #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ - | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH) - + | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \ + | ECRYPTFS_VERSIONING_PUBKEY \ + | ECRYPTFS_VERSIONING_XATTR) #define ECRYPTFS_MAX_PASSWORD_LENGTH 64 #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH #define ECRYPTFS_SALT_SIZE 8 @@ -60,10 +65,25 @@ #define ECRYPTFS_MAX_KEY_BYTES 64 #define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512 #define ECRYPTFS_DEFAULT_IV_BYTES 16 -#define ECRYPTFS_FILE_VERSION 0x01 +#define ECRYPTFS_FILE_VERSION 0x02 #define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192 #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 #define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192 +#define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32 +#define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ +#define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3) +#define ECRYPTFS_NLMSG_HELO 100 +#define ECRYPTFS_NLMSG_QUIT 101 +#define ECRYPTFS_NLMSG_REQUEST 102 +#define ECRYPTFS_NLMSG_RESPONSE 103 +#define ECRYPTFS_MAX_PKI_NAME_BYTES 16 +#define ECRYPTFS_DEFAULT_NUM_USERS 4 +#define ECRYPTFS_MAX_NUM_USERS 32768 +#define ECRYPTFS_TRANSPORT_NETLINK 0 +#define ECRYPTFS_TRANSPORT_CONNECTOR 1 +#define ECRYPTFS_TRANSPORT_RELAYFS 2 +#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK +#define ECRYPTFS_XATTR_NAME "user.ecryptfs" #define RFC2440_CIPHER_DES3_EDE 0x02 #define RFC2440_CIPHER_CAST_5 0x03 @@ -74,9 +94,7 @@ #define RFC2440_CIPHER_TWOFISH 0x0a #define RFC2440_CIPHER_CAST_6 0x0b -#define ECRYPTFS_SET_FLAG(flag_bit_vector, flag) (flag_bit_vector |= (flag)) -#define ECRYPTFS_CLEAR_FLAG(flag_bit_vector, flag) (flag_bit_vector &= ~(flag)) -#define ECRYPTFS_CHECK_FLAG(flag_bit_vector, flag) (flag_bit_vector & (flag)) +#define RFC2440_CIPHER_RSA 0x01 /** * For convenience, we may need to pass around the encrypted session @@ -114,6 +132,14 @@ struct ecryptfs_password { enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY}; +struct ecryptfs_private_key { + u32 key_size; + u32 data_len; + u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; + char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1]; + u8 data[]; +}; + /* May be a password or a private key */ struct ecryptfs_auth_tok { u16 version; /* 8-bit major and 8-bit minor */ @@ -123,7 +149,7 @@ struct ecryptfs_auth_tok { u8 reserved[32]; union { struct ecryptfs_password password; - /* Private key is in future eCryptfs releases */ + struct ecryptfs_private_key private_key; } token; } __attribute__ ((packed)); @@ -177,8 +203,13 @@ ecryptfs_get_key_payload_data(struct key *key) #define ECRYPTFS_DEFAULT_CIPHER "aes" #define ECRYPTFS_DEFAULT_KEY_BYTES 16 #define ECRYPTFS_DEFAULT_HASH "md5" +#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01 #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED +#define ECRYPTFS_TAG_64_PACKET_TYPE 0x40 +#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41 +#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42 +#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43 #define MD5_DIGEST_SIZE 16 /** @@ -195,6 +226,8 @@ struct ecryptfs_crypt_stat { #define ECRYPTFS_ENABLE_HMAC 0x00000020 #define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040 #define ECRYPTFS_KEY_VALID 0x00000080 +#define ECRYPTFS_METADATA_IN_XATTR 0x00000100 +#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200 u32 flags; unsigned int file_version; size_t iv_bytes; @@ -241,6 +274,8 @@ struct ecryptfs_dentry_info { struct ecryptfs_mount_crypt_stat { /* Pointers to memory we do not own, do not free these */ #define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001 +#define ECRYPTFS_XATTR_METADATA_ENABLED 0x00000002 +#define ECRYPTFS_ENCRYPTED_VIEW_ENABLED 0x00000004 u32 flags; struct ecryptfs_auth_tok *global_auth_tok; struct key *global_auth_tok_key; @@ -271,6 +306,33 @@ struct ecryptfs_auth_tok_list_item { struct ecryptfs_auth_tok auth_tok; }; +struct ecryptfs_message { + u32 index; + u32 data_len; + u8 data[]; +}; + +struct ecryptfs_msg_ctx { +#define ECRYPTFS_MSG_CTX_STATE_FREE 0x0001 +#define ECRYPTFS_MSG_CTX_STATE_PENDING 0x0002 +#define ECRYPTFS_MSG_CTX_STATE_DONE 0x0003 + u32 state; + unsigned int index; + unsigned int counter; + struct ecryptfs_message *msg; + struct task_struct *task; + struct list_head node; + struct mutex mux; +}; + +extern unsigned int ecryptfs_transport; + +struct ecryptfs_daemon_id { + pid_t pid; + uid_t uid; + struct hlist_node id_chain; +}; + static inline struct ecryptfs_file_info * ecryptfs_file_to_private(struct file *file) { @@ -384,13 +446,16 @@ void __ecryptfs_printk(const char *fmt, ...); extern const struct file_operations ecryptfs_main_fops; extern const struct file_operations ecryptfs_dir_fops; -extern struct inode_operations ecryptfs_main_iops; -extern struct inode_operations ecryptfs_dir_iops; -extern struct inode_operations ecryptfs_symlink_iops; -extern struct super_operations ecryptfs_sops; +extern const struct inode_operations ecryptfs_main_iops; +extern const struct inode_operations ecryptfs_dir_iops; +extern const struct inode_operations ecryptfs_symlink_iops; +extern const struct super_operations ecryptfs_sops; extern struct dentry_operations ecryptfs_dops; extern struct address_space_operations ecryptfs_aops; extern int ecryptfs_verbosity; +extern unsigned int ecryptfs_message_buf_len; +extern signed long ecryptfs_message_wait_timeout; +extern unsigned int ecryptfs_number_of_users; extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache; extern struct kmem_cache *ecryptfs_file_info_cache; @@ -400,6 +465,7 @@ extern struct kmem_cache *ecryptfs_sb_info_cache; extern struct kmem_cache *ecryptfs_header_cache_0; extern struct kmem_cache *ecryptfs_header_cache_1; extern struct kmem_cache *ecryptfs_header_cache_2; +extern struct kmem_cache *ecryptfs_xattr_cache; extern struct kmem_cache *ecryptfs_lower_page_cache; int ecryptfs_interpose(struct dentry *hidden_dentry, @@ -426,9 +492,13 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, char *cipher_name, char *chaining_modifier); -int ecryptfs_write_inode_size_to_header(struct file *lower_file, - struct inode *lower_inode, - struct inode *inode); +#define ECRYPTFS_LOWER_I_MUTEX_NOT_HELD 0 +#define ECRYPTFS_LOWER_I_MUTEX_HELD 1 +int ecryptfs_write_inode_size_to_metadata(struct file *lower_file, + struct inode *lower_inode, + struct inode *inode, + struct dentry *ecryptfs_dentry, + int lower_i_mutex_held); int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, struct file *lower_file, unsigned long lower_page_index, int byte_offset, @@ -441,26 +511,20 @@ int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode, struct file *lower_file); int ecryptfs_do_readpage(struct file *file, struct page *page, pgoff_t lower_page_index); -int ecryptfs_grab_and_map_lower_page(struct page **lower_page, - char **lower_virt, - struct inode *lower_inode, - unsigned long lower_page_index); int ecryptfs_writepage_and_release_lower_page(struct page *lower_page, struct inode *lower_inode, struct writeback_control *wbc); int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx); int ecryptfs_decrypt_page(struct file *file, struct page *page); -int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, +int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, + struct file *lower_file); +int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, struct file *lower_file); -int ecryptfs_write_headers_virt(char *page_virt, - struct ecryptfs_crypt_stat *crypt_stat, - struct dentry *ecryptfs_dentry); -int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, - struct file *lower_file); int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); -int contains_ecryptfs_marker(char *data); -int ecryptfs_read_header_region(char *data, struct dentry *dentry, - struct vfsmount *mnt); +int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry, + struct vfsmount *mnt); +int ecryptfs_read_and_validate_xattr_region(char *page_virt, + struct dentry *ecryptfs_dentry); u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat); int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code); void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat); @@ -483,5 +547,37 @@ int ecryptfs_open_lower_file(struct file **lower_file, struct dentry *lower_dentry, struct vfsmount *lower_mnt, int flags); int ecryptfs_close_lower_file(struct file *lower_file); +ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, + size_t size); +int +ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags); +int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry); +int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid); +int ecryptfs_process_quit(uid_t uid, pid_t pid); +int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid, + pid_t pid, u32 seq); +int ecryptfs_send_message(unsigned int transport, char *data, int data_len, + struct ecryptfs_msg_ctx **msg_ctx); +int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, + struct ecryptfs_message **emsg); +int ecryptfs_init_messaging(unsigned int transport); +void ecryptfs_release_messaging(unsigned int transport); + +int ecryptfs_send_netlink(char *data, int data_len, + struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type, + u16 msg_flags, pid_t daemon_pid); +int ecryptfs_init_netlink(void); +void ecryptfs_release_netlink(void); + +int ecryptfs_send_connector(char *data, int data_len, + struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type, + u16 msg_flags, pid_t daemon_pid); +int ecryptfs_init_connector(void); +void ecryptfs_release_connector(void); +void +ecryptfs_write_header_metadata(char *virt, + struct ecryptfs_crypt_stat *crypt_stat, + size_t *written); #endif /* #ifndef ECRYPTFS_KERNEL_H */ diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 779c3477d93..bd969adf70d 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -3,7 +3,7 @@ * * Copyright (C) 1997-2004 Erez Zadok * Copyright (C) 2001-2004 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. + * Copyright (C) 2004-2007 International Business Machines Corp. * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> * Michael C. Thompson <mcthomps@us.ibm.com> * @@ -250,6 +250,17 @@ static int ecryptfs_open(struct inode *inode, struct file *file) struct ecryptfs_file_info *file_info; int lower_flags; + mount_crypt_stat = &ecryptfs_superblock_to_private( + ecryptfs_dentry->d_sb)->mount_crypt_stat; + if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) + && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) + || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) + || (file->f_flags & O_APPEND))) { + printk(KERN_WARNING "Mount has encrypted view enabled; " + "files may only be read\n"); + rc = -EPERM; + goto out; + } /* Released in ecryptfs_release or end of function if failure */ file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); ecryptfs_set_file_private(file, file_info); @@ -261,14 +272,12 @@ static int ecryptfs_open(struct inode *inode, struct file *file) } lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; mutex_lock(&crypt_stat->cs_mutex); - if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) { + if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) { ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); /* Policy code enabled in future release */ - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED); - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); + crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED; + crypt_stat->flags |= ECRYPTFS_ENCRYPTED; } mutex_unlock(&crypt_stat->cs_mutex); lower_flags = file->f_flags; @@ -288,31 +297,14 @@ static int ecryptfs_open(struct inode *inode, struct file *file) lower_inode = lower_dentry->d_inode; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); - ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); + crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); rc = 0; goto out; } mutex_lock(&crypt_stat->cs_mutex); - if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) { - if (!(mount_crypt_stat->flags - & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { - rc = -EIO; - printk(KERN_WARNING "Attempt to read file that is " - "not in a valid eCryptfs format, and plaintext " - "passthrough mode is not enabled; returning " - "-EIO\n"); - mutex_unlock(&crypt_stat->cs_mutex); - goto out_puts; - } - crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); - rc = 0; - mutex_unlock(&crypt_stat->cs_mutex); - goto out; - } else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, - ECRYPTFS_POLICY_APPLIED) - || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, - ECRYPTFS_KEY_VALID)) { - rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file); + if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) + || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { + rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file); if (rc) { ecryptfs_printk(KERN_DEBUG, "Valid headers not found\n"); @@ -326,9 +318,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) mutex_unlock(&crypt_stat->cs_mutex); goto out_puts; } - ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, - ECRYPTFS_ENCRYPTED); rc = 0; + crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); mutex_unlock(&crypt_stat->cs_mutex); goto out; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index d4f02f3e18d..9fa7e0b27a9 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -3,7 +3,7 @@ * * Copyright (C) 1997-2004 Erez Zadok * Copyright (C) 2001-2004 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. + * Copyright (C) 2004-2007 International Business Machines Corp. * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> * Michael C. Thompsion <mcthomps@us.ibm.com> * @@ -161,17 +161,17 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file, ecryptfs_set_file_lower(&fake_file, lower_file); rc = ecryptfs_fill_zeros(&fake_file, 1); if (rc) { - ECRYPTFS_SET_FLAG( - ecryptfs_inode_to_private(inode)->crypt_stat.flags, - ECRYPTFS_SECURITY_WARNING); + ecryptfs_inode_to_private(inode)->crypt_stat.flags |= + ECRYPTFS_SECURITY_WARNING; ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros " "in file; rc = [%d]\n", rc); goto out; } i_size_write(inode, 0); - ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); - ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags, - ECRYPTFS_NEW_FILE); + ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode, + ecryptfs_dentry, + ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); + ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE; out: return rc; } @@ -199,7 +199,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) lower_dentry->d_name.name); inode = ecryptfs_dentry->d_inode; crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; + lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR; #if BITS_PER_LONG != 32 lower_flags |= O_LARGEFILE; #endif @@ -214,10 +214,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) lower_inode = lower_dentry->d_inode; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); - ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); + crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); goto out_fput; } - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE); + crypt_stat->flags |= ECRYPTFS_NEW_FILE; ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); rc = ecryptfs_new_file_context(ecryptfs_dentry); if (rc) { @@ -225,7 +225,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) "context\n"); goto out_fput; } - rc = ecryptfs_write_headers(ecryptfs_dentry, lower_file); + rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file); if (rc) { ecryptfs_printk(KERN_DEBUG, "Error writing headers\n"); goto out_fput; @@ -287,6 +287,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, char *encoded_name; unsigned int encoded_namelen; struct ecryptfs_crypt_stat *crypt_stat = NULL; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; char *page_virt = NULL; struct inode *lower_inode; u64 file_size; @@ -362,32 +363,43 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, } /* Released in this function */ page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, - GFP_USER); + GFP_USER); if (!page_virt) { rc = -ENOMEM; ecryptfs_printk(KERN_ERR, "Cannot ecryptfs_kmalloc a page\n"); goto out_dput; } - - rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; - if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) + if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) ecryptfs_set_default_sizes(crypt_stat); + rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry, + nd->mnt); if (rc) { - rc = 0; - ecryptfs_printk(KERN_WARNING, "Error reading header region;" - " assuming unencrypted\n"); - } else { - if (!contains_ecryptfs_marker(page_virt - + ECRYPTFS_FILE_SIZE_BYTES)) { + rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry); + if (rc) { + printk(KERN_DEBUG "Valid metadata not found in header " + "region or xattr region; treating file as " + "unencrypted\n"); + rc = 0; kmem_cache_free(ecryptfs_header_cache_2, page_virt); goto out; } + crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; + } + mount_crypt_stat = &ecryptfs_superblock_to_private( + dentry->d_sb)->mount_crypt_stat; + if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) + file_size = (crypt_stat->header_extent_size + + i_size_read(lower_dentry->d_inode)); + else + file_size = i_size_read(lower_dentry->d_inode); + } else { memcpy(&file_size, page_virt, sizeof(file_size)); file_size = be64_to_cpu(file_size); - i_size_write(dentry->d_inode, (loff_t)file_size); } + i_size_write(dentry->d_inode, (loff_t)file_size); kmem_cache_free(ecryptfs_header_cache_2, page_virt); goto out; @@ -781,20 +793,26 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) goto out_fput; } i_size_write(inode, new_length); - rc = ecryptfs_write_inode_size_to_header(lower_file, - lower_dentry->d_inode, - inode); + rc = ecryptfs_write_inode_size_to_metadata( + lower_file, lower_dentry->d_inode, inode, dentry, + ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); if (rc) { - ecryptfs_printk(KERN_ERR, - "Problem with ecryptfs_write" - "_inode_size\n"); + printk(KERN_ERR "Problem with " + "ecryptfs_write_inode_size_to_metadata; " + "rc = [%d]\n", rc); goto out_fput; } } else { /* new_length < i_size_read(inode) */ vmtruncate(inode, new_length); - ecryptfs_write_inode_size_to_header(lower_file, - lower_dentry->d_inode, - inode); + rc = ecryptfs_write_inode_size_to_metadata( + lower_file, lower_dentry->d_inode, inode, dentry, + ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); + if (rc) { + printk(KERN_ERR "Problem with " + "ecryptfs_write_inode_size_to_metadata; " + "rc = [%d]\n", rc); + goto out_fput; + } /* We are reducing the size of the ecryptfs file, and need to * know if we need to reduce the size of the lower file. */ lower_size_before_truncate = @@ -881,7 +899,7 @@ out: return rc; } -static int +int ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { @@ -901,7 +919,7 @@ out: return rc; } -static ssize_t +ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) { @@ -971,7 +989,7 @@ int ecryptfs_inode_set(struct inode *inode, void *lower_inode) return 0; } -struct inode_operations ecryptfs_symlink_iops = { +const struct inode_operations ecryptfs_symlink_iops = { .readlink = ecryptfs_readlink, .follow_link = ecryptfs_follow_link, .put_link = ecryptfs_put_link, @@ -983,7 +1001,7 @@ struct inode_operations ecryptfs_symlink_iops = { .removexattr = ecryptfs_removexattr }; -struct inode_operations ecryptfs_dir_iops = { +const struct inode_operations ecryptfs_dir_iops = { .create = ecryptfs_create, .lookup = ecryptfs_lookup, .link = ecryptfs_link, @@ -1001,7 +1019,7 @@ struct inode_operations ecryptfs_dir_iops = { .removexattr = ecryptfs_removexattr }; -struct inode_operations ecryptfs_main_iops = { +const struct inode_operations ecryptfs_main_iops = { .permission = ecryptfs_permission, .setattr = ecryptfs_setattr, .setxattr = ecryptfs_setxattr, diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 80bccd5ff8e..c209f67e7a2 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -7,6 +7,7 @@ * Copyright (C) 2004-2006 International Business Machines Corp. * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> * Michael C. Thompson <mcthomps@us.ibm.com> + * Trevor S. Highland <trevor.highland@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -64,26 +65,6 @@ int process_request_key_err(long err_code) return rc; } -static void wipe_auth_tok_list(struct list_head *auth_tok_list_head) -{ - struct list_head *walker; - struct ecryptfs_auth_tok_list_item *auth_tok_list_item; - - walker = auth_tok_list_head->next; - while (walker != auth_tok_list_head) { - auth_tok_list_item = - list_entry(walker, struct ecryptfs_auth_tok_list_item, - list); - walker = auth_tok_list_item->list.next; - memset(auth_tok_list_item, 0, - sizeof(struct ecryptfs_auth_tok_list_item)); - kmem_cache_free(ecryptfs_auth_tok_list_item_cache, - auth_tok_list_item); - } -} - -struct kmem_cache *ecryptfs_auth_tok_list_item_cache; - /** * parse_packet_length * @data: Pointer to memory containing length at offset @@ -102,12 +83,12 @@ static int parse_packet_length(unsigned char *data, size_t *size, (*size) = 0; if (data[0] < 192) { /* One-byte length */ - (*size) = data[0]; + (*size) = (unsigned char)data[0]; (*length_size) = 1; } else if (data[0] < 224) { /* Two-byte length */ - (*size) = ((data[0] - 192) * 256); - (*size) += (data[1] + 192); + (*size) = (((unsigned char)(data[0]) - 192) * 256); + (*size) += ((unsigned char)(data[1]) + 192); (*length_size) = 2; } else if (data[0] == 255) { /* Five-byte length; we're not supposed to see this */ @@ -154,6 +135,499 @@ static int write_packet_length(char *dest, size_t size, return rc; } +static int +write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key, + char **packet, size_t *packet_len) +{ + size_t i = 0; + size_t data_len; + size_t packet_size_len; + char *message; + int rc; + + /* + * ***** TAG 64 Packet Format ***** + * | Content Type | 1 byte | + * | Key Identifier Size | 1 or 2 bytes | + * | Key Identifier | arbitrary | + * | Encrypted File Encryption Key Size | 1 or 2 bytes | + * | Encrypted File Encryption Key | arbitrary | + */ + data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + + session_key->encrypted_key_size); + *packet = kmalloc(data_len, GFP_KERNEL); + message = *packet; + if (!message) { + ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); + rc = -ENOMEM; + goto out; + } + message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE; + rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, + &packet_size_len); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " + "header; cannot generate packet length\n"); + goto out; + } + i += packet_size_len; + memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); + i += ECRYPTFS_SIG_SIZE_HEX; + rc = write_packet_length(&message[i], session_key->encrypted_key_size, + &packet_size_len); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " + "header; cannot generate packet length\n"); + goto out; + } + i += packet_size_len; + memcpy(&message[i], session_key->encrypted_key, + session_key->encrypted_key_size); + i += session_key->encrypted_key_size; + *packet_len = i; +out: + return rc; +} + +static int +parse_tag_65_packet(struct ecryptfs_session_key *session_key, u16 *cipher_code, + struct ecryptfs_message *msg) +{ + size_t i = 0; + char *data; + size_t data_len; + size_t m_size; + size_t message_len; + u16 checksum = 0; + u16 expected_checksum = 0; + int rc; + + /* + * ***** TAG 65 Packet Format ***** + * | Content Type | 1 byte | + * | Status Indicator | 1 byte | + * | File Encryption Key Size | 1 or 2 bytes | + * | File Encryption Key | arbitrary | + */ + message_len = msg->data_len; + data = msg->data; + if (message_len < 4) { + rc = -EIO; + goto out; + } + if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) { + ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n"); + rc = -EIO; + goto out; + } + if (data[i++]) { + ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value " + "[%d]\n", data[i-1]); + rc = -EIO; + goto out; + } + rc = parse_packet_length(&data[i], &m_size, &data_len); + if (rc) { + ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " + "rc = [%d]\n", rc); + goto out; + } + i += data_len; + if (message_len < (i + m_size)) { + ecryptfs_printk(KERN_ERR, "The received netlink message is " + "shorter than expected\n"); + rc = -EIO; + goto out; + } + if (m_size < 3) { + ecryptfs_printk(KERN_ERR, + "The decrypted key is not long enough to " + "include a cipher code and checksum\n"); + rc = -EIO; + goto out; + } + *cipher_code = data[i++]; + /* The decrypted key includes 1 byte cipher code and 2 byte checksum */ + session_key->decrypted_key_size = m_size - 3; + if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) { + ecryptfs_printk(KERN_ERR, "key_size [%d] larger than " + "the maximum key size [%d]\n", + session_key->decrypted_key_size, + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); + rc = -EIO; + goto out; + } + memcpy(session_key->decrypted_key, &data[i], + session_key->decrypted_key_size); + i += session_key->decrypted_key_size; + expected_checksum += (unsigned char)(data[i++]) << 8; + expected_checksum += (unsigned char)(data[i++]); + for (i = 0; i < session_key->decrypted_key_size; i++) + checksum += session_key->decrypted_key[i]; + if (expected_checksum != checksum) { + ecryptfs_printk(KERN_ERR, "Invalid checksum for file " + "encryption key; expected [%x]; calculated " + "[%x]\n", expected_checksum, checksum); + rc = -EIO; + } +out: + return rc; +} + + +static int +write_tag_66_packet(char *signature, size_t cipher_code, + struct ecryptfs_crypt_stat *crypt_stat, char **packet, + size_t *packet_len) +{ + size_t i = 0; + size_t j; + size_t data_len; + size_t checksum = 0; + size_t packet_size_len; + char *message; + int rc; + + /* + * ***** TAG 66 Packet Format ***** + * | Content Type | 1 byte | + * | Key Identifier Size | 1 or 2 bytes | + * | Key Identifier | arbitrary | + * | File Encryption Key Size | 1 or 2 bytes | + * | File Encryption Key | arbitrary | + */ + data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); + *packet = kmalloc(data_len, GFP_KERNEL); + message = *packet; + if (!message) { + ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); + rc = -ENOMEM; + goto out; + } + message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE; + rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, + &packet_size_len); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " + "header; cannot generate packet length\n"); + goto out; + } + i += packet_size_len; + memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); + i += ECRYPTFS_SIG_SIZE_HEX; + /* The encrypted key includes 1 byte cipher code and 2 byte checksum */ + rc = write_packet_length(&message[i], crypt_stat->key_size + 3, + &packet_size_len); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " + "header; cannot generate packet length\n"); + goto out; + } + i += packet_size_len; + message[i++] = cipher_code; + memcpy(&message[i], crypt_stat->key, crypt_stat->key_size); + i += crypt_stat->key_size; + for (j = 0; j < crypt_stat->key_size; j++) + checksum += crypt_stat->key[j]; + message[i++] = (checksum / 256) % 256; + message[i++] = (checksum % 256); + *packet_len = i; +out: + return rc; +} + +static int +parse_tag_67_packet(struct ecryptfs_key_record *key_rec, + struct ecryptfs_message *msg) +{ + size_t i = 0; + char *data; + size_t data_len; + size_t message_len; + int rc; + + /* + * ***** TAG 65 Packet Format ***** + * | Content Type | 1 byte | + * | Status Indicator | 1 byte | + * | Encrypted File Encryption Key Size | 1 or 2 bytes | + * | Encrypted File Encryption Key | arbitrary | + */ + message_len = msg->data_len; + data = msg->data; + /* verify that everything through the encrypted FEK size is present */ + if (message_len < 4) { + rc = -EIO; + goto out; + } + if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) { + ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_67\n"); + rc = -EIO; + goto out; + } + if (data[i++]) { + ecryptfs_printk(KERN_ERR, "Status indicator has non zero value" + " [%d]\n", data[i-1]); + rc = -EIO; + goto out; + } + rc = parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len); + if (rc) { + ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " + "rc = [%d]\n", rc); + goto out; + } + i += data_len; + if (message_len < (i + key_rec->enc_key_size)) { + ecryptfs_printk(KERN_ERR, "message_len [%d]; max len is [%d]\n", + message_len, (i + key_rec->enc_key_size)); + rc = -EIO; + goto out; + } + if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { + ecryptfs_printk(KERN_ERR, "Encrypted key_size [%d] larger than " + "the maximum key size [%d]\n", + key_rec->enc_key_size, + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); + rc = -EIO; + goto out; + } + memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size); +out: + return rc; +} + +/** + * decrypt_pki_encrypted_session_key - Decrypt the session key with + * the given auth_tok. + * + * Returns Zero on success; non-zero error otherwise. + */ +static int decrypt_pki_encrypted_session_key( + struct ecryptfs_mount_crypt_stat *mount_crypt_stat, + struct ecryptfs_auth_tok *auth_tok, + struct ecryptfs_crypt_stat *crypt_stat) +{ + u16 cipher_code = 0; + struct ecryptfs_msg_ctx *msg_ctx; + struct ecryptfs_message *msg = NULL; + char *netlink_message; + size_t netlink_message_length; + int rc; + + rc = write_tag_64_packet(mount_crypt_stat->global_auth_tok_sig, + &(auth_tok->session_key), + &netlink_message, &netlink_message_length); + if (rc) { + ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet"); + goto out; + } + rc = ecryptfs_send_message(ecryptfs_transport, netlink_message, + netlink_message_length, &msg_ctx); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error sending netlink message\n"); + goto out; + } + rc = ecryptfs_wait_for_response(msg_ctx, &msg); + if (rc) { + ecryptfs_printk(KERN_ERR, "Failed to receive tag 65 packet " + "from the user space daemon\n"); + rc = -EIO; + goto out; + } + rc = parse_tag_65_packet(&(auth_tok->session_key), + &cipher_code, msg); + if (rc) { + printk(KERN_ERR "Failed to parse tag 65 packet; rc = [%d]\n", + rc); + goto out; + } + auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY; + memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, + auth_tok->session_key.decrypted_key_size); + crypt_stat->key_size = auth_tok->session_key.decrypted_key_size; + rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code); + if (rc) { + ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n", + cipher_code) + goto out; + } + crypt_stat->flags |= ECRYPTFS_KEY_VALID; + if (ecryptfs_verbosity > 0) { + ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n"); + ecryptfs_dump_hex(crypt_stat->key, + crypt_stat->key_size); + } +out: + if (msg) + kfree(msg); + return rc; +} + +static void wipe_auth_tok_list(struct list_head *auth_tok_list_head) +{ + struct list_head *walker; + struct ecryptfs_auth_tok_list_item *auth_tok_list_item; + + walker = auth_tok_list_head->next; + while (walker != auth_tok_list_head) { + auth_tok_list_item = + list_entry(walker, struct ecryptfs_auth_tok_list_item, + list); + walker = auth_tok_list_item->list.next; + memset(auth_tok_list_item, 0, + sizeof(struct ecryptfs_auth_tok_list_item)); + kmem_cache_free(ecryptfs_auth_tok_list_item_cache, + auth_tok_list_item); + } + auth_tok_list_head->next = NULL; +} + +struct kmem_cache *ecryptfs_auth_tok_list_item_cache; + + +/** + * parse_tag_1_packet + * @crypt_stat: The cryptographic context to modify based on packet + * contents. + * @data: The raw bytes of the packet. + * @auth_tok_list: eCryptfs parses packets into authentication tokens; + * a new authentication token will be placed at the end + * of this list for this packet. + * @new_auth_tok: Pointer to a pointer to memory that this function + * allocates; sets the memory address of the pointer to + * NULL on error. This object is added to the + * auth_tok_list. + * @packet_size: This function writes the size of the parsed packet + * into this memory location; zero on error. + * + * Returns zero on success; non-zero on error. + */ +static int +parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, + unsigned char *data, struct list_head *auth_tok_list, + struct ecryptfs_auth_tok **new_auth_tok, + size_t *packet_size, size_t max_packet_size) +{ + size_t body_size; + struct ecryptfs_auth_tok_list_item *auth_tok_list_item; + size_t length_size; + int rc = 0; + + (*packet_size) = 0; + (*new_auth_tok) = NULL; + + /* we check that: + * one byte for the Tag 1 ID flag + * two bytes for the body size + * do not exceed the maximum_packet_size + */ + if (unlikely((*packet_size) + 3 > max_packet_size)) { + ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); + rc = -EINVAL; + goto out; + } + /* check for Tag 1 identifier - one byte */ + if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) { + ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n", + ECRYPTFS_TAG_1_PACKET_TYPE); + rc = -EINVAL; + goto out; + } + /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or + * at end of function upon failure */ + auth_tok_list_item = + kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache, + GFP_KERNEL); + if (!auth_tok_list_item) { + ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); + rc = -ENOMEM; + goto out; + } + memset(auth_tok_list_item, 0, + sizeof(struct ecryptfs_auth_tok_list_item)); + (*new_auth_tok) = &auth_tok_list_item->auth_tok; + /* check for body size - one to two bytes + * + * ***** TAG 1 Packet Format ***** + * | version number | 1 byte | + * | key ID | 8 bytes | + * | public key algorithm | 1 byte | + * | encrypted session key | arbitrary | + */ + rc = parse_packet_length(&data[(*packet_size)], &body_size, + &length_size); + if (rc) { + ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " + "rc = [%d]\n", rc); + goto out_free; + } + if (unlikely(body_size < (0x02 + ECRYPTFS_SIG_SIZE))) { + ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n", + body_size); + rc = -EINVAL; + goto out_free; + } + (*packet_size) += length_size; + if (unlikely((*packet_size) + body_size > max_packet_size)) { + ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n"); + rc = -EINVAL; + goto out_free; + } + /* Version 3 (from RFC2440) - one byte */ + if (unlikely(data[(*packet_size)++] != 0x03)) { + ecryptfs_printk(KERN_DEBUG, "Unknown version number " + "[%d]\n", data[(*packet_size) - 1]); + rc = -EINVAL; + goto out_free; + } + /* Read Signature */ + ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature, + &data[(*packet_size)], ECRYPTFS_SIG_SIZE); + *packet_size += ECRYPTFS_SIG_SIZE; + /* This byte is skipped because the kernel does not need to + * know which public key encryption algorithm was used */ + (*packet_size)++; + (*new_auth_tok)->session_key.encrypted_key_size = + body_size - (0x02 + ECRYPTFS_SIG_SIZE); + if ((*new_auth_tok)->session_key.encrypted_key_size + > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { + ecryptfs_printk(KERN_ERR, "Tag 1 packet contains key larger " + "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES"); + rc = -EINVAL; + goto out; + } + ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n", + (*new_auth_tok)->session_key.encrypted_key_size); + memcpy((*new_auth_tok)->session_key.encrypted_key, + &data[(*packet_size)], (body_size - 0x02 - ECRYPTFS_SIG_SIZE)); + (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size; + (*new_auth_tok)->session_key.flags &= + ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; + (*new_auth_tok)->session_key.flags |= + ECRYPTFS_CONTAINS_ENCRYPTED_KEY; + (*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY; + (*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY; + /* TODO: Why are we setting this flag here? Don't we want the + * userspace to decrypt the session key? */ + (*new_auth_tok)->session_key.flags &= + ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); + (*new_auth_tok)->session_key.flags &= + ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); + list_add(&auth_tok_list_item->list, auth_tok_list); + goto out; +out_free: + (*new_auth_tok) = NULL; + memset(auth_tok_list_item, 0, + sizeof(struct ecryptfs_auth_tok_list_item)); + kmem_cache_free(ecryptfs_auth_tok_list_item_cache, + auth_tok_list_item); +out: + if (rc) + (*packet_size) = 0; + return rc; +} + /** * parse_tag_3_packet * @crypt_stat: The cryptographic context to modify based on packet @@ -178,10 +652,10 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_auth_tok **new_auth_tok, size_t *packet_size, size_t max_packet_size) { - int rc = 0; size_t body_size; struct ecryptfs_auth_tok_list_item *auth_tok_list_item; size_t length_size; + int rc = 0; (*packet_size) = 0; (*new_auth_tok) = NULL; @@ -319,10 +793,10 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, (*new_auth_tok)->token_type = ECRYPTFS_PASSWORD; /* TODO: Parametarize; we might actually want userspace to * decrypt the session key. */ - ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags, - ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); - ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags, - ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); + (*new_auth_tok)->session_key.flags &= + ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); + (*new_auth_tok)->session_key.flags &= + ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); list_add(&auth_tok_list_item->list, auth_tok_list); goto out; out_free: @@ -358,9 +832,9 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents, size_t max_contents_bytes, size_t *tag_11_contents_size, size_t *packet_size, size_t max_packet_size) { - int rc = 0; size_t body_size; size_t length_size; + int rc = 0; (*packet_size) = 0; (*tag_11_contents_size) = 0; @@ -459,7 +933,6 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_password *password_s_ptr; struct scatterlist src_sg[2], dst_sg[2]; struct mutex *tfm_mutex = NULL; - /* TODO: Use virt_to_scatterlist for these */ char *encrypted_session_key; char *session_key; struct blkcipher_desc desc = { @@ -468,8 +941,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, int rc = 0; password_s_ptr = &auth_tok->token.password; - if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags, - ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)) + if (password_s_ptr->flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) ecryptfs_printk(KERN_DEBUG, "Session key encryption key " "set; skipping key generation\n"); ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])" @@ -551,7 +1023,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY; memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, auth_tok->session_key.decrypted_key_size); - ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID); + crypt_stat->flags |= ECRYPTFS_KEY_VALID; ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n"); if (ecryptfs_verbosity > 0) ecryptfs_dump_hex(crypt_stat->key, @@ -587,7 +1059,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, struct dentry *ecryptfs_dentry) { size_t i = 0; - int rc = 0; size_t found_auth_tok = 0; size_t next_packet_is_auth_tok_packet; char sig[ECRYPTFS_SIG_SIZE_HEX]; @@ -603,6 +1074,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE]; size_t tag_11_contents_size; size_t tag_11_packet_size; + int rc = 0; INIT_LIST_HEAD(&auth_tok_list); /* Parse the header to find as many packets as we can, these will be @@ -654,8 +1126,21 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, sig_tmp_space, tag_11_contents_size); new_auth_tok->token.password.signature[ ECRYPTFS_PASSWORD_SIG_SIZE] = '\0'; - ECRYPTFS_SET_FLAG(crypt_stat->flags, - ECRYPTFS_ENCRYPTED); + crypt_stat->flags |= ECRYPTFS_ENCRYPTED; + break; + case ECRYPTFS_TAG_1_PACKET_TYPE: + rc = parse_tag_1_packet(crypt_stat, + (unsigned char *)&src[i], + &auth_tok_list, &new_auth_tok, + &packet_size, max_packet_size); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error parsing " + "tag 1 packet\n"); + rc = -EIO; + goto out_wipe_list; + } + i += packet_size; + crypt_stat->flags |= ECRYPTFS_ENCRYPTED; break; case ECRYPTFS_TAG_11_PACKET_TYPE: ecryptfs_printk(KERN_WARNING, "Invalid packet set " @@ -704,31 +1189,46 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, goto leave_list; /* TODO: Transfer the common salt into the * crypt_stat salt */ + } else if ((candidate_auth_tok->token_type + == ECRYPTFS_PRIVATE_KEY) + && !strncmp(candidate_auth_tok->token.private_key.signature, + sig, ECRYPTFS_SIG_SIZE_HEX)) { + found_auth_tok = 1; + goto leave_list; } } -leave_list: if (!found_auth_tok) { ecryptfs_printk(KERN_ERR, "Could not find authentication " "token on temporary list for sig [%.*s]\n", ECRYPTFS_SIG_SIZE_HEX, sig); rc = -EIO; goto out_wipe_list; - } else { + } +leave_list: + rc = -ENOTSUPP; + if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { + memcpy(&(candidate_auth_tok->token.private_key), + &(chosen_auth_tok->token.private_key), + sizeof(struct ecryptfs_private_key)); + rc = decrypt_pki_encrypted_session_key(mount_crypt_stat, + candidate_auth_tok, + crypt_stat); + } else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) { memcpy(&(candidate_auth_tok->token.password), &(chosen_auth_tok->token.password), sizeof(struct ecryptfs_password)); rc = decrypt_session_key(candidate_auth_tok, crypt_stat); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error decrypting the " - "session key\n"); - goto out_wipe_list; - } - rc = ecryptfs_compute_root_iv(crypt_stat); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error computing " - "the root IV\n"); - goto out_wipe_list; - } + } + if (rc) { + ecryptfs_printk(KERN_ERR, "Error decrypting the " + "session key; rc = [%d]\n", rc); + goto out_wipe_list; + } + rc = ecryptfs_compute_root_iv(crypt_stat); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error computing " + "the root IV\n"); + goto out_wipe_list; } rc = ecryptfs_init_crypt_ctx(crypt_stat); if (rc) { @@ -741,6 +1241,145 @@ out_wipe_list: out: return rc; } +static int +pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok, + struct ecryptfs_crypt_stat *crypt_stat, + struct ecryptfs_key_record *key_rec) +{ + struct ecryptfs_msg_ctx *msg_ctx = NULL; + char *netlink_payload; + size_t netlink_payload_length; + struct ecryptfs_message *msg; + int rc; + + rc = write_tag_66_packet(auth_tok->token.private_key.signature, + ecryptfs_code_for_cipher_string(crypt_stat), + crypt_stat, &netlink_payload, + &netlink_payload_length); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n"); + goto out; + } + rc = ecryptfs_send_message(ecryptfs_transport, netlink_payload, + netlink_payload_length, &msg_ctx); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error sending netlink message\n"); + goto out; + } + rc = ecryptfs_wait_for_response(msg_ctx, &msg); + if (rc) { + ecryptfs_printk(KERN_ERR, "Failed to receive tag 67 packet " + "from the user space daemon\n"); + rc = -EIO; + goto out; + } + rc = parse_tag_67_packet(key_rec, msg); + if (rc) + ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n"); + kfree(msg); +out: + if (netlink_payload) + kfree(netlink_payload); + return rc; +} +/** + * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet + * @dest: Buffer into which to write the packet + * @max: Maximum number of bytes that can be writtn + * @packet_size: This function will write the number of bytes that end + * up constituting the packet; set to zero on error + * + * Returns zero on success; non-zero on error. + */ +static int +write_tag_1_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, + struct ecryptfs_crypt_stat *crypt_stat, + struct ecryptfs_mount_crypt_stat *mount_crypt_stat, + struct ecryptfs_key_record *key_rec, size_t *packet_size) +{ + size_t i; + size_t encrypted_session_key_valid = 0; + size_t key_rec_size; + size_t packet_size_length; + int rc = 0; + + (*packet_size) = 0; + ecryptfs_from_hex(key_rec->sig, auth_tok->token.private_key.signature, + ECRYPTFS_SIG_SIZE); + encrypted_session_key_valid = 0; + for (i = 0; i < crypt_stat->key_size; i++) + encrypted_session_key_valid |= + auth_tok->session_key.encrypted_key[i]; + if (encrypted_session_key_valid) { + memcpy(key_rec->enc_key, + auth_tok->session_key.encrypted_key, + auth_tok->session_key.encrypted_key_size); + goto encrypted_session_key_set; + } + if (auth_tok->session_key.encrypted_key_size == 0) + auth_tok->session_key.encrypted_key_size = + auth_tok->token.private_key.key_size; + rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec); + if (rc) { + ecryptfs_printk(KERN_ERR, "Failed to encrypt session key " + "via a pki"); + goto out; + } + if (ecryptfs_verbosity > 0) { + ecryptfs_printk(KERN_DEBUG, "Encrypted key:\n"); + ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size); + } +encrypted_session_key_set: + /* Now we have a valid key_rec. Append it to the + * key_rec set. */ + key_rec_size = (sizeof(struct ecryptfs_key_record) + - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES + + (key_rec->enc_key_size)); + /* TODO: Include a packet size limit as a parameter to this + * function once we have multi-packet headers (for versions + * later than 0.1 */ + if (key_rec_size >= ECRYPTFS_MAX_KEYSET_SIZE) { + ecryptfs_printk(KERN_ERR, "Keyset too large\n"); + rc = -EINVAL; + goto out; + } + /* ***** TAG 1 Packet Format ***** + * | version number | 1 byte | + * | key ID | 8 bytes | + * | public key algorithm | 1 byte | + * | encrypted session key | arbitrary | + */ + if ((0x02 + ECRYPTFS_SIG_SIZE + key_rec->enc_key_size) >= max) { + ecryptfs_printk(KERN_ERR, + "Authentication token is too large\n"); + rc = -EINVAL; + goto out; + } + dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE; + /* This format is inspired by OpenPGP; see RFC 2440 + * packet tag 1 */ + rc = write_packet_length(&dest[(*packet_size)], + (0x02 + ECRYPTFS_SIG_SIZE + + key_rec->enc_key_size), + &packet_size_length); + if (rc) { + ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet " + "header; cannot generate packet length\n"); + goto out; + } + (*packet_size) += packet_size_length; + dest[(*packet_size)++] = 0x03; /* version 3 */ + memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE); + (*packet_size) += ECRYPTFS_SIG_SIZE; + dest[(*packet_size)++] = RFC2440_CIPHER_RSA; + memcpy(&dest[(*packet_size)], key_rec->enc_key, + key_rec->enc_key_size); + (*packet_size) += key_rec->enc_key_size; +out: + if (rc) + (*packet_size) = 0; + return rc; +} /** * write_tag_11_packet @@ -756,8 +1395,8 @@ static int write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length, size_t *packet_length) { - int rc = 0; size_t packet_size_length; + int rc = 0; (*packet_length) = 0; if ((13 + contents_length) > max) { @@ -815,7 +1454,6 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_key_record *key_rec, size_t *packet_size) { size_t i; - size_t signature_is_valid = 0; size_t encrypted_session_key_valid = 0; char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; struct scatterlist dest_sg[2]; @@ -831,19 +1469,14 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, int rc = 0; (*packet_size) = 0; - /* Check for a valid signature on the auth_tok */ - for (i = 0; i < ECRYPTFS_SIG_SIZE_HEX; i++) - signature_is_valid |= auth_tok->token.password.signature[i]; - if (!signature_is_valid) - BUG(); - ecryptfs_from_hex((*key_rec).sig, auth_tok->token.password.signature, + ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature, ECRYPTFS_SIG_SIZE); encrypted_session_key_valid = 0; for (i = 0; i < crypt_stat->key_size; i++) encrypted_session_key_valid |= auth_tok->session_key.encrypted_key[i]; if (encrypted_session_key_valid) { - memcpy((*key_rec).enc_key, + memcpy(key_rec->enc_key, auth_tok->session_key.encrypted_key, auth_tok->session_key.encrypted_key_size); goto encrypted_session_key_set; @@ -856,10 +1489,10 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, memset((crypt_stat->key + 24), 0, 8); auth_tok->session_key.encrypted_key_size = 32; } - (*key_rec).enc_key_size = + key_rec->enc_key_size = auth_tok->session_key.encrypted_key_size; - if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags, - ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)) { + if (auth_tok->token.password.flags & + ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) { ecryptfs_printk(KERN_DEBUG, "Using previously generated " "session key encryption key of size [%d]\n", auth_tok->token.password. @@ -877,15 +1510,15 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, ecryptfs_dump_hex(session_key_encryption_key, 16); } rc = virt_to_scatterlist(crypt_stat->key, - (*key_rec).enc_key_size, src_sg, 2); + key_rec->enc_key_size, src_sg, 2); if (!rc) { ecryptfs_printk(KERN_ERR, "Error generating scatterlist " "for crypt_stat session key\n"); rc = -ENOMEM; goto out; } - rc = virt_to_scatterlist((*key_rec).enc_key, - (*key_rec).enc_key_size, dest_sg, 2); + rc = virt_to_scatterlist(key_rec->enc_key, + key_rec->enc_key_size, dest_sg, 2); if (!rc) { ecryptfs_printk(KERN_ERR, "Error generating scatterlist " "for crypt_stat encrypted session key\n"); @@ -941,14 +1574,14 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); if (ecryptfs_verbosity > 0) - ecryptfs_dump_hex((*key_rec).enc_key, - (*key_rec).enc_key_size); + ecryptfs_dump_hex(key_rec->enc_key, + key_rec->enc_key_size); encrypted_session_key_set: /* Now we have a valid key_rec. Append it to the * key_rec set. */ key_rec_size = (sizeof(struct ecryptfs_key_record) - ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES - + ((*key_rec).enc_key_size)); + + (key_rec->enc_key_size)); /* TODO: Include a packet size limit as a parameter to this * function once we have multi-packet headers (for versions * later than 0.1 */ @@ -960,7 +1593,7 @@ encrypted_session_key_set: /* TODO: Packet size limit */ /* We have 5 bytes of surrounding packet data */ if ((0x05 + ECRYPTFS_SALT_SIZE - + (*key_rec).enc_key_size) >= max) { + + key_rec->enc_key_size) >= max) { ecryptfs_printk(KERN_ERR, "Authentication token is too " "large\n"); rc = -EINVAL; @@ -972,7 +1605,7 @@ encrypted_session_key_set: /* ver+cipher+s2k+hash+salt+iter+enc_key */ rc = write_packet_length(&dest[(*packet_size)], (0x05 + ECRYPTFS_SALT_SIZE - + (*key_rec).enc_key_size), + + key_rec->enc_key_size), &packet_size_length); if (rc) { ecryptfs_printk(KERN_ERR, "Error generating tag 3 packet " @@ -995,9 +1628,9 @@ encrypted_session_key_set: ECRYPTFS_SALT_SIZE); (*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */ dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */ - memcpy(&dest[(*packet_size)], (*key_rec).enc_key, - (*key_rec).enc_key_size); - (*packet_size) += (*key_rec).enc_key_size; + memcpy(&dest[(*packet_size)], key_rec->enc_key, + key_rec->enc_key_size); + (*packet_size) += key_rec->enc_key_size; out: if (desc.tfm && !tfm_mutex) crypto_free_blkcipher(desc.tfm); @@ -1027,13 +1660,13 @@ ecryptfs_generate_key_packet_set(char *dest_base, struct dentry *ecryptfs_dentry, size_t *len, size_t max) { - int rc = 0; struct ecryptfs_auth_tok *auth_tok; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private( ecryptfs_dentry->d_sb)->mount_crypt_stat; size_t written; struct ecryptfs_key_record key_rec; + int rc = 0; (*len) = 0; if (mount_crypt_stat->global_auth_tok) { @@ -1060,20 +1693,23 @@ ecryptfs_generate_key_packet_set(char *dest_base, goto out; } (*len) += written; + } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { + rc = write_tag_1_packet(dest_base + (*len), + max, auth_tok, + crypt_stat,mount_crypt_stat, + &key_rec, &written); + if (rc) { + ecryptfs_printk(KERN_WARNING, "Error " + "writing tag 1 packet\n"); + goto out; + } + (*len) += written; } else { ecryptfs_printk(KERN_WARNING, "Unsupported " "authentication token type\n"); rc = -EINVAL; goto out; } - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error writing " - "authentication token packet with sig " - "= [%s]\n", - mount_crypt_stat->global_auth_tok_sig); - rc = -EIO; - goto out; - } } else BUG(); if (likely((max - (*len)) > 0)) { diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index fe41ab1566e..26fe405a576 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -3,9 +3,10 @@ * * Copyright (C) 1997-2003 Erez Zadok * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. + * Copyright (C) 2004-2007 International Business Machines Corp. * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> * Michael C. Thompson <mcthomps@us.ibm.com> + * Tyler Hicks <tyhicks@ou.edu> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -48,6 +49,43 @@ MODULE_PARM_DESC(ecryptfs_verbosity, "Initial verbosity level (0 or 1; defaults to " "0, which is Quiet)"); +/** + * Module parameter that defines the number of netlink message buffer + * elements + */ +unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS; + +module_param(ecryptfs_message_buf_len, uint, 0); +MODULE_PARM_DESC(ecryptfs_message_buf_len, + "Number of message buffer elements"); + +/** + * Module parameter that defines the maximum guaranteed amount of time to wait + * for a response through netlink. The actual sleep time will be, more than + * likely, a small amount greater than this specified value, but only less if + * the netlink message successfully arrives. + */ +signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ; + +module_param(ecryptfs_message_wait_timeout, long, 0); +MODULE_PARM_DESC(ecryptfs_message_wait_timeout, + "Maximum number of seconds that an operation will " + "sleep while waiting for a message response from " + "userspace"); + +/** + * Module parameter that is an estimate of the maximum number of users + * that will be concurrently using eCryptfs. Set this to the right + * value to balance performance and memory use. + */ +unsigned int ecryptfs_number_of_users = ECRYPTFS_DEFAULT_NUM_USERS; + +module_param(ecryptfs_number_of_users, uint, 0); +MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of " + "concurrent users of eCryptfs"); + +unsigned int ecryptfs_transport = ECRYPTFS_DEFAULT_TRANSPORT; + void __ecryptfs_printk(const char *fmt, ...) { va_list args; @@ -124,7 +162,8 @@ out: enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug, ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes, - ecryptfs_opt_passthrough, ecryptfs_opt_err }; + ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata, + ecryptfs_opt_encrypted_view, ecryptfs_opt_err }; static match_table_t tokens = { {ecryptfs_opt_sig, "sig=%s"}, @@ -135,6 +174,8 @@ static match_table_t tokens = { {ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"}, {ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"}, {ecryptfs_opt_passthrough, "ecryptfs_passthrough"}, + {ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"}, + {ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"}, {ecryptfs_opt_err, NULL} }; @@ -275,6 +316,16 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) mount_crypt_stat->flags |= ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED; break; + case ecryptfs_opt_xattr_metadata: + mount_crypt_stat->flags |= + ECRYPTFS_XATTR_METADATA_ENABLED; + break; + case ecryptfs_opt_encrypted_view: + mount_crypt_stat->flags |= + ECRYPTFS_XATTR_METADATA_ENABLED; + mount_crypt_stat->flags |= + ECRYPTFS_ENCRYPTED_VIEW_ENABLED; + break; case ecryptfs_opt_err: default: ecryptfs_printk(KERN_WARNING, @@ -347,9 +398,10 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) rc = -EINVAL; goto out; } - if (auth_tok->token_type != ECRYPTFS_PASSWORD) { + if (auth_tok->token_type != ECRYPTFS_PASSWORD + && auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) { ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure " - "returned from key\n"); + "returned from key query\n"); rc = -EINVAL; goto out; } @@ -590,6 +642,11 @@ static struct ecryptfs_cache_info { .size = PAGE_CACHE_SIZE, }, { + .cache = &ecryptfs_xattr_cache, + .name = "ecryptfs_xattr_cache", + .size = PAGE_CACHE_SIZE, + }, + { .cache = &ecryptfs_lower_page_cache, .name = "ecryptfs_lower_page_cache", .size = PAGE_CACHE_SIZE, @@ -695,7 +752,8 @@ static struct ecryptfs_version_str_map_elem { {ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"}, {ECRYPTFS_VERSIONING_PUBKEY, "pubkey"}, {ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"}, - {ECRYPTFS_VERSIONING_POLICY, "policy"} + {ECRYPTFS_VERSIONING_POLICY, "policy"}, + {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"} }; static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff) @@ -794,6 +852,11 @@ static int __init ecryptfs_init(void) ecryptfs_free_kmem_caches(); goto out; } + rc = ecryptfs_init_messaging(ecryptfs_transport); + if (rc) { + ecryptfs_printk(KERN_ERR, "Failure occured while attempting to " + "initialize the eCryptfs netlink socket\n"); + } out: return rc; } @@ -805,6 +868,7 @@ static void __exit ecryptfs_exit(void) sysfs_remove_file(&ecryptfs_subsys.kset.kobj, &sysfs_attr_version_str.attr); subsystem_unregister(&ecryptfs_subsys); + ecryptfs_release_messaging(ecryptfs_transport); unregister_filesystem(&ecryptfs_fs_type); ecryptfs_free_kmem_caches(); } diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c new file mode 100644 index 00000000000..47d7e7b611f --- /dev/null +++ b/fs/ecryptfs/messaging.c @@ -0,0 +1,515 @@ +/** + * eCryptfs: Linux filesystem encryption layer + * + * Copyright (C) 2004-2006 International Business Machines Corp. + * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> + * Tyler Hicks <tyhicks@ou.edu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "ecryptfs_kernel.h" + +static LIST_HEAD(ecryptfs_msg_ctx_free_list); +static LIST_HEAD(ecryptfs_msg_ctx_alloc_list); +static struct mutex ecryptfs_msg_ctx_lists_mux; + +static struct hlist_head *ecryptfs_daemon_id_hash; +static struct mutex ecryptfs_daemon_id_hash_mux; +static int ecryptfs_hash_buckets; +#define ecryptfs_uid_hash(uid) \ + hash_long((unsigned long)uid, ecryptfs_hash_buckets) + +static unsigned int ecryptfs_msg_counter; +static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; + +/** + * ecryptfs_acquire_free_msg_ctx + * @msg_ctx: The context that was acquired from the free list + * + * Acquires a context element from the free list and locks the mutex + * on the context. Returns zero on success; non-zero on error or upon + * failure to acquire a free context element. Be sure to lock the + * list mutex before calling. + */ +static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx) +{ + struct list_head *p; + int rc; + + if (list_empty(&ecryptfs_msg_ctx_free_list)) { + ecryptfs_printk(KERN_WARNING, "The eCryptfs free " + "context list is empty. It may be helpful to " + "specify the ecryptfs_message_buf_len " + "parameter to be greater than the current " + "value of [%d]\n", ecryptfs_message_buf_len); + rc = -ENOMEM; + goto out; + } + list_for_each(p, &ecryptfs_msg_ctx_free_list) { + *msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node); + if (mutex_trylock(&(*msg_ctx)->mux)) { + (*msg_ctx)->task = current; + rc = 0; + goto out; + } + } + rc = -ENOMEM; +out: + return rc; +} + +/** + * ecryptfs_msg_ctx_free_to_alloc + * @msg_ctx: The context to move from the free list to the alloc list + * + * Be sure to lock the list mutex and the context mutex before + * calling. + */ +static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx) +{ + list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list); + msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING; + msg_ctx->counter = ++ecryptfs_msg_counter; +} + +/** + * ecryptfs_msg_ctx_alloc_to_free + * @msg_ctx: The context to move from the alloc list to the free list + * + * Be sure to lock the list mutex and the context mutex before + * calling. + */ +static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) +{ + list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list); + if (msg_ctx->msg) + kfree(msg_ctx->msg); + msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE; +} + +/** + * ecryptfs_find_daemon_id + * @uid: The user id which maps to the desired daemon id + * @id: If return value is zero, points to the desired daemon id + * pointer + * + * Search the hash list for the given user id. Returns zero if the + * user id exists in the list; non-zero otherwise. The daemon id hash + * mutex should be held before calling this function. + */ +static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id) +{ + struct hlist_node *elem; + int rc; + + hlist_for_each_entry(*id, elem, + &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)], + id_chain) { + if ((*id)->uid == uid) { + rc = 0; + goto out; + } + } + rc = -EINVAL; +out: + return rc; +} + +static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type, + pid_t pid) +{ + int rc; + + switch(transport) { + case ECRYPTFS_TRANSPORT_NETLINK: + rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid); + break; + case ECRYPTFS_TRANSPORT_CONNECTOR: + case ECRYPTFS_TRANSPORT_RELAYFS: + default: + rc = -ENOSYS; + } + return rc; +} + +/** + * ecryptfs_process_helo + * @transport: The underlying transport (netlink, etc.) + * @uid: The user ID owner of the message + * @pid: The process ID for the userspace program that sent the + * message + * + * Adds the uid and pid values to the daemon id hash. If a uid + * already has a daemon pid registered, the daemon will be + * unregistered before the new daemon id is put into the hash list. + * Returns zero after adding a new daemon id to the hash list; + * non-zero otherwise. + */ +int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid) +{ + struct ecryptfs_daemon_id *new_id; + struct ecryptfs_daemon_id *old_id; + int rc; + + mutex_lock(&ecryptfs_daemon_id_hash_mux); + new_id = kmalloc(sizeof(*new_id), GFP_KERNEL); + if (!new_id) { + rc = -ENOMEM; + ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable " + "to register daemon [%d] for user\n", pid, uid); + goto unlock; + } + if (!ecryptfs_find_daemon_id(uid, &old_id)) { + printk(KERN_WARNING "Received request from user [%d] " + "to register daemon [%d]; unregistering daemon " + "[%d]\n", uid, pid, old_id->pid); + hlist_del(&old_id->id_chain); + rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT, + old_id->pid); + if (rc) + printk(KERN_WARNING "Failed to send QUIT " + "message to daemon [%d]; rc = [%d]\n", + old_id->pid, rc); + kfree(old_id); + } + new_id->uid = uid; + new_id->pid = pid; + hlist_add_head(&new_id->id_chain, + &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]); + rc = 0; +unlock: + mutex_unlock(&ecryptfs_daemon_id_hash_mux); + return rc; +} + +/** + * ecryptfs_process_quit + * @uid: The user ID owner of the message + * @pid: The process ID for the userspace program that sent the + * message + * + * Deletes the corresponding daemon id for the given uid and pid, if + * it is the registered that is requesting the deletion. Returns zero + * after deleting the desired daemon id; non-zero otherwise. + */ +int ecryptfs_process_quit(uid_t uid, pid_t pid) +{ + struct ecryptfs_daemon_id *id; + int rc; + + mutex_lock(&ecryptfs_daemon_id_hash_mux); + if (ecryptfs_find_daemon_id(uid, &id)) { + rc = -EINVAL; + ecryptfs_printk(KERN_ERR, "Received request from user [%d] to " + "unregister unrecognized daemon [%d]\n", uid, + pid); + goto unlock; + } + if (id->pid != pid) { + rc = -EINVAL; + ecryptfs_printk(KERN_WARNING, "Received request from user [%d] " + "with pid [%d] to unregister daemon [%d]\n", + uid, pid, id->pid); + goto unlock; + } + hlist_del(&id->id_chain); + kfree(id); + rc = 0; +unlock: + mutex_unlock(&ecryptfs_daemon_id_hash_mux); + return rc; +} + +/** + * ecryptfs_process_reponse + * @msg: The ecryptfs message received; the caller should sanity check + * msg->data_len + * @pid: The process ID of the userspace application that sent the + * message + * @seq: The sequence number of the message + * + * Processes a response message after sending a operation request to + * userspace. Returns zero upon delivery to desired context element; + * non-zero upon delivery failure or error. + */ +int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid, + pid_t pid, u32 seq) +{ + struct ecryptfs_daemon_id *id; + struct ecryptfs_msg_ctx *msg_ctx; + int msg_size; + int rc; + + if (msg->index >= ecryptfs_message_buf_len) { + rc = -EINVAL; + ecryptfs_printk(KERN_ERR, "Attempt to reference " + "context buffer at index [%d]; maximum " + "allowable is [%d]\n", msg->index, + (ecryptfs_message_buf_len - 1)); + goto out; + } + msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; + mutex_lock(&msg_ctx->mux); + if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) { + rc = -EBADMSG; + ecryptfs_printk(KERN_WARNING, "User [%d] received a " + "message response from process [%d] but does " + "not have a registered daemon\n", + msg_ctx->task->euid, pid); + goto wake_up; + } + if (msg_ctx->task->euid != uid) { + rc = -EBADMSG; + ecryptfs_printk(KERN_WARNING, "Received message from user " + "[%d]; expected message from user [%d]\n", + uid, msg_ctx->task->euid); + goto unlock; + } + if (id->pid != pid) { + rc = -EBADMSG; + ecryptfs_printk(KERN_ERR, "User [%d] received a " + "message response from an unrecognized " + "process [%d]\n", msg_ctx->task->euid, pid); + goto unlock; + } + if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { + rc = -EINVAL; + ecryptfs_printk(KERN_WARNING, "Desired context element is not " + "pending a response\n"); + goto unlock; + } else if (msg_ctx->counter != seq) { + rc = -EINVAL; + ecryptfs_printk(KERN_WARNING, "Invalid message sequence; " + "expected [%d]; received [%d]\n", + msg_ctx->counter, seq); + goto unlock; + } + msg_size = sizeof(*msg) + msg->data_len; + msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL); + if (!msg_ctx->msg) { + rc = -ENOMEM; + ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); + goto unlock; + } + memcpy(msg_ctx->msg, msg, msg_size); + msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; + rc = 0; +wake_up: + wake_up_process(msg_ctx->task); +unlock: + mutex_unlock(&msg_ctx->mux); +out: + return rc; +} + +/** + * ecryptfs_send_message + * @transport: The transport over which to send the message (i.e., + * netlink) + * @data: The data to send + * @data_len: The length of data + * @msg_ctx: The message context allocated for the send + */ +int ecryptfs_send_message(unsigned int transport, char *data, int data_len, + struct ecryptfs_msg_ctx **msg_ctx) +{ + struct ecryptfs_daemon_id *id; + int rc; + + mutex_lock(&ecryptfs_daemon_id_hash_mux); + if (ecryptfs_find_daemon_id(current->euid, &id)) { + mutex_unlock(&ecryptfs_daemon_id_hash_mux); + rc = -ENOTCONN; + ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon " + "registered\n", current->euid); + goto out; + } + mutex_unlock(&ecryptfs_daemon_id_hash_mux); + mutex_lock(&ecryptfs_msg_ctx_lists_mux); + rc = ecryptfs_acquire_free_msg_ctx(msg_ctx); + if (rc) { + mutex_unlock(&ecryptfs_msg_ctx_lists_mux); + ecryptfs_printk(KERN_WARNING, "Could not claim a free " + "context element\n"); + goto out; + } + ecryptfs_msg_ctx_free_to_alloc(*msg_ctx); + mutex_unlock(&(*msg_ctx)->mux); + mutex_unlock(&ecryptfs_msg_ctx_lists_mux); + switch (transport) { + case ECRYPTFS_TRANSPORT_NETLINK: + rc = ecryptfs_send_netlink(data, data_len, *msg_ctx, + ECRYPTFS_NLMSG_REQUEST, 0, id->pid); + break; + case ECRYPTFS_TRANSPORT_CONNECTOR: + case ECRYPTFS_TRANSPORT_RELAYFS: + default: + rc = -ENOSYS; + } + if (rc) { + printk(KERN_ERR "Error attempting to send message to userspace " + "daemon; rc = [%d]\n", rc); + } +out: + return rc; +} + +/** + * ecryptfs_wait_for_response + * @msg_ctx: The context that was assigned when sending a message + * @msg: The incoming message from userspace; not set if rc != 0 + * + * Sleeps until awaken by ecryptfs_receive_message or until the amount + * of time exceeds ecryptfs_message_wait_timeout. If zero is + * returned, msg will point to a valid message from userspace; a + * non-zero value is returned upon failure to receive a message or an + * error occurs. + */ +int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, + struct ecryptfs_message **msg) +{ + signed long timeout = ecryptfs_message_wait_timeout * HZ; + int rc = 0; + +sleep: + timeout = schedule_timeout_interruptible(timeout); + mutex_lock(&ecryptfs_msg_ctx_lists_mux); + mutex_lock(&msg_ctx->mux); + if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) { + if (timeout) { + mutex_unlock(&msg_ctx->mux); + mutex_unlock(&ecryptfs_msg_ctx_lists_mux); + goto sleep; + } + rc = -ENOMSG; + } else { + *msg = msg_ctx->msg; + msg_ctx->msg = NULL; + } + ecryptfs_msg_ctx_alloc_to_free(msg_ctx); + mutex_unlock(&msg_ctx->mux); + mutex_unlock(&ecryptfs_msg_ctx_lists_mux); + return rc; +} + +int ecryptfs_init_messaging(unsigned int transport) +{ + int i; + int rc = 0; + + if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) { + ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS; + ecryptfs_printk(KERN_WARNING, "Specified number of users is " + "too large, defaulting to [%d] users\n", + ecryptfs_number_of_users); + } + mutex_init(&ecryptfs_daemon_id_hash_mux); + mutex_lock(&ecryptfs_daemon_id_hash_mux); + ecryptfs_hash_buckets = 0; + while (ecryptfs_number_of_users >> ++ecryptfs_hash_buckets); + ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head) + * ecryptfs_hash_buckets, GFP_KERNEL); + if (!ecryptfs_daemon_id_hash) { + rc = -ENOMEM; + ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); + goto out; + } + for (i = 0; i < ecryptfs_hash_buckets; i++) + INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]); + mutex_unlock(&ecryptfs_daemon_id_hash_mux); + + ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx) + * ecryptfs_message_buf_len), GFP_KERNEL); + if (!ecryptfs_msg_ctx_arr) { + rc = -ENOMEM; + ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n"); + goto out; + } + mutex_init(&ecryptfs_msg_ctx_lists_mux); + mutex_lock(&ecryptfs_msg_ctx_lists_mux); + ecryptfs_msg_counter = 0; + for (i = 0; i < ecryptfs_message_buf_len; i++) { + INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node); + mutex_init(&ecryptfs_msg_ctx_arr[i].mux); + mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); + ecryptfs_msg_ctx_arr[i].index = i; + ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE; + ecryptfs_msg_ctx_arr[i].counter = 0; + ecryptfs_msg_ctx_arr[i].task = NULL; + ecryptfs_msg_ctx_arr[i].msg = NULL; + list_add_tail(&ecryptfs_msg_ctx_arr[i].node, + &ecryptfs_msg_ctx_free_list); + mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); + } + mutex_unlock(&ecryptfs_msg_ctx_lists_mux); + switch(transport) { + case ECRYPTFS_TRANSPORT_NETLINK: + rc = ecryptfs_init_netlink(); + if (rc) + ecryptfs_release_messaging(transport); + break; + case ECRYPTFS_TRANSPORT_CONNECTOR: + case ECRYPTFS_TRANSPORT_RELAYFS: + default: + rc = -ENOSYS; + } +out: + return rc; +} + +void ecryptfs_release_messaging(unsigned int transport) +{ + if (ecryptfs_msg_ctx_arr) { + int i; + + mutex_lock(&ecryptfs_msg_ctx_lists_mux); + for (i = 0; i < ecryptfs_message_buf_len; i++) { + mutex_lock(&ecryptfs_msg_ctx_arr[i].mux); + if (ecryptfs_msg_ctx_arr[i].msg) + kfree(ecryptfs_msg_ctx_arr[i].msg); + mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux); + } + kfree(ecryptfs_msg_ctx_arr); + mutex_unlock(&ecryptfs_msg_ctx_lists_mux); + } + if (ecryptfs_daemon_id_hash) { + struct hlist_node *elem; + struct ecryptfs_daemon_id *id; + int i; + + mutex_lock(&ecryptfs_daemon_id_hash_mux); + for (i = 0; i < ecryptfs_hash_buckets; i++) { + hlist_for_each_entry(id, elem, + &ecryptfs_daemon_id_hash[i], + id_chain) { + hlist_del(elem); + kfree(id); + } + } + kfree(ecryptfs_daemon_id_hash); + mutex_unlock(&ecryptfs_daemon_id_hash_mux); + } + switch(transport) { + case ECRYPTFS_TRANSPORT_NETLINK: + ecryptfs_release_netlink(); + break; + case ECRYPTFS_TRANSPORT_CONNECTOR: + case ECRYPTFS_TRANSPORT_RELAYFS: + default: + break; + } + return; +} diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 06843d24f23..3a6f65c3f14 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -6,7 +6,7 @@ * * Copyright (C) 1997-2003 Erez Zadok * Copyright (C) 2001-2003 Stony Brook University - * Copyright (C) 2004-2006 International Business Machines Corp. + * Copyright (C) 2004-2007 International Business Machines Corp. * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> * * This program is free software; you can redistribute it and/or @@ -234,22 +234,13 @@ int ecryptfs_do_readpage(struct file *file, struct page *page, goto out; } wait_on_page_locked(lower_page); - page_data = (char *)kmap(page); - if (!page_data) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Error mapping page\n"); - goto out; - } - lower_page_data = (char *)kmap(lower_page); - if (!lower_page_data) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Error mapping page\n"); - kunmap(page); - goto out; - } + page_data = kmap_atomic(page, KM_USER0); + lower_page_data = kmap_atomic(lower_page, KM_USER1); memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); - kunmap(lower_page); - kunmap(page); + kunmap_atomic(lower_page_data, KM_USER1); + flush_dcache_page(lower_page); + kunmap_atomic(page_data, KM_USER0); + flush_dcache_page(page); rc = 0; out: if (likely(lower_page)) @@ -260,6 +251,33 @@ out: ClearPageUptodate(page); return rc; } +/** + * Header Extent: + * Octets 0-7: Unencrypted file size (big-endian) + * Octets 8-15: eCryptfs special marker + * Octets 16-19: Flags + * Octet 16: File format version number (between 0 and 255) + * Octets 17-18: Reserved + * Octet 19: Bit 1 (lsb): Reserved + * Bit 2: Encrypted? + * Bits 3-8: Reserved + * Octets 20-23: Header extent size (big-endian) + * Octets 24-25: Number of header extents at front of file + * (big-endian) + * Octet 26: Begin RFC 2440 authentication token packet set + */ +static void set_header_info(char *page_virt, + struct ecryptfs_crypt_stat *crypt_stat) +{ + size_t written; + int save_num_header_extents_at_front = + crypt_stat->num_header_extents_at_front; + + crypt_stat->num_header_extents_at_front = 1; + ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written); + crypt_stat->num_header_extents_at_front = + save_num_header_extents_at_front; +} /** * ecryptfs_readpage @@ -279,8 +297,8 @@ static int ecryptfs_readpage(struct file *file, struct page *page) crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) ->crypt_stat; if (!crypt_stat - || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED) - || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) { + || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED) + || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { ecryptfs_printk(KERN_DEBUG, "Passing through unencrypted page\n"); rc = ecryptfs_do_readpage(file, page, page->index); @@ -289,10 +307,51 @@ static int ecryptfs_readpage(struct file *file, struct page *page) "[%d]\n", rc); goto out; } + } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { + int num_pages_in_header_region = + (crypt_stat->header_extent_size + / PAGE_CACHE_SIZE); + + if (page->index < num_pages_in_header_region) { + char *page_virt; + + page_virt = kmap_atomic(page, KM_USER0); + memset(page_virt, 0, PAGE_CACHE_SIZE); + if (page->index == 0) { + rc = ecryptfs_read_xattr_region( + page_virt, file->f_path.dentry); + set_header_info(page_virt, crypt_stat); + } + kunmap_atomic(page_virt, KM_USER0); + flush_dcache_page(page); + if (rc) { + printk(KERN_ERR "Error reading xattr " + "region\n"); + goto out; + } + } else { + rc = ecryptfs_do_readpage( + file, page, + (page->index + - num_pages_in_header_region)); + if (rc) { + printk(KERN_ERR "Error reading page; " + "rc = [%d]\n", rc); + goto out; + } + } + } else { + rc = ecryptfs_do_readpage(file, page, page->index); + if (rc) { + printk(KERN_ERR "Error reading page; rc = " + "[%d]\n", rc); + goto out; + } + } } else { rc = ecryptfs_decrypt_page(file, page); if (rc) { - ecryptfs_printk(KERN_ERR, "Error decrypting page; " "rc = [%d]\n", rc); goto out; @@ -308,30 +367,27 @@ out: return rc; } +/** + * Called with lower inode mutex held. + */ static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) { struct inode *inode = page->mapping->host; int end_byte_in_page; - int rc = 0; char *page_virt; - if ((i_size_read(inode) / PAGE_CACHE_SIZE) == page->index) { - end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; - if (to > end_byte_in_page) - end_byte_in_page = to; - page_virt = kmap(page); - if (!page_virt) { - rc = -ENOMEM; - ecryptfs_printk(KERN_WARNING, - "Could not map page\n"); - goto out; - } - memset((page_virt + end_byte_in_page), 0, - (PAGE_CACHE_SIZE - end_byte_in_page)); - kunmap(page); - } + if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index) + goto out; + end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; + if (to > end_byte_in_page) + end_byte_in_page = to; + page_virt = kmap_atomic(page, KM_USER0); + memset((page_virt + end_byte_in_page), 0, + (PAGE_CACHE_SIZE - end_byte_in_page)); + kunmap_atomic(page_virt, KM_USER0); + flush_dcache_page(page); out: - return rc; + return 0; } static int ecryptfs_prepare_write(struct file *file, struct page *page, @@ -339,7 +395,6 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, { int rc = 0; - kmap(page); if (from == 0 && to == PAGE_CACHE_SIZE) goto out; /* If we are writing a full page, it will be up to date. */ @@ -349,30 +404,6 @@ out: return rc; } -int ecryptfs_grab_and_map_lower_page(struct page **lower_page, - char **lower_virt, - struct inode *lower_inode, - unsigned long lower_page_index) -{ - int rc = 0; - - (*lower_page) = grab_cache_page(lower_inode->i_mapping, - lower_page_index); - if (!(*lower_page)) { - ecryptfs_printk(KERN_ERR, "grab_cache_page for " - "lower_page_index = [0x%.16x] failed\n", - lower_page_index); - rc = -EINVAL; - goto out; - } - if (lower_virt) - (*lower_virt) = kmap((*lower_page)); - else - kmap((*lower_page)); -out: - return rc; -} - int ecryptfs_writepage_and_release_lower_page(struct page *lower_page, struct inode *lower_inode, struct writeback_control *wbc) @@ -391,11 +422,8 @@ out: return rc; } -static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page) +static void ecryptfs_release_lower_page(struct page *lower_page) { - kunmap(lower_page); - ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = " - "[0x%.16x]\n", lower_page->index); unlock_page(lower_page); page_cache_release(lower_page); } @@ -407,10 +435,9 @@ static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page) * * Returns zero on success; non-zero on error. */ -int -ecryptfs_write_inode_size_to_header(struct file *lower_file, - struct inode *lower_inode, - struct inode *inode) +static int ecryptfs_write_inode_size_to_header(struct file *lower_file, + struct inode *lower_inode, + struct inode *inode) { int rc = 0; struct page *header_page; @@ -418,11 +445,11 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file, const struct address_space_operations *lower_a_ops; u64 file_size; - rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt, - lower_inode, 0); - if (rc) { - ecryptfs_printk(KERN_ERR, "grab_cache_page for header page " - "failed\n"); + header_page = grab_cache_page(lower_inode->i_mapping, 0); + if (!header_page) { + ecryptfs_printk(KERN_ERR, "grab_cache_page for " + "lower_page_index 0 failed\n"); + rc = -EINVAL; goto out; } lower_a_ops = lower_inode->i_mapping->a_ops; @@ -430,18 +457,95 @@ ecryptfs_write_inode_size_to_header(struct file *lower_file, file_size = (u64)i_size_read(inode); ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); file_size = cpu_to_be64(file_size); + header_virt = kmap_atomic(header_page, KM_USER0); memcpy(header_virt, &file_size, sizeof(u64)); + kunmap_atomic(header_virt, KM_USER0); + flush_dcache_page(header_page); rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8); if (rc < 0) ecryptfs_printk(KERN_ERR, "Error commiting header page " "write\n"); - ecryptfs_unmap_and_release_lower_page(header_page); + ecryptfs_release_lower_page(header_page); lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; mark_inode_dirty_sync(inode); out: return rc; } +static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode, + struct inode *inode, + struct dentry *ecryptfs_dentry, + int lower_i_mutex_held) +{ + ssize_t size; + void *xattr_virt; + struct dentry *lower_dentry; + u64 file_size; + int rc; + + xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); + if (!xattr_virt) { + printk(KERN_ERR "Out of memory whilst attempting to write " + "inode size to xattr\n"); + rc = -ENOMEM; + goto out; + } + lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); + if (!lower_dentry->d_inode->i_op->getxattr) { + printk(KERN_WARNING + "No support for setting xattr in lower filesystem\n"); + rc = -ENOSYS; + kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); + goto out; + } + if (!lower_i_mutex_held) + mutex_lock(&lower_dentry->d_inode->i_mutex); + size = lower_dentry->d_inode->i_op->getxattr(lower_dentry, + ECRYPTFS_XATTR_NAME, + xattr_virt, + PAGE_CACHE_SIZE); + if (!lower_i_mutex_held) + mutex_unlock(&lower_dentry->d_inode->i_mutex); + if (size < 0) + size = 8; + file_size = (u64)i_size_read(inode); + file_size = cpu_to_be64(file_size); + memcpy(xattr_virt, &file_size, sizeof(u64)); + if (!lower_i_mutex_held) + mutex_lock(&lower_dentry->d_inode->i_mutex); + rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry, + ECRYPTFS_XATTR_NAME, + xattr_virt, size, 0); + if (!lower_i_mutex_held) + mutex_unlock(&lower_dentry->d_inode->i_mutex); + if (rc) + printk(KERN_ERR "Error whilst attempting to write inode size " + "to lower file xattr; rc = [%d]\n", rc); + kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); +out: + return rc; +} + +int +ecryptfs_write_inode_size_to_metadata(struct file *lower_file, + struct inode *lower_inode, + struct inode *inode, + struct dentry *ecryptfs_dentry, + int lower_i_mutex_held) +{ + struct ecryptfs_crypt_stat *crypt_stat; + + crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; + if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) + return ecryptfs_write_inode_size_to_xattr(lower_inode, inode, + ecryptfs_dentry, + lower_i_mutex_held); + else + return ecryptfs_write_inode_size_to_header(lower_file, + lower_inode, + inode); +} + int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, struct file *lower_file, unsigned long lower_page_index, int byte_offset, @@ -449,10 +553,10 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, { int rc = 0; - rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, lower_inode, - lower_page_index); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error attempting to grab and map " + *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index); + if (!(*lower_page)) { + rc = -EINVAL; + ecryptfs_printk(KERN_ERR, "Error attempting to grab " "lower page with index [0x%.16x]\n", lower_page_index); goto out; @@ -468,7 +572,7 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, } out: if (rc && (*lower_page)) { - ecryptfs_unmap_and_release_lower_page(*lower_page); + ecryptfs_release_lower_page(*lower_page); (*lower_page) = NULL; } return rc; @@ -493,7 +597,7 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode, "Error committing write; rc = [%d]\n", rc); } else rc = 0; - ecryptfs_unmap_and_release_lower_page(lower_page); + ecryptfs_release_lower_page(lower_page); return rc; } @@ -528,89 +632,7 @@ out: return rc; } -static int -process_new_file(struct ecryptfs_crypt_stat *crypt_stat, - struct file *file, struct inode *inode) -{ - struct page *header_page; - const struct address_space_operations *lower_a_ops; - struct inode *lower_inode; - struct file *lower_file; - char *header_virt; - int rc = 0; - int current_header_page = 0; - int header_pages; - int more_header_data_to_be_written = 1; - - lower_inode = ecryptfs_inode_to_lower(inode); - lower_file = ecryptfs_file_to_lower(file); - lower_a_ops = lower_inode->i_mapping->a_ops; - header_pages = ((crypt_stat->header_extent_size - * crypt_stat->num_header_extents_at_front) - / PAGE_CACHE_SIZE); - BUG_ON(header_pages < 1); - while (current_header_page < header_pages) { - rc = ecryptfs_grab_and_map_lower_page(&header_page, - &header_virt, - lower_inode, - current_header_page); - if (rc) { - ecryptfs_printk(KERN_ERR, "grab_cache_page for " - "header page [%d] failed; rc = [%d]\n", - current_header_page, rc); - goto out; - } - rc = lower_a_ops->prepare_write(lower_file, header_page, 0, - PAGE_CACHE_SIZE); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error preparing to write " - "header page out; rc = [%d]\n", rc); - goto out; - } - memset(header_virt, 0, PAGE_CACHE_SIZE); - if (more_header_data_to_be_written) { - rc = ecryptfs_write_headers_virt(header_virt, - crypt_stat, - file->f_dentry); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error " - "generating header; rc = " - "[%d]\n", rc); - rc = -EIO; - memset(header_virt, 0, PAGE_CACHE_SIZE); - ecryptfs_unmap_and_release_lower_page( - header_page); - goto out; - } - if (current_header_page == 0) - memset(header_virt, 0, 8); - more_header_data_to_be_written = 0; - } - rc = lower_a_ops->commit_write(lower_file, header_page, 0, - PAGE_CACHE_SIZE); - ecryptfs_unmap_and_release_lower_page(header_page); - if (rc < 0) { - ecryptfs_printk(KERN_ERR, - "Error commiting header page write; " - "rc = [%d]\n", rc); - break; - } - current_header_page++; - } - if (rc >= 0) { - rc = 0; - ecryptfs_printk(KERN_DEBUG, "lower_inode->i_blocks = " - "[0x%.16x]\n", lower_inode->i_blocks); - i_size_write(inode, 0); - lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; - mark_inode_dirty_sync(inode); - } - ecryptfs_printk(KERN_DEBUG, "Clearing ECRYPTFS_NEW_FILE flag in " - "crypt_stat at memory location [%p]\n", crypt_stat); - ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE); -out: - return rc; -} +struct kmem_cache *ecryptfs_xattr_cache; /** * ecryptfs_commit_write @@ -640,15 +662,10 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, mutex_lock(&lower_inode->i_mutex); crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) ->crypt_stat; - if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) { + if (crypt_stat->flags & ECRYPTFS_NEW_FILE) { ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " "crypt_stat at memory location [%p]\n", crypt_stat); - rc = process_new_file(crypt_stat, file, inode); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error processing new " - "file; rc = [%d]\n", rc); - goto out; - } + crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE); } else ecryptfs_printk(KERN_DEBUG, "Not a new file\n"); ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" @@ -670,7 +687,6 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, "index [0x%.16x])\n", page->index); goto out; } - rc = 0; inode->i_blocks = lower_inode->i_blocks; pos = (page->index << PAGE_CACHE_SHIFT) + to; if (pos > i_size_read(inode)) { @@ -678,11 +694,15 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, ecryptfs_printk(KERN_DEBUG, "Expanded file size to " "[0x%.16x]\n", i_size_read(inode)); } - ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); + rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, + inode, file->f_dentry, + ECRYPTFS_LOWER_I_MUTEX_HELD); + if (rc) + printk(KERN_ERR "Error writing inode size to metadata; " + "rc = [%d]\n", rc); lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; mark_inode_dirty_sync(inode); out: - kunmap(page); /* mapped in prior call (prepare_write) */ if (rc < 0) ClearPageUptodate(page); else @@ -707,6 +727,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) { int rc = 0; struct page *tmp_page; + char *tmp_page_virt; tmp_page = ecryptfs_get1page(file, index); if (IS_ERR(tmp_page)) { @@ -715,28 +736,27 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) rc = PTR_ERR(tmp_page); goto out; } - kmap(tmp_page); rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros); if (rc) { ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " "to remainder of page at index [0x%.16x]\n", index); - kunmap(tmp_page); page_cache_release(tmp_page); goto out; } - memset(((char *)page_address(tmp_page) + start), 0, num_zeros); + tmp_page_virt = kmap_atomic(tmp_page, KM_USER0); + memset(((char *)tmp_page_virt + start), 0, num_zeros); + kunmap_atomic(tmp_page_virt, KM_USER0); + flush_dcache_page(tmp_page); rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros); if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error attempting to write zero's " "to remainder of page at index [0x%.16x]\n", index); - kunmap(tmp_page); page_cache_release(tmp_page); goto out; } rc = 0; - kunmap(tmp_page); page_cache_release(tmp_page); out: return rc; diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c new file mode 100644 index 00000000000..e3aa2253c85 --- /dev/null +++ b/fs/ecryptfs/netlink.c @@ -0,0 +1,255 @@ +/** + * eCryptfs: Linux filesystem encryption layer + * + * Copyright (C) 2004-2006 International Business Machines Corp. + * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> + * Tyler Hicks <tyhicks@ou.edu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <net/sock.h> +#include <linux/hash.h> +#include <linux/random.h> +#include "ecryptfs_kernel.h" + +static struct sock *ecryptfs_nl_sock; + +/** + * ecryptfs_send_netlink + * @data: The data to include as the payload + * @data_len: The byte count of the data + * @msg_ctx: The netlink context that will be used to handle the + * response message + * @msg_type: The type of netlink message to send + * @msg_flags: The flags to include in the netlink header + * @daemon_pid: The process id of the daemon to send the message to + * + * Sends the data to the specified daemon pid and uses the netlink + * context element to store the data needed for validation upon + * receiving the response. The data and the netlink context can be + * null if just sending a netlink header is sufficient. Returns zero + * upon sending the message; non-zero upon error. + */ +int ecryptfs_send_netlink(char *data, int data_len, + struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type, + u16 msg_flags, pid_t daemon_pid) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + struct ecryptfs_message *msg; + size_t payload_len; + int rc; + + payload_len = ((data && data_len) ? (sizeof(*msg) + data_len) : 0); + skb = alloc_skb(NLMSG_SPACE(payload_len), GFP_KERNEL); + if (!skb) { + rc = -ENOMEM; + ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n"); + goto out; + } + nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0, + msg_type, payload_len); + nlh->nlmsg_flags = msg_flags; + if (msg_ctx && payload_len) { + msg = (struct ecryptfs_message *)NLMSG_DATA(nlh); + msg->index = msg_ctx->index; + msg->data_len = data_len; + memcpy(msg->data, data, data_len); + } + rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0); + if (rc < 0) { + ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink " + "message; rc = [%d]\n", rc); + goto out; + } + rc = 0; + goto out; +nlmsg_failure: + rc = -EMSGSIZE; + kfree_skb(skb); +out: + return rc; +} + +/** + * ecryptfs_process_nl_reponse + * @skb: The socket buffer containing the netlink message of state + * RESPONSE + * + * Processes a response message after sending a operation request to + * userspace. Attempts to assign the msg to a netlink context element + * at the index specified in the msg. The sk_buff and nlmsghdr must + * be validated before this function. Returns zero upon delivery to + * desired context element; non-zero upon delivery failure or error. + */ +static int ecryptfs_process_nl_response(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = (struct nlmsghdr*)skb->data; + struct ecryptfs_message *msg = NLMSG_DATA(nlh); + int rc; + + if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) { + rc = -EINVAL; + ecryptfs_printk(KERN_ERR, "Received netlink message with " + "incorrectly specified data length\n"); + goto out; + } + rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid, + NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq); + if (rc) + printk(KERN_ERR + "Error processing response message; rc = [%d]\n", rc); +out: + return rc; +} + +/** + * ecryptfs_process_nl_helo + * @skb: The socket buffer containing the nlmsghdr in HELO state + * + * Gets uid and pid of the skb and adds the values to the daemon id + * hash. Returns zero after adding a new daemon id to the hash list; + * non-zero otherwise. + */ +static int ecryptfs_process_nl_helo(struct sk_buff *skb) +{ + int rc; + + rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK, + NETLINK_CREDS(skb)->uid, + NETLINK_CREDS(skb)->pid); + if (rc) + printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc); + return rc; +} + +/** + * ecryptfs_process_nl_quit + * @skb: The socket buffer containing the nlmsghdr in QUIT state + * + * Gets uid and pid of the skb and deletes the corresponding daemon + * id, if it is the registered that is requesting the + * deletion. Returns zero after deleting the desired daemon id; + * non-zero otherwise. + */ +static int ecryptfs_process_nl_quit(struct sk_buff *skb) +{ + int rc; + + rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid, + NETLINK_CREDS(skb)->pid); + if (rc) + printk(KERN_WARNING + "Error processing QUIT message; rc = [%d]\n", rc); + return rc; +} + +/** + * ecryptfs_receive_nl_message + * + * Callback function called by netlink system when a message arrives. + * If the message looks to be valid, then an attempt is made to assign + * it to its desired netlink context element and wake up the process + * that is waiting for a response. + */ +static void ecryptfs_receive_nl_message(struct sock *sk, int len) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + int rc = 0; /* skb_recv_datagram requires this */ + +receive: + skb = skb_recv_datagram(sk, 0, 0, &rc); + if (rc == -EINTR) + goto receive; + else if (rc < 0) { + ecryptfs_printk(KERN_ERR, "Error occurred while " + "receiving eCryptfs netlink message; " + "rc = [%d]\n", rc); + return; + } + nlh = (struct nlmsghdr *)skb->data; + if (!NLMSG_OK(nlh, skb->len)) { + ecryptfs_printk(KERN_ERR, "Received corrupt netlink " + "message\n"); + goto free; + } + switch (nlh->nlmsg_type) { + case ECRYPTFS_NLMSG_RESPONSE: + if (ecryptfs_process_nl_response(skb)) { + ecryptfs_printk(KERN_WARNING, "Failed to " + "deliver netlink response to " + "requesting operation\n"); + } + break; + case ECRYPTFS_NLMSG_HELO: + if (ecryptfs_process_nl_helo(skb)) { + ecryptfs_printk(KERN_WARNING, "Failed to " + "fulfill HELO request\n"); + } + break; + case ECRYPTFS_NLMSG_QUIT: + if (ecryptfs_process_nl_quit(skb)) { + ecryptfs_printk(KERN_WARNING, "Failed to " + "fulfill QUIT request\n"); + } + break; + default: + ecryptfs_printk(KERN_WARNING, "Dropping netlink " + "message of unrecognized type [%d]\n", + nlh->nlmsg_type); + break; + } +free: + kfree_skb(skb); +} + +/** + * ecryptfs_init_netlink + * + * Initializes the daemon id hash list, netlink context array, and + * necessary locks. Returns zero upon success; non-zero upon error. + */ +int ecryptfs_init_netlink(void) +{ + int rc; + + ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0, + ecryptfs_receive_nl_message, + THIS_MODULE); + if (!ecryptfs_nl_sock) { + rc = -EIO; + ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n"); + goto out; + } + ecryptfs_nl_sock->sk_sndtimeo = ECRYPTFS_DEFAULT_SEND_TIMEOUT; + rc = 0; +out: + return rc; +} + +/** + * ecryptfs_release_netlink + * + * Frees all memory used by the netlink context array and releases the + * netlink socket. + */ +void ecryptfs_release_netlink(void) +{ + if (ecryptfs_nl_sock && ecryptfs_nl_sock->sk_socket) + sock_release(ecryptfs_nl_sock->sk_socket); + ecryptfs_nl_sock = NULL; +} diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index eaa5daaf106..7b3f0cc09a6 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -168,7 +168,7 @@ out: return rc; } -struct super_operations ecryptfs_sops = { +const struct super_operations ecryptfs_sops = { .alloc_inode = ecryptfs_alloc_inode, .destroy_inode = ecryptfs_destroy_inode, .drop_inode = generic_delete_inode, diff --git a/fs/efs/dir.c b/fs/efs/dir.c index b46c488eefc..dfb5cb40021 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c @@ -15,7 +15,7 @@ const struct file_operations efs_dir_operations = { .readdir = efs_readdir, }; -struct inode_operations efs_dir_inode_operations = { +const struct inode_operations efs_dir_inode_operations = { .lookup = efs_lookup, }; diff --git a/fs/efs/super.c b/fs/efs/super.c index dfebf21289f..c2235e46edc 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -105,7 +105,7 @@ static int efs_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations efs_superblock_operations = { +static const struct super_operations efs_superblock_operations = { .alloc_inode = efs_alloc_inode, .destroy_inode = efs_destroy_inode, .read_inode = efs_read_inode, diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index c19ac153f56..e2a0ea50af1 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -158,7 +158,7 @@ extern void ext2_write_super (struct super_block *); extern const struct file_operations ext2_dir_operations; /* file.c */ -extern struct inode_operations ext2_file_inode_operations; +extern const struct inode_operations ext2_file_inode_operations; extern const struct file_operations ext2_file_operations; extern const struct file_operations ext2_xip_file_operations; @@ -168,9 +168,9 @@ extern const struct address_space_operations ext2_aops_xip; extern const struct address_space_operations ext2_nobh_aops; /* namei.c */ -extern struct inode_operations ext2_dir_inode_operations; -extern struct inode_operations ext2_special_inode_operations; +extern const struct inode_operations ext2_dir_inode_operations; +extern const struct inode_operations ext2_special_inode_operations; /* symlink.c */ -extern struct inode_operations ext2_fast_symlink_inode_operations; -extern struct inode_operations ext2_symlink_inode_operations; +extern const struct inode_operations ext2_fast_symlink_inode_operations; +extern const struct inode_operations ext2_symlink_inode_operations; diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 2dba473c524..566d4e2d385 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -75,7 +75,7 @@ const struct file_operations ext2_xip_file_operations = { }; #endif -struct inode_operations ext2_file_inode_operations = { +const struct inode_operations ext2_file_inode_operations = { .truncate = ext2_truncate, #ifdef CONFIG_EXT2_FS_XATTR .setxattr = generic_setxattr, diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index e1af5b4cf80..e69beed839a 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -373,7 +373,7 @@ out: return err; } -struct inode_operations ext2_dir_inode_operations = { +const struct inode_operations ext2_dir_inode_operations = { .create = ext2_create, .lookup = ext2_lookup, .link = ext2_link, @@ -393,7 +393,7 @@ struct inode_operations ext2_dir_inode_operations = { .permission = ext2_permission, }; -struct inode_operations ext2_special_inode_operations = { +const struct inode_operations ext2_special_inode_operations = { #ifdef CONFIG_EXT2_FS_XATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, diff --git a/fs/ext2/super.c b/fs/ext2/super.c index daaa243eee9..a046a419d8a 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -231,7 +231,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, siz static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); #endif -static struct super_operations ext2_sops = { +static const struct super_operations ext2_sops = { .alloc_inode = ext2_alloc_inode, .destroy_inode = ext2_destroy_inode, .read_inode = ext2_read_inode, diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 1e67d87cfa9..4e2426e22bb 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -28,7 +28,7 @@ static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations ext2_symlink_inode_operations = { +const struct inode_operations ext2_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, @@ -40,7 +40,7 @@ struct inode_operations ext2_symlink_inode_operations = { #endif }; -struct inode_operations ext2_fast_symlink_inode_operations = { +const struct inode_operations ext2_fast_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = ext2_follow_link, #ifdef CONFIG_EXT2_FS_XATTR diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 881f6365c41..1e6f1386453 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -125,7 +125,7 @@ const struct file_operations ext3_file_operations = { .splice_write = generic_file_splice_write, }; -struct inode_operations ext3_file_inode_operations = { +const struct inode_operations ext3_file_inode_operations = { .truncate = ext3_truncate, .setattr = ext3_setattr, #ifdef CONFIG_EXT3_FS_XATTR diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index a8e89328e66..49159f13cc1 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -2365,7 +2365,7 @@ end_rename: /* * directories can handle most operations... */ -struct inode_operations ext3_dir_inode_operations = { +const struct inode_operations ext3_dir_inode_operations = { .create = ext3_create, .lookup = ext3_lookup, .link = ext3_link, @@ -2385,7 +2385,7 @@ struct inode_operations ext3_dir_inode_operations = { .permission = ext3_permission, }; -struct inode_operations ext3_special_inode_operations = { +const struct inode_operations ext3_special_inode_operations = { .setattr = ext3_setattr, #ifdef CONFIG_EXT3_FS_XATTR .setxattr = generic_setxattr, diff --git a/fs/ext3/super.c b/fs/ext3/super.c index a0623a84a4b..4a4fcd6868c 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -639,7 +639,7 @@ static struct quotactl_ops ext3_qctl_operations = { }; #endif -static struct super_operations ext3_sops = { +static const struct super_operations ext3_sops = { .alloc_inode = ext3_alloc_inode, .destroy_inode = ext3_destroy_inode, .read_inode = ext3_read_inode, diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c index 4f79122cde6..ff7b4ccd898 100644 --- a/fs/ext3/symlink.c +++ b/fs/ext3/symlink.c @@ -30,7 +30,7 @@ static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations ext3_symlink_inode_operations = { +const struct inode_operations ext3_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, @@ -42,7 +42,7 @@ struct inode_operations ext3_symlink_inode_operations = { #endif }; -struct inode_operations ext3_fast_symlink_inode_operations = { +const struct inode_operations ext3_fast_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = ext3_follow_link, #ifdef CONFIG_EXT3_FS_XATTR diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 3bbc24b5878..3c6c1fd2be9 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -125,7 +125,7 @@ const struct file_operations ext4_file_operations = { .splice_write = generic_file_splice_write, }; -struct inode_operations ext4_file_inode_operations = { +const struct inode_operations ext4_file_inode_operations = { .truncate = ext4_truncate, .setattr = ext4_setattr, #ifdef CONFIG_EXT4DEV_FS_XATTR diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 34b3448b40f..e7e1d79a7d7 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2363,7 +2363,7 @@ end_rename: /* * directories can handle most operations... */ -struct inode_operations ext4_dir_inode_operations = { +const struct inode_operations ext4_dir_inode_operations = { .create = ext4_create, .lookup = ext4_lookup, .link = ext4_link, @@ -2383,7 +2383,7 @@ struct inode_operations ext4_dir_inode_operations = { .permission = ext4_permission, }; -struct inode_operations ext4_special_inode_operations = { +const struct inode_operations ext4_special_inode_operations = { .setattr = ext4_setattr, #ifdef CONFIG_EXT4DEV_FS_XATTR .setxattr = generic_setxattr, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index c63a18b574d..61c4718e4a5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -690,7 +690,7 @@ static struct quotactl_ops ext4_qctl_operations = { }; #endif -static struct super_operations ext4_sops = { +static const struct super_operations ext4_sops = { .alloc_inode = ext4_alloc_inode, .destroy_inode = ext4_destroy_inode, .read_inode = ext4_read_inode, diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index fcf527286d7..e6f9da4287c 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c @@ -30,7 +30,7 @@ static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations ext4_symlink_inode_operations = { +const struct inode_operations ext4_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, @@ -42,7 +42,7 @@ struct inode_operations ext4_symlink_inode_operations = { #endif }; -struct inode_operations ext4_fast_symlink_inode_operations = { +const struct inode_operations ext4_fast_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = ext4_follow_link, #ifdef CONFIG_EXT4DEV_FS_XATTR diff --git a/fs/fat/file.c b/fs/fat/file.c index c1237b70c1f..55d3c7461c5 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -312,7 +312,7 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) } EXPORT_SYMBOL_GPL(fat_getattr); -struct inode_operations fat_file_inode_operations = { +const struct inode_operations fat_file_inode_operations = { .truncate = fat_truncate, .setattr = fat_notify_change, .getattr = fat_getattr, diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a9e4688582a..76107354421 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -618,7 +618,7 @@ int fat_sync_inode(struct inode *inode) EXPORT_SYMBOL_GPL(fat_sync_inode); static int fat_show_options(struct seq_file *m, struct vfsmount *mnt); -static struct super_operations fat_sops = { +static const struct super_operations fat_sops = { .alloc_inode = fat_alloc_inode, .destroy_inode = fat_destroy_inode, .write_inode = fat_write_inode, @@ -1151,7 +1151,7 @@ static int fat_read_root(struct inode *inode) * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct super_block *sb, void *data, int silent, - struct inode_operations *fs_dir_inode_ops, int isvfat) + const struct inode_operations *fs_dir_inode_ops, int isvfat) { struct inode *root_inode = NULL; struct buffer_head *bh; diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 1cf1fe8466a..91ccee8723f 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -62,7 +62,7 @@ extern void vxfs_read_inode(struct inode *); extern void vxfs_clear_inode(struct inode *); /* vxfs_lookup.c */ -extern struct inode_operations vxfs_dir_inode_ops; +extern const struct inode_operations vxfs_dir_inode_ops; extern const struct file_operations vxfs_dir_operations; /* vxfs_olt.c */ diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c index 4e25f3fbed8..24b5a775ff9 100644 --- a/fs/freevxfs/vxfs_immed.c +++ b/fs/freevxfs/vxfs_immed.c @@ -48,7 +48,7 @@ static int vxfs_immed_readpage(struct file *, struct page *); * Unliked all other operations we do not go through the pagecache, * but do all work directly on the inode. */ -struct inode_operations vxfs_immed_symlink_iops = { +const struct inode_operations vxfs_immed_symlink_iops = { .readlink = generic_readlink, .follow_link = vxfs_immed_follow_link, }; diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 0b7ae897cb7..098a915fd9a 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -44,7 +44,7 @@ extern const struct address_space_operations vxfs_aops; extern const struct address_space_operations vxfs_immed_aops; -extern struct inode_operations vxfs_immed_symlink_iops; +extern const struct inode_operations vxfs_immed_symlink_iops; struct kmem_cache *vxfs_inode_cachep; diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 3995d7fbeda..bf86e5444ea 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -52,7 +52,7 @@ static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *); static int vxfs_readdir(struct file *, void *, filldir_t); -struct inode_operations vxfs_dir_inode_ops = { +const struct inode_operations vxfs_dir_inode_ops = { .lookup = vxfs_lookup, }; diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index ac28b0835ff..647d600f0bc 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -59,7 +59,7 @@ static void vxfs_put_super(struct super_block *); static int vxfs_statfs(struct dentry *, struct kstatfs *); static int vxfs_remount(struct super_block *, int *, char *); -static struct super_operations vxfs_super_ops = { +static const struct super_operations vxfs_super_ops = { .read_inode = vxfs_read_inode, .clear_inode = vxfs_clear_inode, .put_super = vxfs_put_super, diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 1794305f9ed..105d4a271e0 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -73,7 +73,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, struct fuse_conn *fc, const char *name, int mode, int nlink, - struct inode_operations *iop, + const struct inode_operations *iop, const struct file_operations *fop) { struct dentry *dentry; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 40080477ceb..406bf61ed51 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1242,7 +1242,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name) return err; } -static struct inode_operations fuse_dir_inode_operations = { +static const struct inode_operations fuse_dir_inode_operations = { .lookup = fuse_lookup, .mkdir = fuse_mkdir, .symlink = fuse_symlink, @@ -1270,7 +1270,7 @@ static const struct file_operations fuse_dir_operations = { .fsync = fuse_dir_fsync, }; -static struct inode_operations fuse_common_inode_operations = { +static const struct inode_operations fuse_common_inode_operations = { .setattr = fuse_setattr, .permission = fuse_permission, .getattr = fuse_getattr, @@ -1280,7 +1280,7 @@ static struct inode_operations fuse_common_inode_operations = { .removexattr = fuse_removexattr, }; -static struct inode_operations fuse_symlink_inode_operations = { +static const struct inode_operations fuse_symlink_inode_operations = { .setattr = fuse_setattr, .follow_link = fuse_follow_link, .put_link = fuse_put_link, diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 220255110d7..5ab8e50e780 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -446,7 +446,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode) return fuse_iget(sb, 1, 0, &attr); } -static struct super_operations fuse_super_operations = { +static const struct super_operations fuse_super_operations = { .alloc_inode = fuse_alloc_inode, .destroy_inode = fuse_destroy_inode, .read_inode = fuse_read_inode, diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c index 3799f19b282..1dd4215b83d 100644 --- a/fs/gfs2/locking/dlm/plock.c +++ b/fs/gfs2/locking/dlm/plock.c @@ -264,7 +264,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) return 0; } -static struct file_operations dev_fops = { +static const struct file_operations dev_fops = { .read = dev_read, .write = dev_write, .poll = dev_poll, diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index f40a84807d7..60f47bf2e8e 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -1115,7 +1115,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er); } -struct inode_operations gfs2_file_iops = { +const struct inode_operations gfs2_file_iops = { .permission = gfs2_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, @@ -1125,7 +1125,7 @@ struct inode_operations gfs2_file_iops = { .removexattr = gfs2_removexattr, }; -struct inode_operations gfs2_dev_iops = { +const struct inode_operations gfs2_dev_iops = { .permission = gfs2_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, @@ -1135,7 +1135,7 @@ struct inode_operations gfs2_dev_iops = { .removexattr = gfs2_removexattr, }; -struct inode_operations gfs2_dir_iops = { +const struct inode_operations gfs2_dir_iops = { .create = gfs2_create, .lookup = gfs2_lookup, .link = gfs2_link, @@ -1154,7 +1154,7 @@ struct inode_operations gfs2_dir_iops = { .removexattr = gfs2_removexattr, }; -struct inode_operations gfs2_symlink_iops = { +const struct inode_operations gfs2_symlink_iops = { .readlink = gfs2_readlink, .follow_link = gfs2_follow_link, .permission = gfs2_permission, diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h index b15acb4fd34..34f0caac1a0 100644 --- a/fs/gfs2/ops_inode.h +++ b/fs/gfs2/ops_inode.h @@ -12,9 +12,9 @@ #include <linux/fs.h> -extern struct inode_operations gfs2_file_iops; -extern struct inode_operations gfs2_dir_iops; -extern struct inode_operations gfs2_symlink_iops; -extern struct inode_operations gfs2_dev_iops; +extern const struct inode_operations gfs2_file_iops; +extern const struct inode_operations gfs2_dir_iops; +extern const struct inode_operations gfs2_symlink_iops; +extern const struct inode_operations gfs2_dev_iops; #endif /* __OPS_INODE_DOT_H__ */ diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 47369d01121..b89999d3a76 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -468,7 +468,7 @@ static void gfs2_destroy_inode(struct inode *inode) kmem_cache_free(gfs2_inode_cachep, inode); } -struct super_operations gfs2_super_ops = { +const struct super_operations gfs2_super_ops = { .alloc_inode = gfs2_alloc_inode, .destroy_inode = gfs2_destroy_inode, .write_inode = gfs2_write_inode, diff --git a/fs/gfs2/ops_super.h b/fs/gfs2/ops_super.h index 9de73f042f7..442a274c627 100644 --- a/fs/gfs2/ops_super.h +++ b/fs/gfs2/ops_super.h @@ -12,6 +12,6 @@ #include <linux/fs.h> -extern struct super_operations gfs2_super_ops; +extern const struct super_operations gfs2_super_ops; #endif /* __OPS_SUPER_DOT_H__ */ diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index e2e0358da33..7c69b98a2e4 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c @@ -320,7 +320,7 @@ const struct file_operations hfs_dir_operations = { .release = hfs_dir_release, }; -struct inode_operations hfs_dir_inode_operations = { +const struct inode_operations hfs_dir_inode_operations = { .create = hfs_create, .lookup = hfs_lookup, .unlink = hfs_unlink, diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 735332dfd1b..147374b6f67 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -170,7 +170,7 @@ extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qst /* dir.c */ extern const struct file_operations hfs_dir_operations; -extern struct inode_operations hfs_dir_inode_operations; +extern const struct inode_operations hfs_dir_inode_operations; /* extent.c */ extern int hfs_ext_keycmp(const btree_key *, const btree_key *); diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 5cb7f8fee8d..fafcba59387 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -18,7 +18,7 @@ #include "btree.h" static const struct file_operations hfs_file_operations; -static struct inode_operations hfs_file_inode_operations; +static const struct inode_operations hfs_file_inode_operations; /*================ Variable-like macros ================*/ @@ -612,7 +612,7 @@ static const struct file_operations hfs_file_operations = { .release = hfs_file_release, }; -static struct inode_operations hfs_file_inode_operations = { +static const struct inode_operations hfs_file_inode_operations = { .lookup = hfs_file_lookup, .truncate = hfs_file_truncate, .setattr = hfs_inode_setattr, diff --git a/fs/hfs/super.c b/fs/hfs/super.c index a3698796600..623f509f1d4 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -154,7 +154,7 @@ static void hfs_destroy_inode(struct inode *inode) kmem_cache_free(hfs_inode_cachep, HFS_I(inode)); } -static struct super_operations hfs_super_operations = { +static const struct super_operations hfs_super_operations = { .alloc_inode = hfs_alloc_inode, .destroy_inode = hfs_destroy_inode, .write_inode = hfs_write_inode, diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index e886ac8460d..78137007ccc 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -471,7 +471,7 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, return res; } -struct inode_operations hfsplus_dir_inode_operations = { +const struct inode_operations hfsplus_dir_inode_operations = { .lookup = hfsplus_lookup, .create = hfsplus_create, .link = hfsplus_link, diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 75e8c4d8aac..642012ac337 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -268,10 +268,10 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) return 0; } -extern struct inode_operations hfsplus_dir_inode_operations; +extern const struct inode_operations hfsplus_dir_inode_operations; extern struct file_operations hfsplus_dir_operations; -static struct inode_operations hfsplus_file_inode_operations = { +static const struct inode_operations hfsplus_file_inode_operations = { .lookup = hfsplus_file_lookup, .truncate = hfsplus_file_truncate, .permission = hfsplus_permission, diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 0f513c6bf84..5a282f64c63 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -260,7 +260,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations hfsplus_sops = { +static const struct super_operations hfsplus_sops = { .alloc_inode = hfsplus_alloc_inode, .destroy_inode = hfsplus_destroy_inode, .read_inode = hfsplus_read_inode, diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 69a376f35a6..e965eb11d76 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -52,8 +52,8 @@ static int append = 0; #define HOSTFS_SUPER_MAGIC 0x00c0ffee -static struct inode_operations hostfs_iops; -static struct inode_operations hostfs_dir_iops; +static const struct inode_operations hostfs_iops; +static const struct inode_operations hostfs_dir_iops; static const struct address_space_operations hostfs_link_aops; #ifndef MODULE @@ -309,7 +309,7 @@ static void hostfs_read_inode(struct inode *inode) read_inode(inode); } -static struct super_operations hostfs_sbops = { +static const struct super_operations hostfs_sbops = { .alloc_inode = hostfs_alloc_inode, .drop_inode = generic_delete_inode, .delete_inode = hostfs_delete_inode, @@ -880,7 +880,7 @@ int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry, return(0); } -static struct inode_operations hostfs_iops = { +static const struct inode_operations hostfs_iops = { .create = hostfs_create, .link = hostfs_link, .unlink = hostfs_unlink, @@ -894,7 +894,7 @@ static struct inode_operations hostfs_iops = { .getattr = hostfs_getattr, }; -static struct inode_operations hostfs_dir_iops = { +static const struct inode_operations hostfs_dir_iops = { .create = hostfs_create, .lookup = hostfs_lookup, .link = hostfs_link, diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index fb4c8915010..b4eafc0f1e5 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -132,7 +132,7 @@ const struct file_operations hpfs_file_ops = .sendfile = generic_file_sendfile, }; -struct inode_operations hpfs_file_iops = +const struct inode_operations hpfs_file_iops = { .truncate = hpfs_truncate, .setattr = hpfs_notify_change, diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 1c07aa82d32..42ff60ccf2a 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int); int hpfs_file_fsync(struct file *, struct dentry *, int); extern const struct file_operations hpfs_file_ops; -extern struct inode_operations hpfs_file_iops; +extern const struct inode_operations hpfs_file_iops; extern const struct address_space_operations hpfs_aops; /* inode.c */ @@ -302,7 +302,7 @@ void hpfs_decide_conv(struct inode *, unsigned char *, unsigned); /* namei.c */ -extern struct inode_operations hpfs_dir_iops; +extern const struct inode_operations hpfs_dir_iops; extern const struct address_space_operations hpfs_symlink_aops; static inline struct hpfs_inode_info *hpfs_i(struct inode *inode) diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 2507e7393f3..9953cf9a2f1 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -659,7 +659,7 @@ end1: return err; } -struct inode_operations hpfs_dir_iops = +const struct inode_operations hpfs_dir_iops = { .create = hpfs_create, .lookup = hpfs_lookup, diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index d4abc1a1d56..e0174e33852 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -426,7 +426,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) /* Super operations */ -static struct super_operations hpfs_sops = +static const struct super_operations hpfs_sops = { .alloc_inode = hpfs_alloc_inode, .destroy_inode = hpfs_destroy_inode, diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index afd340a45da..affb7412125 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -43,7 +43,7 @@ static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) #define HPPFS_SUPER_MAGIC 0xb00000ee -static struct super_operations hppfs_sbops; +static const struct super_operations hppfs_sbops; static int is_pid(struct dentry *dentry) { @@ -212,7 +212,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, return(ERR_PTR(err)); } -static struct inode_operations hppfs_file_iops = { +static const struct inode_operations hppfs_file_iops = { }; static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, @@ -649,7 +649,7 @@ static void hppfs_destroy_inode(struct inode *inode) kfree(HPPFS_I(inode)); } -static struct super_operations hppfs_sbops = { +static const struct super_operations hppfs_sbops = { .alloc_inode = hppfs_alloc_inode, .destroy_inode = hppfs_destroy_inode, .read_inode = hppfs_read_inode, @@ -693,11 +693,11 @@ static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) return ret; } -static struct inode_operations hppfs_dir_iops = { +static const struct inode_operations hppfs_dir_iops = { .lookup = hppfs_lookup, }; -static struct inode_operations hppfs_link_iops = { +static const struct inode_operations hppfs_link_iops = { .readlink = hppfs_readlink, .follow_link = hppfs_follow_link, }; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index e6bd553fdc4..8c718a3d413 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -33,11 +33,11 @@ /* some random number */ #define HUGETLBFS_MAGIC 0x958458f6 -static struct super_operations hugetlbfs_ops; +static const struct super_operations hugetlbfs_ops; static const struct address_space_operations hugetlbfs_aops; const struct file_operations hugetlbfs_file_operations; -static struct inode_operations hugetlbfs_dir_inode_operations; -static struct inode_operations hugetlbfs_inode_operations; +static const struct inode_operations hugetlbfs_dir_inode_operations; +static const struct inode_operations hugetlbfs_inode_operations; static struct backing_dev_info hugetlbfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ @@ -563,7 +563,7 @@ const struct file_operations hugetlbfs_file_operations = { .get_unmapped_area = hugetlb_get_unmapped_area, }; -static struct inode_operations hugetlbfs_dir_inode_operations = { +static const struct inode_operations hugetlbfs_dir_inode_operations = { .create = hugetlbfs_create, .lookup = simple_lookup, .link = simple_link, @@ -576,11 +576,11 @@ static struct inode_operations hugetlbfs_dir_inode_operations = { .setattr = hugetlbfs_setattr, }; -static struct inode_operations hugetlbfs_inode_operations = { +static const struct inode_operations hugetlbfs_inode_operations = { .setattr = hugetlbfs_setattr, }; -static struct super_operations hugetlbfs_ops = { +static const struct super_operations hugetlbfs_ops = { .alloc_inode = hugetlbfs_alloc_inode, .destroy_inode = hugetlbfs_destroy_inode, .statfs = hugetlbfs_statfs, diff --git a/fs/inode.c b/fs/inode.c index e6d93070f14..5abb097ab1b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1000,7 +1000,7 @@ EXPORT_SYMBOL(remove_inode_hash); */ void generic_delete_inode(struct inode *inode) { - struct super_operations *op = inode->i_sb->s_op; + const struct super_operations *op = inode->i_sb->s_op; list_del_init(&inode->i_list); list_del_init(&inode->i_sb_list); @@ -1093,7 +1093,7 @@ EXPORT_SYMBOL_GPL(generic_drop_inode); */ static inline void iput_final(struct inode *inode) { - struct super_operations *op = inode->i_sb->s_op; + const struct super_operations *op = inode->i_sb->s_op; void (*drop)(struct inode *) = generic_drop_inode; if (op && op->drop_inode) @@ -1113,7 +1113,7 @@ static inline void iput_final(struct inode *inode) void iput(struct inode *inode) { if (inode) { - struct super_operations *op = inode->i_sb->s_op; + const struct super_operations *op = inode->i_sb->s_op; BUG_ON(inode->i_state == I_CLEAR); @@ -1251,33 +1251,6 @@ int inode_needs_sync(struct inode *inode) EXPORT_SYMBOL(inode_needs_sync); -/* - * Quota functions that want to walk the inode lists.. - */ -#ifdef CONFIG_QUOTA - -void remove_dquot_ref(struct super_block *sb, int type, - struct list_head *tofree_head) -{ - struct inode *inode; - - if (!sb->dq_op) - return; /* nothing to do */ - spin_lock(&inode_lock); /* This lock is for inodes code */ - - /* - * We don't have to lock against quota code - test IS_QUOTAINIT is - * just for speedup... - */ - list_for_each_entry(inode, &sb->s_inodes, i_sb_list) - if (!IS_NOQUOTA(inode)) - remove_inode_dquot_ref(inode, type, tofree_head); - - spin_unlock(&inode_lock); -} - -#endif - int inode_wait(void *word) { schedule(); diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 55f6da55b7c..9f2224f65a1 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c @@ -455,8 +455,16 @@ static ssize_t inotify_read(struct file *file, char __user *buf, break; kevent = inotify_dev_get_event(dev); - if (event_size + kevent->event.len > count) + if (event_size + kevent->event.len > count) { + if (ret == 0 && count > 0) { + /* + * could not get a single event because we + * didn't have enough buffer space. + */ + ret = -EINVAL; + } break; + } if (copy_to_user(buf, &kevent->event, event_size)) { ret = -EFAULT; diff --git a/fs/ioprio.c b/fs/ioprio.c index 89e8da112a7..10d2c211d18 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -60,6 +60,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) int data = IOPRIO_PRIO_DATA(ioprio); struct task_struct *p, *g; struct user_struct *user; + struct pid *pgrp; int ret; switch (class) { @@ -98,12 +99,14 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) break; case IOPRIO_WHO_PGRP: if (!who) - who = process_group(current); - do_each_task_pid(who, PIDTYPE_PGID, p) { + pgrp = task_pgrp(current); + else + pgrp = find_pid(who); + do_each_pid_task(pgrp, PIDTYPE_PGID, p) { ret = set_task_ioprio(p, ioprio); if (ret) break; - } while_each_task_pid(who, PIDTYPE_PGID, p); + } while_each_pid_task(pgrp, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) @@ -167,6 +170,7 @@ asmlinkage long sys_ioprio_get(int which, int who) { struct task_struct *g, *p; struct user_struct *user; + struct pid *pgrp; int ret = -ESRCH; int tmpio; @@ -182,8 +186,10 @@ asmlinkage long sys_ioprio_get(int which, int who) break; case IOPRIO_WHO_PGRP: if (!who) - who = process_group(current); - do_each_task_pid(who, PIDTYPE_PGID, p) { + pgrp = task_pgrp(current); + else + pgrp = find_pid(who); + do_each_pid_task(pgrp, PIDTYPE_PGID, p) { tmpio = get_task_ioprio(p); if (tmpio < 0) continue; @@ -191,7 +197,7 @@ asmlinkage long sys_ioprio_get(int which, int who) ret = tmpio; else ret = ioprio_best(ret, tmpio); - } while_each_task_pid(who, PIDTYPE_PGID, p); + } while_each_pid_task(pgrp, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 4af2548f97a..0e94c31cad9 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -24,7 +24,7 @@ const struct file_operations isofs_dir_operations = /* * directories can handle most operations... */ -struct inode_operations isofs_dir_inode_operations = +const struct inode_operations isofs_dir_inode_operations = { .lookup = isofs_lookup, }; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index ea55b6c469e..64a96cdfe3a 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -106,7 +106,7 @@ static int isofs_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations isofs_sops = { +static const struct super_operations isofs_sops = { .alloc_inode = isofs_alloc_inode, .destroy_inode = isofs_destroy_inode, .read_inode = isofs_read_inode, diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index e6308c8b573..efe2872cd4e 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h @@ -174,7 +174,7 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, } } -extern struct inode_operations isofs_dir_inode_operations; +extern const struct inode_operations isofs_dir_inode_operations; extern const struct file_operations isofs_dir_operations; extern const struct address_space_operations isofs_symlink_aops; extern struct export_operations isofs_export_ops; diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 6ee20668850..9602b925da0 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -54,11 +54,11 @@ static int jffs_remove(struct inode *dir, struct dentry *dentry, int type); -static struct super_operations jffs_ops; +static const struct super_operations jffs_ops; static const struct file_operations jffs_file_operations; -static struct inode_operations jffs_file_inode_operations; +static const struct inode_operations jffs_file_inode_operations; static const struct file_operations jffs_dir_operations; -static struct inode_operations jffs_dir_inode_operations; +static const struct inode_operations jffs_dir_inode_operations; static const struct address_space_operations jffs_address_operations; struct kmem_cache *node_cache = NULL; @@ -1642,7 +1642,7 @@ static const struct file_operations jffs_file_operations = }; -static struct inode_operations jffs_file_inode_operations = +static const struct inode_operations jffs_file_inode_operations = { .lookup = jffs_lookup, /* lookup */ .setattr = jffs_setattr, @@ -1655,7 +1655,7 @@ static const struct file_operations jffs_dir_operations = }; -static struct inode_operations jffs_dir_inode_operations = +static const struct inode_operations jffs_dir_inode_operations = { .create = jffs_create, .lookup = jffs_lookup, @@ -1774,7 +1774,7 @@ static int jffs_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations jffs_ops = +static const struct super_operations jffs_ops = { .read_inode = jffs_read_inode, .delete_inode = jffs_delete_inode, diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index da6034d5071..cdbe2fe14e2 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -46,7 +46,7 @@ const struct file_operations jffs2_dir_operations = }; -struct inode_operations jffs2_dir_inode_operations = +const struct inode_operations jffs2_dir_inode_operations = { .create = jffs2_create, .lookup = jffs2_lookup, diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 242875f77cb..e82eeaf7590 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -54,7 +54,7 @@ const struct file_operations jffs2_file_operations = /* jffs2_file_inode_operations */ -struct inode_operations jffs2_file_inode_operations = +const struct inode_operations jffs2_file_inode_operations = { .permission = jffs2_permission, .setattr = jffs2_setattr, diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 9f41fc01a37..e07a0edcdb4 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -153,11 +153,11 @@ void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); /* dir.c */ extern const struct file_operations jffs2_dir_operations; -extern struct inode_operations jffs2_dir_inode_operations; +extern const struct inode_operations jffs2_dir_inode_operations; /* file.c */ extern const struct file_operations jffs2_file_operations; -extern struct inode_operations jffs2_file_inode_operations; +extern const struct inode_operations jffs2_file_inode_operations; extern const struct address_space_operations jffs2_file_address_operations; int jffs2_fsync(struct file *, struct dentry *, int); int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); @@ -166,7 +166,7 @@ int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long); /* symlink.c */ -extern struct inode_operations jffs2_symlink_inode_operations; +extern const struct inode_operations jffs2_symlink_inode_operations; /* fs.c */ int jffs2_setattr (struct dentry *, struct iattr *); diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 08a0e6c49e6..cc7e8e71ad4 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -66,7 +66,7 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) return 0; } -static struct super_operations jffs2_super_operations = +static const struct super_operations jffs2_super_operations = { .alloc_inode = jffs2_alloc_inode, .destroy_inode =jffs2_destroy_inode, diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index b90d5aa3d96..7e4882c8a7e 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -20,7 +20,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); -struct inode_operations jffs2_symlink_inode_operations = +const struct inode_operations jffs2_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = jffs2_follow_link, diff --git a/fs/jfs/file.c b/fs/jfs/file.c index aa9132d0492..f7f8eff19b7 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -88,7 +88,7 @@ static int jfs_release(struct inode *inode, struct file *file) return 0; } -struct inode_operations jfs_file_inode_operations = { +const struct inode_operations jfs_file_inode_operations = { .truncate = jfs_truncate, .setxattr = jfs_setxattr, .getxattr = jfs_getxattr, diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 0d06ccfaff0..6802837f757 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h @@ -35,10 +35,10 @@ extern void jfs_set_inode_flags(struct inode *); extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); extern const struct address_space_operations jfs_aops; -extern struct inode_operations jfs_dir_inode_operations; +extern const struct inode_operations jfs_dir_inode_operations; extern const struct file_operations jfs_dir_operations; -extern struct inode_operations jfs_file_inode_operations; +extern const struct inode_operations jfs_file_inode_operations; extern const struct file_operations jfs_file_operations; -extern struct inode_operations jfs_symlink_inode_operations; +extern const struct inode_operations jfs_symlink_inode_operations; extern struct dentry_operations jfs_ci_dentry_operations; #endif /* _H_JFS_INODE */ diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 7ab47561b68..41c20477126 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1503,7 +1503,7 @@ struct dentry *jfs_get_parent(struct dentry *dentry) return parent; } -struct inode_operations jfs_dir_inode_operations = { +const struct inode_operations jfs_dir_inode_operations = { .create = jfs_create, .lookup = jfs_lookup, .link = jfs_link, diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 846ac8f3451..52d73d54a93 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); static struct kmem_cache * jfs_inode_cachep; -static struct super_operations jfs_super_operations; +static const struct super_operations jfs_super_operations; static struct export_operations jfs_export_operations; static struct file_system_type jfs_fs_type; @@ -716,7 +716,7 @@ out: #endif -static struct super_operations jfs_super_operations = { +static const struct super_operations jfs_super_operations = { .alloc_inode = jfs_alloc_inode, .destroy_inode = jfs_destroy_inode, .read_inode = jfs_read_inode, diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index cee43f36f51..4af1a05aad0 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c @@ -29,7 +29,7 @@ static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations jfs_symlink_inode_operations = { +const struct inode_operations jfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = jfs_follow_link, .setxattr = jfs_setxattr, diff --git a/fs/libfs.c b/fs/libfs.c index 503898d5c4a..7d487047dbb 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -186,7 +186,7 @@ const struct file_operations simple_dir_operations = { .fsync = simple_sync_file, }; -struct inode_operations simple_dir_inode_operations = { +const struct inode_operations simple_dir_inode_operations = { .lookup = simple_lookup, }; @@ -195,11 +195,11 @@ struct inode_operations simple_dir_inode_operations = { * will never be mountable) */ int get_sb_pseudo(struct file_system_type *fs_type, char *name, - struct super_operations *ops, unsigned long magic, + const struct super_operations *ops, unsigned long magic, struct vfsmount *mnt) { struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); - static struct super_operations default_ops = {.statfs = simple_statfs}; + static const struct super_operations default_ops = {.statfs = simple_statfs}; struct dentry *dentry; struct inode *root; struct qstr d_name = {.name = name, .len = strlen(name)}; diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 3d4610c2a26..22d40320897 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -192,7 +192,7 @@ struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *rqstp, const char *hostname, int hostname_len) { - return nlm_lookup_host(1, &rqstp->rq_addr, + return nlm_lookup_host(1, svc_addr_in(rqstp), rqstp->rq_prot, rqstp->rq_vers, hostname, hostname_len); } diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 8ca18085e68..80fcacc1acf 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -141,6 +141,7 @@ lockd(struct svc_rqst *rqstp) */ while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) { long timeout = MAX_SCHEDULE_TIMEOUT; + char buf[RPC_MAX_ADDRBUFLEN]; if (signalled()) { flush_signals(current); @@ -175,11 +176,10 @@ lockd(struct svc_rqst *rqstp) break; } - dprintk("lockd: request from %08x\n", - (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); + dprintk("lockd: request from %s\n", + svc_print_addr(rqstp, buf, sizeof(buf))); svc_process(rqstp); - } flush_signals(current); @@ -223,23 +223,29 @@ static int find_socket(struct svc_serv *serv, int proto) return found; } +/* + * Make any sockets that are needed but not present. + * If nlm_udpport or nlm_tcpport were set as module + * options, make those sockets unconditionally + */ static int make_socks(struct svc_serv *serv, int proto) { - /* Make any sockets that are needed but not present. - * If nlm_udpport or nlm_tcpport were set as module - * options, make those sockets unconditionally - */ - static int warned; + static int warned; int err = 0; + if (proto == IPPROTO_UDP || nlm_udpport) if (!find_socket(serv, IPPROTO_UDP)) - err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport); - if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport)) + err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport, + SVC_SOCK_DEFAULTS); + if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) if (!find_socket(serv, IPPROTO_TCP)) - err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport); - if (!err) + err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport, + SVC_SOCK_DEFAULTS); + + if (err >= 0) { warned = 0; - else if (warned++ == 0) + err = 0; + } else if (warned++ == 0) printk(KERN_WARNING "lockd_up: makesock failed, error=%d\n", err); return err; diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index f67146a8199..47a66aa5d55 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -224,7 +224,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, resp->cookie = argp->cookie; dprintk("lockd: GRANTED called\n"); - resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock); + resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); return rpc_success; } @@ -421,15 +421,16 @@ static __be32 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, void *resp) { - struct sockaddr_in saddr = rqstp->rq_addr; + struct sockaddr_in saddr; + + memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr)); dprintk("lockd: SM_NOTIFY called\n"); if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) || ntohs(saddr.sin_port) >= 1024) { - printk(KERN_WARNING - "lockd: rejected NSM callback from %08x:%d\n", - ntohl(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port)); + char buf[RPC_MAX_ADDRBUFLEN]; + printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", + svc_print_addr(rqstp, buf, sizeof(buf))); return rpc_system_err; } diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3707c3a23e9..31cb4842573 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -253,7 +253,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, resp->cookie = argp->cookie; dprintk("lockd: GRANTED called\n"); - resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock); + resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock); dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); return rpc_success; } @@ -452,15 +452,16 @@ static __be32 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, void *resp) { - struct sockaddr_in saddr = rqstp->rq_addr; + struct sockaddr_in saddr; + + memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr)); dprintk("lockd: SM_NOTIFY called\n"); if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) || ntohs(saddr.sin_port) >= 1024) { - printk(KERN_WARNING - "lockd: rejected NSM callback from %08x:%d\n", - ntohl(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port)); + char buf[RPC_MAX_ADDRBUFLEN]; + printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", + svc_print_addr(rqstp, buf, sizeof(buf))); return rpc_system_err; } diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index df6b1075b54..c4a554df7b7 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -26,14 +26,14 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _ for (i=0; i<numblocks-1; i++) { if (!(bh=map[i])) return(0); - for (j=0; j<BLOCK_SIZE; j++) + for (j=0; j<bh->b_size; j++) sum += nibblemap[bh->b_data[j] & 0xf] + nibblemap[(bh->b_data[j]>>4) & 0xf]; } if (numblocks==0 || !(bh=map[numblocks-1])) return(0); - i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2; + i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2; for (j=0; j<i; j++) { sum += nibblemap[bh->b_data[j] & 0xf] + nibblemap[(bh->b_data[j]>>4) & 0xf]; @@ -48,28 +48,29 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _ return(sum); } -void minix_free_block(struct inode * inode, int block) +void minix_free_block(struct inode *inode, unsigned long block) { - struct super_block * sb = inode->i_sb; - struct minix_sb_info * sbi = minix_sb(sb); - struct buffer_head * bh; - unsigned int bit,zone; + struct super_block *sb = inode->i_sb; + struct minix_sb_info *sbi = minix_sb(sb); + struct buffer_head *bh; + int k = sb->s_blocksize_bits + 3; + unsigned long bit, zone; if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { printk("Trying to free block not in datazone\n"); return; } zone = block - sbi->s_firstdatazone + 1; - bit = zone & 8191; - zone >>= 13; + bit = zone & ((1<<k) - 1); + zone >>= k; if (zone >= sbi->s_zmap_blocks) { printk("minix_free_block: nonexistent bitmap buffer\n"); return; } bh = sbi->s_zmap[zone]; lock_kernel(); - if (!minix_test_and_clear_bit(bit,bh->b_data)) - printk("free_block (%s:%d): bit already cleared\n", + if (!minix_test_and_clear_bit(bit, bh->b_data)) + printk("minix_free_block (%s:%lu): bit already cleared\n", sb->s_id, block); unlock_kernel(); mark_buffer_dirty(bh); @@ -79,6 +80,7 @@ void minix_free_block(struct inode * inode, int block) int minix_new_block(struct inode * inode) { struct minix_sb_info *sbi = minix_sb(inode->i_sb); + int bits_per_zone = 8 * inode->i_sb->s_blocksize; int i; for (i = 0; i < sbi->s_zmap_blocks; i++) { @@ -86,11 +88,12 @@ int minix_new_block(struct inode * inode) int j; lock_kernel(); - if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) { - minix_set_bit(j,bh->b_data); + j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); + if (j < bits_per_zone) { + minix_set_bit(j, bh->b_data); unlock_kernel(); mark_buffer_dirty(bh); - j += i*8192 + sbi->s_firstdatazone-1; + j += i * bits_per_zone + sbi->s_firstdatazone-1; if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) break; return j; @@ -137,6 +140,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) int block; struct minix_sb_info *sbi = minix_sb(sb); struct minix2_inode *p; + int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode); *bh = NULL; if (!ino || ino > sbi->s_ninodes) { @@ -146,14 +150,14 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) } ino--; block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks + - ino / MINIX2_INODES_PER_BLOCK; + ino / minix2_inodes_per_block; *bh = sb_bread(sb, block); if (!*bh) { printk("Unable to read inode block\n"); return NULL; } p = (void *)(*bh)->b_data; - return p + ino % MINIX2_INODES_PER_BLOCK; + return p + ino % minix2_inodes_per_block; } /* Clear the link count and mode of a deleted inode on disk. */ @@ -185,26 +189,30 @@ static void minix_clear_inode(struct inode *inode) void minix_free_inode(struct inode * inode) { + struct super_block *sb = inode->i_sb; struct minix_sb_info *sbi = minix_sb(inode->i_sb); - struct buffer_head * bh; - unsigned long ino; + struct buffer_head *bh; + int k = sb->s_blocksize_bits + 3; + unsigned long ino, bit; ino = inode->i_ino; if (ino < 1 || ino > sbi->s_ninodes) { printk("minix_free_inode: inode 0 or nonexistent inode\n"); goto out; } - if ((ino >> 13) >= sbi->s_imap_blocks) { + bit = ino & ((1<<k) - 1); + ino >>= k; + if (ino >= sbi->s_imap_blocks) { printk("minix_free_inode: nonexistent imap in superblock\n"); goto out; } minix_clear_inode(inode); /* clear on-disk copy */ - bh = sbi->s_imap[ino >> 13]; + bh = sbi->s_imap[ino]; lock_kernel(); - if (!minix_test_and_clear_bit(ino & 8191, bh->b_data)) - printk("minix_free_inode: bit %lu already cleared\n", ino); + if (!minix_test_and_clear_bit(bit, bh->b_data)) + printk("minix_free_inode: bit %lu already cleared\n", bit); unlock_kernel(); mark_buffer_dirty(bh); out: @@ -217,35 +225,38 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) struct minix_sb_info *sbi = minix_sb(sb); struct inode *inode = new_inode(sb); struct buffer_head * bh; - int i,j; + int bits_per_zone = 8 * sb->s_blocksize; + unsigned long j; + int i; if (!inode) { *error = -ENOMEM; return NULL; } - j = 8192; + j = bits_per_zone; bh = NULL; *error = -ENOSPC; lock_kernel(); for (i = 0; i < sbi->s_imap_blocks; i++) { bh = sbi->s_imap[i]; - if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) + j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); + if (j < bits_per_zone) break; } - if (!bh || j >= 8192) { + if (!bh || j >= bits_per_zone) { unlock_kernel(); iput(inode); return NULL; } - if (minix_test_and_set_bit(j,bh->b_data)) { /* shouldn't happen */ - printk("new_inode: bit already set\n"); + if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */ unlock_kernel(); + printk("minix_new_inode: bit already set\n"); iput(inode); return NULL; } unlock_kernel(); mark_buffer_dirty(bh); - j += i*8192; + j += i * bits_per_zone; if (!j || j > sbi->s_ninodes) { iput(inode); return NULL; diff --git a/fs/minix/dir.c b/fs/minix/dir.c index ab782c4086f..cb4cb571fdd 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c @@ -4,6 +4,8 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * minix directory handling functions + * + * Updated to filesystem version 3 by Daniel Aragones */ #include "minix.h" @@ -11,6 +13,7 @@ #include <linux/smp_lock.h> typedef struct minix_dir_entry minix_dirent; +typedef struct minix3_dir_entry minix3_dirent; static int minix_readdir(struct file *, void *, filldir_t); @@ -89,6 +92,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) unsigned long npages = dir_pages(inode); struct minix_sb_info *sbi = minix_sb(sb); unsigned chunk_size = sbi->s_dirsize; + char *name; + __u32 inumber; lock_kernel(); @@ -105,16 +110,24 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) kaddr = (char *)page_address(page); p = kaddr+offset; limit = kaddr + minix_last_byte(inode, n) - chunk_size; - for ( ; p <= limit ; p = minix_next_entry(p, sbi)) { - minix_dirent *de = (minix_dirent *)p; - if (de->inode) { + for ( ; p <= limit; p = minix_next_entry(p, sbi)) { + if (sbi->s_version == MINIX_V3) { + minix3_dirent *de3 = (minix3_dirent *)p; + name = de3->name; + inumber = de3->inode; + } else { + minix_dirent *de = (minix_dirent *)p; + name = de->name; + inumber = de->inode; + } + if (inumber) { int over; - unsigned l = strnlen(de->name,sbi->s_namelen); + unsigned l = strnlen(name, sbi->s_namelen); offset = p - kaddr; - over = filldir(dirent, de->name, l, - (n<<PAGE_CACHE_SHIFT) | offset, - de->inode, DT_UNKNOWN); + over = filldir(dirent, name, l, + (n << PAGE_CACHE_SHIFT) | offset, + inumber, DT_UNKNOWN); if (over) { dir_put_page(page); goto done; @@ -156,23 +169,34 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page) unsigned long n; unsigned long npages = dir_pages(dir); struct page *page = NULL; - struct minix_dir_entry *de; + char *p; + char *namx; + __u32 inumber; *res_page = NULL; for (n = 0; n < npages; n++) { - char *kaddr; + char *kaddr, *limit; + page = dir_get_page(dir, n); if (IS_ERR(page)) continue; kaddr = (char*)page_address(page); - de = (struct minix_dir_entry *) kaddr; - kaddr += minix_last_byte(dir, n) - sbi->s_dirsize; - for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) { - if (!de->inode) + limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize; + for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { + if (sbi->s_version == MINIX_V3) { + minix3_dirent *de3 = (minix3_dirent *)p; + namx = de3->name; + inumber = de3->inode; + } else { + minix_dirent *de = (minix_dirent *)p; + namx = de->name; + inumber = de->inode; + } + if (!inumber) continue; - if (namecompare(namelen,sbi->s_namelen,name,de->name)) + if (namecompare(namelen, sbi->s_namelen, name, namx)) goto found; } dir_put_page(page); @@ -181,7 +205,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page) found: *res_page = page; - return de; + return (minix_dirent *)p; } int minix_add_link(struct dentry *dentry, struct inode *inode) @@ -192,12 +216,15 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) struct super_block * sb = dir->i_sb; struct minix_sb_info * sbi = minix_sb(sb); struct page *page = NULL; - struct minix_dir_entry * de; unsigned long npages = dir_pages(dir); unsigned long n; - char *kaddr; + char *kaddr, *p; + minix_dirent *de; + minix3_dirent *de3; unsigned from, to; int err; + char *namx = NULL; + __u32 inumber; /* * We take care of directory expansion in the same loop @@ -205,7 +232,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) * to protect that region. */ for (n = 0; n <= npages; n++) { - char *dir_end; + char *limit, *dir_end; page = dir_get_page(dir, n); err = PTR_ERR(page); @@ -214,20 +241,30 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) lock_page(page); kaddr = (char*)page_address(page); dir_end = kaddr + minix_last_byte(dir, n); - de = (minix_dirent *)kaddr; - kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize; - while ((char *)de <= kaddr) { - if ((char *)de == dir_end) { + limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize; + for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { + de = (minix_dirent *)p; + de3 = (minix3_dirent *)p; + if (sbi->s_version == MINIX_V3) { + namx = de3->name; + inumber = de3->inode; + } else { + namx = de->name; + inumber = de->inode; + } + if (p == dir_end) { /* We hit i_size */ - de->inode = 0; + if (sbi->s_version == MINIX_V3) + de3->inode = 0; + else + de->inode = 0; goto got_it; } - if (!de->inode) + if (!inumber) goto got_it; err = -EEXIST; - if (namecompare(namelen,sbi->s_namelen,name,de->name)) + if (namecompare(namelen, sbi->s_namelen, name, namx)) goto out_unlock; - de = minix_next_entry(de, sbi); } unlock_page(page); dir_put_page(page); @@ -236,14 +273,19 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) return -EINVAL; got_it: - from = (char*)de - (char*)page_address(page); + from = p - (char*)page_address(page); to = from + sbi->s_dirsize; err = page->mapping->a_ops->prepare_write(NULL, page, from, to); if (err) goto out_unlock; - memcpy (de->name, name, namelen); - memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2); - de->inode = inode->i_ino; + memcpy (namx, name, namelen); + if (sbi->s_version == MINIX_V3) { + memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4); + de3->inode = inode->i_ino; + } else { + memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2); + de->inode = inode->i_ino; + } err = dir_commit_chunk(page, from, to); dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(dir); @@ -283,8 +325,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir) { struct address_space *mapping = inode->i_mapping; struct page *page = grab_cache_page(mapping, 0); - struct minix_sb_info * sbi = minix_sb(inode->i_sb); - struct minix_dir_entry * de; + struct minix_sb_info *sbi = minix_sb(inode->i_sb); char *kaddr; int err; @@ -299,12 +340,23 @@ int minix_make_empty(struct inode *inode, struct inode *dir) kaddr = kmap_atomic(page, KM_USER0); memset(kaddr, 0, PAGE_CACHE_SIZE); - de = (struct minix_dir_entry *)kaddr; - de->inode = inode->i_ino; - strcpy(de->name,"."); - de = minix_next_entry(de, sbi); - de->inode = dir->i_ino; - strcpy(de->name,".."); + if (sbi->s_version == MINIX_V3) { + minix3_dirent *de3 = (minix3_dirent *)kaddr; + + de3->inode = inode->i_ino; + strcpy(de3->name, "."); + de3 = minix_next_entry(de3, sbi); + de3->inode = dir->i_ino; + strcpy(de3->name, ".."); + } else { + minix_dirent *de = (minix_dirent *)kaddr; + + de->inode = inode->i_ino; + strcpy(de->name, "."); + de = minix_next_entry(de, sbi); + de->inode = dir->i_ino; + strcpy(de->name, ".."); + } kunmap_atomic(kaddr, KM_USER0); err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize); @@ -321,33 +373,41 @@ int minix_empty_dir(struct inode * inode) struct page *page = NULL; unsigned long i, npages = dir_pages(inode); struct minix_sb_info *sbi = minix_sb(inode->i_sb); + char *name; + __u32 inumber; for (i = 0; i < npages; i++) { - char *kaddr; - minix_dirent * de; - page = dir_get_page(inode, i); + char *p, *kaddr, *limit; + page = dir_get_page(inode, i); if (IS_ERR(page)) continue; kaddr = (char *)page_address(page); - de = (minix_dirent *)kaddr; - kaddr += minix_last_byte(inode, i) - sbi->s_dirsize; + limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize; + for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { + if (sbi->s_version == MINIX_V3) { + minix3_dirent *de3 = (minix3_dirent *)p; + name = de3->name; + inumber = de3->inode; + } else { + minix_dirent *de = (minix_dirent *)p; + name = de->name; + inumber = de->inode; + } - while ((char *)de <= kaddr) { - if (de->inode != 0) { + if (inumber != 0) { /* check for . and .. */ - if (de->name[0] != '.') + if (name[0] != '.') goto not_empty; - if (!de->name[1]) { - if (de->inode != inode->i_ino) + if (!name[1]) { + if (inumber != inode->i_ino) goto not_empty; - } else if (de->name[1] != '.') + } else if (name[1] != '.') goto not_empty; - else if (de->name[2]) + else if (name[2]) goto not_empty; } - de = minix_next_entry(de, sbi); } dir_put_page(page); } diff --git a/fs/minix/file.c b/fs/minix/file.c index 40eac2e60d2..f92baa1d757 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -26,7 +26,7 @@ const struct file_operations minix_file_operations = { .sendfile = generic_file_sendfile, }; -struct inode_operations minix_file_inode_operations = { +const struct inode_operations minix_file_inode_operations = { .truncate = minix_truncate, .getattr = minix_getattr, }; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 629e09b38c5..92e383af370 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -7,6 +7,7 @@ * Minix V2 fs support. * * Modified for 680x0 by Andreas Schwab + * Updated to filesystem version 3 by Daniel Aragones */ #include <linux/module.h> @@ -36,7 +37,8 @@ static void minix_put_super(struct super_block *sb) struct minix_sb_info *sbi = minix_sb(sb); if (!(sb->s_flags & MS_RDONLY)) { - sbi->s_ms->s_state = sbi->s_mount_state; + if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ + sbi->s_ms->s_state = sbi->s_mount_state; mark_buffer_dirty(sbi->s_sbh); } for (i = 0; i < sbi->s_imap_blocks; i++) @@ -93,7 +95,7 @@ static void destroy_inodecache(void) kmem_cache_destroy(minix_inode_cachep); } -static struct super_operations minix_sops = { +static const struct super_operations minix_sops = { .alloc_inode = minix_alloc_inode, .destroy_inode = minix_destroy_inode, .read_inode = minix_read_inode, @@ -117,12 +119,17 @@ static int minix_remount (struct super_block * sb, int * flags, char * data) !(sbi->s_mount_state & MINIX_VALID_FS)) return 0; /* Mounting a rw partition read-only. */ - ms->s_state = sbi->s_mount_state; + if (sbi->s_version != MINIX_V3) + ms->s_state = sbi->s_mount_state; mark_buffer_dirty(sbi->s_sbh); } else { /* Mount a partition which is read-only, read-write. */ - sbi->s_mount_state = ms->s_state; - ms->s_state &= ~MINIX_VALID_FS; + if (sbi->s_version != MINIX_V3) { + sbi->s_mount_state = ms->s_state; + ms->s_state &= ~MINIX_VALID_FS; + } else { + sbi->s_mount_state = MINIX_VALID_FS; + } mark_buffer_dirty(sbi->s_sbh); if (!(sbi->s_mount_state & MINIX_VALID_FS)) @@ -140,7 +147,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) struct buffer_head *bh; struct buffer_head **map; struct minix_super_block *ms; - int i, block; + struct minix3_super_block *m3s = NULL; + unsigned long i, block; struct inode *root_inode; struct minix_sb_info *sbi; @@ -192,6 +200,22 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) sbi->s_dirsize = 32; sbi->s_namelen = 30; sbi->s_link_max = MINIX2_LINK_MAX; + } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) { + m3s = (struct minix3_super_block *) bh->b_data; + s->s_magic = m3s->s_magic; + sbi->s_imap_blocks = m3s->s_imap_blocks; + sbi->s_zmap_blocks = m3s->s_zmap_blocks; + sbi->s_firstdatazone = m3s->s_firstdatazone; + sbi->s_log_zone_size = m3s->s_log_zone_size; + sbi->s_max_size = m3s->s_max_size; + sbi->s_ninodes = m3s->s_ninodes; + sbi->s_nzones = m3s->s_zones; + sbi->s_dirsize = 64; + sbi->s_namelen = 60; + sbi->s_version = MINIX_V3; + sbi->s_link_max = MINIX2_LINK_MAX; + sbi->s_mount_state = MINIX_VALID_FS; + sb_set_blocksize(s, m3s->s_blocksize); } else goto out_no_fs; @@ -236,7 +260,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) s->s_root->d_op = &minix_dentry_operations; if (!(s->s_flags & MS_RDONLY)) { - ms->s_state &= ~MINIX_VALID_FS; + if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ + ms->s_state &= ~MINIX_VALID_FS; mark_buffer_dirty(bh); } if (!(sbi->s_mount_state & MINIX_VALID_FS)) @@ -278,8 +303,8 @@ out_illegal_sb: out_no_fs: if (!silent) - printk("VFS: Can't find a Minix or Minix V2 filesystem " - "on device %s\n", s->s_id); + printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 " + "on device %s.\n", s->s_id); out_release: brelse(bh); goto out; @@ -344,7 +369,7 @@ static const struct address_space_operations minix_aops = { .bmap = minix_bmap }; -static struct inode_operations minix_symlink_inode_operations = { +static const struct inode_operations minix_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, @@ -537,12 +562,14 @@ int minix_sync_inode(struct inode * inode) int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { + struct inode *dir = dentry->d_parent->d_inode; + struct super_block *sb = dir->i_sb; generic_fillattr(dentry->d_inode, stat); if (INODE_VERSION(dentry->d_inode) == MINIX_V1) - stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size); + stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb); else - stat->blocks = (BLOCK_SIZE / 512) * V2_minix_blocks(stat->size); - stat->blksize = BLOCK_SIZE; + stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb); + stat->blksize = sb->s_blocksize; return 0; } diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c index 429baf8de10..a731cabf154 100644 --- a/fs/minix/itree_common.c +++ b/fs/minix/itree_common.c @@ -23,7 +23,7 @@ static inline int verify_chain(Indirect *from, Indirect *to) static inline block_t *block_end(struct buffer_head *bh) { - return (block_t *)((char*)bh->b_data + BLOCK_SIZE); + return (block_t *)((char*)bh->b_data + bh->b_size); } static inline Indirect *get_branch(struct inode *inode, @@ -85,7 +85,7 @@ static int alloc_branch(struct inode *inode, branch[n].key = cpu_to_block(nr); bh = sb_getblk(inode->i_sb, parent); lock_buffer(bh); - memset(bh->b_data, 0, BLOCK_SIZE); + memset(bh->b_data, 0, bh->b_size); branch[n].bh = bh; branch[n].p = (block_t*) bh->b_data + offsets[n]; *branch[n].p = branch[n].key; @@ -292,6 +292,7 @@ static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth static inline void truncate (struct inode * inode) { + struct super_block *sb = inode->i_sb; block_t *idata = i_data(inode); int offsets[DEPTH]; Indirect chain[DEPTH]; @@ -301,7 +302,7 @@ static inline void truncate (struct inode * inode) int first_whole; long iblock; - iblock = (inode->i_size + BLOCK_SIZE-1) >> 10; + iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits; block_truncate_page(inode->i_mapping, inode->i_size, get_block); n = block_to_path(inode, iblock, offsets); @@ -346,15 +347,16 @@ do_indirects: mark_inode_dirty(inode); } -static inline unsigned nblocks(loff_t size) +static inline unsigned nblocks(loff_t size, struct super_block *sb) { + int k = sb->s_blocksize_bits - 10; unsigned blocks, res, direct = DIRECT, i = DEPTH; - blocks = (size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; + blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k); res = blocks; while (--i && blocks > direct) { blocks -= direct; - blocks += BLOCK_SIZE/sizeof(block_t) - 1; - blocks /= BLOCK_SIZE/sizeof(block_t); + blocks += sb->s_blocksize/sizeof(block_t) - 1; + blocks /= sb->s_blocksize/sizeof(block_t); res += blocks; direct = 1; } diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c index 656b1347a25..1a5f3bf0bce 100644 --- a/fs/minix/itree_v1.c +++ b/fs/minix/itree_v1.c @@ -55,7 +55,7 @@ void V1_minix_truncate(struct inode * inode) truncate(inode); } -unsigned V1_minix_blocks(loff_t size) +unsigned V1_minix_blocks(loff_t size, struct super_block *sb) { - return nblocks(size); + return nblocks(size, sb); } diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c index 9adcdc754e0..ad8f0dec4ef 100644 --- a/fs/minix/itree_v2.c +++ b/fs/minix/itree_v2.c @@ -23,10 +23,11 @@ static inline block_t *i_data(struct inode *inode) static int block_to_path(struct inode * inode, long block, int offsets[DEPTH]) { int n = 0; + struct super_block *sb = inode->i_sb; if (block < 0) { printk("minix_bmap: block<0\n"); - } else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) { + } else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) { printk("minix_bmap: block>big\n"); } else if (block < 7) { offsets[n++] = block; @@ -60,7 +61,7 @@ void V2_minix_truncate(struct inode * inode) truncate(inode); } -unsigned V2_minix_blocks(loff_t size) +unsigned V2_minix_blocks(loff_t size, struct super_block *sb) { - return nblocks(size); + return nblocks(size, sb); } diff --git a/fs/minix/minix.h b/fs/minix/minix.h index c55b77cdcc8..73ef84f8fb0 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -7,11 +7,10 @@ * truncated. Else they will be disallowed (ENAMETOOLONG). */ #define NO_TRUNCATE 1 - #define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version - #define MINIX_V1 0x0001 /* original minix fs */ #define MINIX_V2 0x0002 /* minix V2 fs */ +#define MINIX_V3 0x0003 /* minix V3 fs */ /* * minix fs inode data in memory @@ -52,12 +51,10 @@ extern struct inode * minix_new_inode(const struct inode * dir, int * error); extern void minix_free_inode(struct inode * inode); extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi); extern int minix_new_block(struct inode * inode); -extern void minix_free_block(struct inode * inode, int block); +extern void minix_free_block(struct inode *inode, unsigned long block); extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi); - extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *); -extern void V2_minix_truncate(struct inode *); extern void V1_minix_truncate(struct inode *); extern void V2_minix_truncate(struct inode *); extern void minix_truncate(struct inode *); @@ -65,8 +62,8 @@ extern int minix_sync_inode(struct inode *); extern void minix_set_inode(struct inode *, dev_t); extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int); extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int); -extern unsigned V1_minix_blocks(loff_t); -extern unsigned V2_minix_blocks(loff_t); +extern unsigned V1_minix_blocks(loff_t, struct super_block *); +extern unsigned V2_minix_blocks(loff_t, struct super_block *); extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**); extern int minix_add_link(struct dentry*, struct inode*); @@ -76,11 +73,10 @@ extern int minix_empty_dir(struct inode*); extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*); extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**); extern ino_t minix_inode_by_name(struct dentry*); - extern int minix_sync_file(struct file *, struct dentry *, int); -extern struct inode_operations minix_file_inode_operations; -extern struct inode_operations minix_dir_inode_operations; +extern const struct inode_operations minix_file_inode_operations; +extern const struct inode_operations minix_dir_inode_operations; extern const struct file_operations minix_file_operations; extern const struct file_operations minix_dir_operations; extern struct dentry_operations minix_dentry_operations; diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 299bb66e3bd..f4aa7a93904 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -291,7 +291,7 @@ out: /* * directories can handle most operations... */ -struct inode_operations minix_dir_inode_operations = { +const struct inode_operations minix_dir_inode_operations = { .create = minix_create, .lookup = minix_lookup, .link = minix_link, diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 452461955cb..30f7d0ae221 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -646,7 +646,7 @@ out: return err; } -static struct inode_operations msdos_dir_inode_operations = { +static const struct inode_operations msdos_dir_inode_operations = { .create = msdos_create, .lookup = msdos_lookup, .unlink = msdos_unlink, diff --git a/fs/namei.c b/fs/namei.c index e4f108f0823..161e2225c75 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2744,7 +2744,7 @@ int page_symlink(struct inode *inode, const char *symname, int len) mapping_gfp_mask(inode->i_mapping)); } -struct inode_operations page_symlink_inode_operations = { +const struct inode_operations page_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 73747772c3b..011ef0b6d2d 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -58,7 +58,7 @@ const struct file_operations ncp_dir_operations = #endif }; -struct inode_operations ncp_dir_inode_operations = +const struct inode_operations ncp_dir_inode_operations = { .create = ncp_create, .lookup = ncp_lookup, diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index b91fea03b1c..6b1f6d27099 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -297,7 +297,7 @@ const struct file_operations ncp_file_operations = .fsync = ncp_fsync, }; -struct inode_operations ncp_file_inode_operations = +const struct inode_operations ncp_file_inode_operations = { .setattr = ncp_notify_change, }; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 67a90bf795d..14939ddf74f 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -90,7 +90,7 @@ static int ncp_remount(struct super_block *sb, int *flags, char* data) return 0; } -static struct super_operations ncp_sops = +static const struct super_operations ncp_sops = { .alloc_inode = ncp_alloc_inode, .destroy_inode = ncp_destroy_inode, @@ -229,7 +229,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) } #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) -static struct inode_operations ncp_symlink_inode_operations = { +static const struct inode_operations ncp_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 7933e2e99db..75f309c8741 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -71,6 +71,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) complete(&nfs_callback_info.started); for(;;) { + char buf[RPC_MAX_ADDRBUFLEN]; + if (signalled()) { if (nfs_callback_info.users == 0) break; @@ -88,8 +90,8 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) __FUNCTION__, -err); break; } - dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__, - NIPQUAD(rqstp->rq_addr.sin_addr.s_addr)); + dprintk("%s: request from %s\n", __FUNCTION__, + svc_print_addr(rqstp, buf, sizeof(buf))); svc_process(rqstp); } @@ -106,7 +108,6 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) int nfs_callback_up(void) { struct svc_serv *serv; - struct svc_sock *svsk; int ret = 0; lock_kernel(); @@ -119,17 +120,14 @@ int nfs_callback_up(void) ret = -ENOMEM; if (!serv) goto out_err; - /* FIXME: We don't want to register this socket with the portmapper */ - ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport); - if (ret < 0) + + ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport, + SVC_SOCK_ANONYMOUS); + if (ret <= 0) goto out_destroy; - if (!list_empty(&serv->sv_permsocks)) { - svsk = list_entry(serv->sv_permsocks.next, - struct svc_sock, sk_list); - nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport); - dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport); - } else - BUG(); + nfs_callback_tcpport = ret; + dprintk("Callback port = 0x%x\n", nfs_callback_tcpport); + ret = svc_create_thread(nfs_callback_svc, serv); if (ret < 0) goto out_destroy; @@ -140,6 +138,8 @@ out: unlock_kernel(); return ret; out_destroy: + dprintk("Couldn't create callback socket or server thread; err = %d\n", + ret); svc_destroy(serv); out_err: nfs_callback_info.users--; @@ -166,15 +166,19 @@ void nfs_callback_down(void) static int nfs_callback_authenticate(struct svc_rqst *rqstp) { - struct sockaddr_in *addr = &rqstp->rq_addr; + struct sockaddr_in *addr = svc_addr_in(rqstp); struct nfs_client *clp; + char buf[RPC_MAX_ADDRBUFLEN]; /* Don't talk to strangers */ clp = nfs_find_client(addr, 4); if (clp == NULL) return SVC_DROP; - dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr)); + + dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__, + svc_print_addr(rqstp, buf, sizeof(buf))); nfs_put_client(clp); + switch (rqstp->rq_authop->flavour) { case RPC_AUTH_NULL: if (rqstp->rq_proc != CB_NULL) diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index f8ea1f51f59..849a2029975 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -176,7 +176,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr status = decode_fh(xdr, &args->fh); if (unlikely(status != 0)) goto out; - args->addr = &rqstp->rq_addr; + args->addr = svc_addr_in(rqstp); status = decode_bitmap(xdr, args->bitmap); out: dprintk("%s: exit with status = %d\n", __FUNCTION__, status); @@ -188,7 +188,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, __be32 *p; __be32 status; - args->addr = &rqstp->rq_addr; + args->addr = svc_addr_in(rqstp); status = decode_stateid(xdr, &args->stateid); if (unlikely(status != 0)) goto out; diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 23ab145daa2..ae9f36e393c 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -1173,7 +1173,7 @@ static struct seq_operations nfs_server_list_ops = { .show = nfs_server_list_show, }; -static struct file_operations nfs_server_list_fops = { +static const struct file_operations nfs_server_list_fops = { .open = nfs_server_list_open, .read = seq_read, .llseek = seq_lseek, @@ -1193,7 +1193,7 @@ static struct seq_operations nfs_volume_list_ops = { .show = nfs_volume_list_show, }; -static struct file_operations nfs_volume_list_fops = { +static const struct file_operations nfs_volume_list_fops = { .open = nfs_volume_list_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index d9ba8cb0ee7..f03a770bacb 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -65,7 +65,7 @@ const struct file_operations nfs_dir_operations = { .fsync = nfs_fsync_dir, }; -struct inode_operations nfs_dir_inode_operations = { +const struct inode_operations nfs_dir_inode_operations = { .create = nfs_create, .lookup = nfs_lookup, .link = nfs_link, @@ -81,7 +81,7 @@ struct inode_operations nfs_dir_inode_operations = { }; #ifdef CONFIG_NFS_V3 -struct inode_operations nfs3_dir_inode_operations = { +const struct inode_operations nfs3_dir_inode_operations = { .create = nfs_create, .lookup = nfs_lookup, .link = nfs_link, @@ -104,7 +104,7 @@ struct inode_operations nfs3_dir_inode_operations = { #ifdef CONFIG_NFS_V4 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); -struct inode_operations nfs4_dir_inode_operations = { +const struct inode_operations nfs4_dir_inode_operations = { .create = nfs_create, .lookup = nfs_atomic_lookup, .link = nfs_link, diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 9e4a2b70995..8e66b5a2d49 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -68,14 +68,14 @@ const struct file_operations nfs_file_operations = { .check_flags = nfs_check_flags, }; -struct inode_operations nfs_file_inode_operations = { +const struct inode_operations nfs_file_inode_operations = { .permission = nfs_permission, .getattr = nfs_getattr, .setattr = nfs_setattr, }; #ifdef CONFIG_NFS_V3 -struct inode_operations nfs3_file_inode_operations = { +const struct inode_operations nfs3_file_inode_operations = { .permission = nfs_permission, .getattr = nfs_getattr, .setattr = nfs_setattr, diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 371b804e7cc..7f86e65182e 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -155,12 +155,12 @@ out_follow: goto out; } -struct inode_operations nfs_mountpoint_inode_operations = { +const struct inode_operations nfs_mountpoint_inode_operations = { .follow_link = nfs_follow_mountpoint, .getattr = nfs_getattr, }; -struct inode_operations nfs_referral_inode_operations = { +const struct inode_operations nfs_referral_inode_operations = { .follow_link = nfs_follow_mountpoint, }; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c26cd978c7c..e2341766c4f 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -151,7 +151,7 @@ struct nfs4_state_recovery_ops { }; extern struct dentry_operations nfs4_dentry_operations; -extern struct inode_operations nfs4_dir_inode_operations; +extern const struct inode_operations nfs4_dir_inode_operations; /* inode.c */ extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b3fd29baadc..1daee65b517 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3625,7 +3625,7 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = { .recover_lock = nfs4_lock_expired, }; -static struct inode_operations nfs4_file_inode_operations = { +static const struct inode_operations nfs4_file_inode_operations = { .permission = nfs_permission, .getattr = nfs_getattr, .setattr = nfs_setattr, diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 28108c82b88..baa28860ad2 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -44,6 +44,7 @@ #include <linux/vfs.h> #include <linux/inet.h> #include <linux/nfs_xdr.h> +#include <linux/magic.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -81,7 +82,7 @@ struct file_system_type nfs_xdev_fs_type = { .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -static struct super_operations nfs_sops = { +static const struct super_operations nfs_sops = { .alloc_inode = nfs_alloc_inode, .destroy_inode = nfs_destroy_inode, .write_inode = nfs_write_inode, @@ -125,7 +126,7 @@ struct file_system_type nfs4_referral_fs_type = { .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -static struct super_operations nfs4_sops = { +static const struct super_operations nfs4_sops = { .alloc_inode = nfs_alloc_inode, .destroy_inode = nfs_destroy_inode, .write_inode = nfs_write_inode, diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 525c136c7d8..f4a0548b9ce 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -78,7 +78,7 @@ read_failed: /* * symlinks can't do much... */ -struct inode_operations nfs_symlink_inode_operations = { +const struct inode_operations nfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = nfs_follow_link, .put_link = page_put_link, diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9de89df961f..9e406799920 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -714,7 +714,7 @@ __be32 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_setclientid *setclid) { - __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; + struct sockaddr_in *sin = svc_addr_in(rqstp); struct xdr_netobj clname = { .len = setclid->se_namelen, .data = setclid->se_name, @@ -749,7 +749,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, */ status = nfserr_clid_inuse; if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) - || conf->cl_addr != ip_addr) { + || conf->cl_addr != sin->sin_addr.s_addr) { printk("NFSD: setclientid: string in use by client" "(clientid %08x/%08x)\n", conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id); @@ -769,7 +769,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (new == NULL) goto out; copy_verf(new, &clverifier); - new->cl_addr = ip_addr; + new->cl_addr = sin->sin_addr.s_addr; copy_cred(&new->cl_cred,&rqstp->rq_cred); gen_clid(new); gen_confirm(new); @@ -801,7 +801,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (new == NULL) goto out; copy_verf(new,&conf->cl_verifier); - new->cl_addr = ip_addr; + new->cl_addr = sin->sin_addr.s_addr; copy_cred(&new->cl_cred,&rqstp->rq_cred); copy_clid(new, conf); gen_confirm(new); @@ -820,7 +820,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (new == NULL) goto out; copy_verf(new,&clverifier); - new->cl_addr = ip_addr; + new->cl_addr = sin->sin_addr.s_addr; copy_cred(&new->cl_cred,&rqstp->rq_cred); gen_clid(new); gen_confirm(new); @@ -847,7 +847,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (new == NULL) goto out; copy_verf(new,&clverifier); - new->cl_addr = ip_addr; + new->cl_addr = sin->sin_addr.s_addr; copy_cred(&new->cl_cred,&rqstp->rq_cred); gen_clid(new); gen_confirm(new); @@ -881,7 +881,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_setclientid_confirm *setclientid_confirm) { - __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; + struct sockaddr_in *sin = svc_addr_in(rqstp); struct nfs4_client *conf, *unconf; nfs4_verifier confirm = setclientid_confirm->sc_confirm; clientid_t * clid = &setclientid_confirm->sc_clientid; @@ -900,9 +900,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, unconf = find_unconfirmed_client(clid); status = nfserr_clid_inuse; - if (conf && conf->cl_addr != ip_addr) + if (conf && conf->cl_addr != sin->sin_addr.s_addr) goto out; - if (unconf && unconf->cl_addr != ip_addr) + if (unconf && unconf->cl_addr != sin->sin_addr.s_addr) goto out; if ((conf && unconf) && diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index f90d7047585..578f2c9d56b 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -185,7 +185,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type) rp->c_state = RC_INPROG; rp->c_xid = xid; rp->c_proc = proc; - rp->c_addr = rqstp->rq_addr; + memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr)); rp->c_prot = proto; rp->c_vers = vers; rp->c_timestamp = jiffies; diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index c59d6fbb7a6..a0b4282cb28 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -20,6 +20,7 @@ #include <linux/mount.h> #include <asm/pgtable.h> +#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/svc.h> #include <linux/nfsd/nfsd.h> @@ -180,10 +181,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) /* Check if the request originated from a secure port. */ error = nfserr_perm; if (!rqstp->rq_secure && EX_SECURE(exp)) { + char buf[RPC_MAX_ADDRBUFLEN]; printk(KERN_WARNING - "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n", - NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port)); + "nfsd: request from insecure port %s!\n", + svc_print_addr(rqstp, buf, sizeof(buf))); goto out; } diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index ec983b77768..5cc2eec981b 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -19,6 +19,7 @@ #include <linux/unistd.h> #include <linux/slab.h> +#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/svc.h> #include <linux/nfsd/nfsd.h> #include <linux/nfsd/cache.h> @@ -147,10 +148,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, */ if (NFSSVC_MAXBLKSIZE_V2 < argp->count) { + char buf[RPC_MAX_ADDRBUFLEN]; printk(KERN_NOTICE - "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n", - NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), - ntohs(rqstp->rq_addr.sin_port), + "oversized read request from %s (%d bytes)\n", + svc_print_addr(rqstp, buf, sizeof(buf)), argp->count); argp->count = NFSSVC_MAXBLKSIZE_V2; } diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index fbf5d51947e..d7759ce6ed9 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -235,7 +235,8 @@ static int nfsd_init_socks(int port) error = lockd_up(IPPROTO_UDP); if (error >= 0) { - error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); + error = svc_makesock(nfsd_serv, IPPROTO_UDP, port, + SVC_SOCK_DEFAULTS); if (error < 0) lockd_down(); } @@ -245,7 +246,8 @@ static int nfsd_init_socks(int port) #ifdef CONFIG_NFSD_TCP error = lockd_up(IPPROTO_TCP); if (error >= 0) { - error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); + error = svc_makesock(nfsd_serv, IPPROTO_TCP, port, + SVC_SOCK_DEFAULTS); if (error < 0) lockd_down(); } diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index c577d8e1bd9..7659cc19299 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1921,7 +1921,7 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size, u32 attr_len = 0; /* Silence stupid gcc warning. */ bool mp_rebuilt; -#ifdef NTFS_DEBUG +#ifdef DEBUG read_lock_irqsave(&ni->size_lock, flags); allocated_size = ni->allocated_size; read_unlock_irqrestore(&ni->size_lock, flags); diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 076c9420c25..d69c4595ccd 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -2328,7 +2328,7 @@ const struct file_operations ntfs_file_ops = { the data source. */ }; -struct inode_operations ntfs_file_inode_ops = { +const struct inode_operations ntfs_file_inode_ops = { #ifdef NTFS_RW .truncate = ntfs_truncate_vfs, .setattr = ntfs_setattr, @@ -2337,4 +2337,4 @@ struct inode_operations ntfs_file_inode_ops = { const struct file_operations ntfs_empty_file_ops = {}; -struct inode_operations ntfs_empty_inode_ops = {}; +const struct inode_operations ntfs_empty_inode_ops = {}; diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index eddb2247cec..bff01a54675 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -359,7 +359,7 @@ err_out: /** * Inode operations for directories. */ -struct inode_operations ntfs_dir_inode_ops = { +const struct inode_operations ntfs_dir_inode_ops = { .lookup = ntfs_lookup, /* VFS: Lookup directory. */ }; diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index a12847ae467..d73f5a9ac34 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h @@ -61,13 +61,13 @@ extern const struct address_space_operations ntfs_aops; extern const struct address_space_operations ntfs_mst_aops; extern const struct file_operations ntfs_file_ops; -extern struct inode_operations ntfs_file_inode_ops; +extern const struct inode_operations ntfs_file_inode_ops; extern const struct file_operations ntfs_dir_ops; -extern struct inode_operations ntfs_dir_inode_ops; +extern const struct inode_operations ntfs_dir_inode_ops; extern const struct file_operations ntfs_empty_file_ops; -extern struct inode_operations ntfs_empty_inode_ops; +extern const struct inode_operations ntfs_empty_inode_ops; extern struct export_operations ntfs_export_ops; diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index babf94d90de..1594c90b716 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2699,7 +2699,7 @@ static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs) /** * The complete super operations. */ -static struct super_operations ntfs_sops = { +static const struct super_operations ntfs_sops = { .alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */ .destroy_inode = ntfs_destroy_big_inode, /* VFS: Deallocate inode. */ #ifdef NTFS_RW diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index b7f0ba97a1a..de952eba29a 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -61,11 +61,11 @@ #define MLOG_MASK_PREFIX ML_DLMFS #include "cluster/masklog.h" -static struct super_operations dlmfs_ops; -static struct file_operations dlmfs_file_operations; -static struct inode_operations dlmfs_dir_inode_operations; -static struct inode_operations dlmfs_root_inode_operations; -static struct inode_operations dlmfs_file_inode_operations; +static const struct super_operations dlmfs_ops; +static const struct file_operations dlmfs_file_operations; +static const struct inode_operations dlmfs_dir_inode_operations; +static const struct inode_operations dlmfs_root_inode_operations; +static const struct inode_operations dlmfs_file_inode_operations; static struct kmem_cache *dlmfs_inode_cache; struct workqueue_struct *user_dlm_worker; @@ -540,27 +540,27 @@ static int dlmfs_fill_super(struct super_block * sb, return 0; } -static struct file_operations dlmfs_file_operations = { +static const struct file_operations dlmfs_file_operations = { .open = dlmfs_file_open, .release = dlmfs_file_release, .read = dlmfs_file_read, .write = dlmfs_file_write, }; -static struct inode_operations dlmfs_dir_inode_operations = { +static const struct inode_operations dlmfs_dir_inode_operations = { .create = dlmfs_create, .lookup = simple_lookup, .unlink = dlmfs_unlink, }; /* this way we can restrict mkdir to only the toplevel of the fs. */ -static struct inode_operations dlmfs_root_inode_operations = { +static const struct inode_operations dlmfs_root_inode_operations = { .lookup = simple_lookup, .mkdir = dlmfs_mkdir, .rmdir = simple_rmdir, }; -static struct super_operations dlmfs_ops = { +static const struct super_operations dlmfs_ops = { .statfs = simple_statfs, .alloc_inode = dlmfs_alloc_inode, .destroy_inode = dlmfs_destroy_inode, @@ -568,7 +568,7 @@ static struct super_operations dlmfs_ops = { .drop_inode = generic_delete_inode, }; -static struct inode_operations dlmfs_file_inode_operations = { +static const struct inode_operations dlmfs_file_inode_operations = { .getattr = simple_getattr, }; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 10953a508f2..f2cd3bf9efb 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1365,13 +1365,13 @@ bail: return ret; } -struct inode_operations ocfs2_file_iops = { +const struct inode_operations ocfs2_file_iops = { .setattr = ocfs2_setattr, .getattr = ocfs2_getattr, .permission = ocfs2_permission, }; -struct inode_operations ocfs2_special_file_iops = { +const struct inode_operations ocfs2_special_file_iops = { .setattr = ocfs2_setattr, .getattr = ocfs2_getattr, .permission = ocfs2_permission, diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 601a453f18a..cc973f01f6c 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -28,8 +28,8 @@ extern const struct file_operations ocfs2_fops; extern const struct file_operations ocfs2_dops; -extern struct inode_operations ocfs2_file_iops; -extern struct inode_operations ocfs2_special_file_iops; +extern const struct inode_operations ocfs2_file_iops; +extern const struct inode_operations ocfs2_special_file_iops; struct ocfs2_alloc_context; enum ocfs2_alloc_restarted { diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f3d7803b4b4..f7fa52bb3f6 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -2306,7 +2306,7 @@ leave: return status; } -struct inode_operations ocfs2_dir_iops = { +const struct inode_operations ocfs2_dir_iops = { .create = ocfs2_create, .lookup = ocfs2_lookup, .link = ocfs2_link, diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h index 8425944fccc..0975c7b7212 100644 --- a/fs/ocfs2/namei.h +++ b/fs/ocfs2/namei.h @@ -26,7 +26,7 @@ #ifndef OCFS2_NAMEI_H #define OCFS2_NAMEI_H -extern struct inode_operations ocfs2_dir_iops; +extern const struct inode_operations ocfs2_dir_iops; struct dentry *ocfs2_get_parent(struct dentry *child); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 6e300a88a47..6534f92424d 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -116,7 +116,7 @@ static void ocfs2_destroy_inode(struct inode *inode); static unsigned long long ocfs2_max_file_offset(unsigned int blockshift); -static struct super_operations ocfs2_sops = { +static const struct super_operations ocfs2_sops = { .statfs = ocfs2_statfs, .alloc_inode = ocfs2_alloc_inode, .destroy_inode = ocfs2_destroy_inode, diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 03b0191534d..40dc1a51f4a 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -170,12 +170,12 @@ bail: return ERR_PTR(status); } -struct inode_operations ocfs2_symlink_inode_operations = { +const struct inode_operations ocfs2_symlink_inode_operations = { .readlink = page_readlink, .follow_link = ocfs2_follow_link, .getattr = ocfs2_getattr, }; -struct inode_operations ocfs2_fast_symlink_inode_operations = { +const struct inode_operations ocfs2_fast_symlink_inode_operations = { .readlink = ocfs2_readlink, .follow_link = ocfs2_follow_link, .getattr = ocfs2_getattr, diff --git a/fs/ocfs2/symlink.h b/fs/ocfs2/symlink.h index 1ea9e4d9e9e..65a6c9c6ad5 100644 --- a/fs/ocfs2/symlink.h +++ b/fs/ocfs2/symlink.h @@ -26,8 +26,8 @@ #ifndef OCFS2_SYMLINK_H #define OCFS2_SYMLINK_H -extern struct inode_operations ocfs2_symlink_inode_operations; -extern struct inode_operations ocfs2_fast_symlink_inode_operations; +extern const struct inode_operations ocfs2_symlink_inode_operations; +extern const struct inode_operations ocfs2_fast_symlink_inode_operations; /* * Test whether an inode is a fast symlink. diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 99c0bc37ba0..bde1c164417 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -169,7 +169,7 @@ static const struct file_operations openprom_operations = { static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *); -static struct inode_operations openprom_inode_operations = { +static const struct inode_operations openprom_inode_operations = { .lookup = openpromfs_lookup, }; @@ -364,7 +364,7 @@ static int openprom_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations openprom_sops = { +static const struct super_operations openprom_sops = { .alloc_inode = openprom_alloc_inode, .destroy_inode = openprom_destroy_inode, .read_inode = openprom_read_inode, diff --git a/fs/proc/array.c b/fs/proc/array.c index 70e4fab117b..07c9cdbcdca 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -351,7 +351,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) struct signal_struct *sig = task->signal; if (sig->tty) { - tty_pgrp = sig->tty->pgrp; + tty_pgrp = pid_nr(sig->tty->pgrp); tty_nr = new_encode_dev(tty_devnum(sig->tty)); } diff --git a/fs/proc/base.c b/fs/proc/base.c index 7fb37d6f286..4f5745af8c1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -93,8 +93,8 @@ struct pid_entry { int len; char *name; mode_t mode; - struct inode_operations *iop; - struct file_operations *fop; + const struct inode_operations *iop; + const struct file_operations *fop; union proc_op op; }; @@ -352,7 +352,7 @@ static int proc_setattr(struct dentry *dentry, struct iattr *attr) return error; } -static struct inode_operations proc_def_inode_operations = { +static const struct inode_operations proc_def_inode_operations = { .setattr = proc_setattr, }; @@ -424,7 +424,7 @@ static unsigned mounts_poll(struct file *file, poll_table *wait) return res; } -static struct file_operations proc_mounts_operations = { +static const struct file_operations proc_mounts_operations = { .open = mounts_open, .read = seq_read, .llseek = seq_lseek, @@ -462,7 +462,7 @@ static int mountstats_open(struct inode *inode, struct file *file) return ret; } -static struct file_operations proc_mountstats_operations = { +static const struct file_operations proc_mountstats_operations = { .open = mountstats_open, .read = seq_read, .llseek = seq_lseek, @@ -501,7 +501,7 @@ out_no_task: return length; } -static struct file_operations proc_info_file_operations = { +static const struct file_operations proc_info_file_operations = { .read = proc_info_read, }; @@ -646,7 +646,7 @@ static loff_t mem_lseek(struct file * file, loff_t offset, int orig) return file->f_pos; } -static struct file_operations proc_mem_operations = { +static const struct file_operations proc_mem_operations = { .llseek = mem_lseek, .read = mem_read, .write = mem_write, @@ -710,7 +710,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, return end - buffer; } -static struct file_operations proc_oom_adjust_operations = { +static const struct file_operations proc_oom_adjust_operations = { .read = oom_adjust_read, .write = oom_adjust_write, }; @@ -777,7 +777,7 @@ out_free_page: return length; } -static struct file_operations proc_loginuid_operations = { +static const struct file_operations proc_loginuid_operations = { .read = proc_loginuid_read, .write = proc_loginuid_write, }; @@ -849,7 +849,7 @@ out_no_task: return result; } -static struct file_operations proc_seccomp_operations = { +static const struct file_operations proc_seccomp_operations = { .read = seccomp_read, .write = seccomp_write, }; @@ -908,7 +908,7 @@ static ssize_t proc_fault_inject_write(struct file * file, return end - buffer; } -static struct file_operations proc_fault_inject_operations = { +static const struct file_operations proc_fault_inject_operations = { .read = proc_fault_inject_read, .write = proc_fault_inject_write, }; @@ -980,7 +980,7 @@ out: return error; } -static struct inode_operations proc_pid_link_inode_operations = { +static const struct inode_operations proc_pid_link_inode_operations = { .readlink = proc_pid_readlink, .follow_link = proc_pid_follow_link, .setattr = proc_setattr, @@ -1408,7 +1408,7 @@ out_no_task: return retval; } -static struct file_operations proc_fd_operations = { +static const struct file_operations proc_fd_operations = { .read = generic_read_dir, .readdir = proc_readfd, }; @@ -1416,7 +1416,7 @@ static struct file_operations proc_fd_operations = { /* * proc directories can do almost nothing.. */ -static struct inode_operations proc_fd_inode_operations = { +static const struct inode_operations proc_fd_inode_operations = { .lookup = proc_lookupfd, .setattr = proc_setattr, }; @@ -1623,7 +1623,7 @@ out_no_task: return length; } -static struct file_operations proc_pid_attr_operations = { +static const struct file_operations proc_pid_attr_operations = { .read = proc_pid_attr_read, .write = proc_pid_attr_write, }; @@ -1644,7 +1644,7 @@ static int proc_attr_dir_readdir(struct file * filp, attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff)); } -static struct file_operations proc_attr_dir_operations = { +static const struct file_operations proc_attr_dir_operations = { .read = generic_read_dir, .readdir = proc_attr_dir_readdir, }; @@ -1656,7 +1656,7 @@ static struct dentry *proc_attr_dir_lookup(struct inode *dir, attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); } -static struct inode_operations proc_attr_dir_inode_operations = { +static const struct inode_operations proc_attr_dir_inode_operations = { .lookup = proc_attr_dir_lookup, .getattr = pid_getattr, .setattr = proc_setattr, @@ -1682,7 +1682,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) return ERR_PTR(vfs_follow_link(nd,tmp)); } -static struct inode_operations proc_self_inode_operations = { +static const struct inode_operations proc_self_inode_operations = { .readlink = proc_self_readlink, .follow_link = proc_self_follow_link, }; @@ -1834,8 +1834,8 @@ static int proc_pid_io_accounting(struct task_struct *task, char *buffer) /* * Thread groups */ -static struct file_operations proc_task_operations; -static struct inode_operations proc_task_inode_operations; +static const struct file_operations proc_task_operations; +static const struct inode_operations proc_task_inode_operations; static struct pid_entry tgid_base_stuff[] = { DIR("task", S_IRUGO|S_IXUGO, task), @@ -1894,7 +1894,7 @@ static int proc_tgid_base_readdir(struct file * filp, tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff)); } -static struct file_operations proc_tgid_base_operations = { +static const struct file_operations proc_tgid_base_operations = { .read = generic_read_dir, .readdir = proc_tgid_base_readdir, }; @@ -1904,7 +1904,7 @@ static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *de tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); } -static struct inode_operations proc_tgid_base_inode_operations = { +static const struct inode_operations proc_tgid_base_inode_operations = { .lookup = proc_tgid_base_lookup, .getattr = pid_getattr, .setattr = proc_setattr, @@ -2177,12 +2177,12 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); } -static struct file_operations proc_tid_base_operations = { +static const struct file_operations proc_tid_base_operations = { .read = generic_read_dir, .readdir = proc_tid_base_readdir, }; -static struct inode_operations proc_tid_base_inode_operations = { +static const struct inode_operations proc_tid_base_inode_operations = { .lookup = proc_tid_base_lookup, .getattr = pid_getattr, .setattr = proc_setattr, @@ -2408,13 +2408,13 @@ static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct return 0; } -static struct inode_operations proc_task_inode_operations = { +static const struct inode_operations proc_task_inode_operations = { .lookup = proc_task_lookup, .getattr = proc_task_getattr, .setattr = proc_setattr, }; -static struct file_operations proc_task_operations = { +static const struct file_operations proc_task_operations = { .read = generic_read_dir, .readdir = proc_task_readdir, }; diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 853cb877d5f..0cdc00d9d97 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -39,7 +39,7 @@ int proc_match(int len, const char *name, struct proc_dir_entry *de) return !memcmp(name, de->name, len); } -static struct file_operations proc_file_operations = { +static const struct file_operations proc_file_operations = { .llseek = proc_file_lseek, .read = proc_file_read, .write = proc_file_write, @@ -265,7 +265,7 @@ static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry, return 0; } -static struct inode_operations proc_file_inode_operations = { +static const struct inode_operations proc_file_inode_operations = { .setattr = proc_notify_change, }; @@ -357,7 +357,7 @@ static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -static struct inode_operations proc_link_inode_operations = { +static const struct inode_operations proc_link_inode_operations = { .readlink = generic_readlink, .follow_link = proc_follow_link, }; @@ -497,7 +497,7 @@ out: unlock_kernel(); * use the in-memory "struct proc_dir_entry" tree to parse * the /proc directory. */ -static struct file_operations proc_dir_operations = { +static const struct file_operations proc_dir_operations = { .read = generic_read_dir, .readdir = proc_readdir, }; @@ -505,7 +505,7 @@ static struct file_operations proc_dir_operations = { /* * proc directories can do almost nothing.. */ -static struct inode_operations proc_dir_inode_operations = { +static const struct inode_operations proc_dir_inode_operations = { .lookup = proc_lookup, .getattr = proc_getattr, .setattr = proc_notify_change, diff --git a/fs/proc/inode.c b/fs/proc/inode.c index e26945ba685..f6722be37dd 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -132,7 +132,7 @@ static int proc_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations proc_sops = { +static const struct super_operations proc_sops = { .alloc_inode = proc_alloc_inode, .destroy_inode = proc_destroy_inode, .read_inode = proc_read_inode, diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 987c773dbb2..277dcd66ebe 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -38,13 +38,13 @@ extern int proc_tgid_stat(struct task_struct *, char *); extern int proc_pid_status(struct task_struct *, char *); extern int proc_pid_statm(struct task_struct *, char *); -extern struct file_operations proc_maps_operations; -extern struct file_operations proc_numa_maps_operations; -extern struct file_operations proc_smaps_operations; +extern const struct file_operations proc_maps_operations; +extern const struct file_operations proc_numa_maps_operations; +extern const struct file_operations proc_smaps_operations; -extern struct file_operations proc_maps_operations; -extern struct file_operations proc_numa_maps_operations; -extern struct file_operations proc_smaps_operations; +extern const struct file_operations proc_maps_operations; +extern const struct file_operations proc_numa_maps_operations; +extern const struct file_operations proc_smaps_operations; void free_proc_entry(struct proc_dir_entry *de); diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index 5ec67257e5f..22f789de390 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -128,7 +128,7 @@ static int proc_nommu_vma_list_open(struct inode *inode, struct file *file) return seq_open(file, &proc_nommu_vma_list_seqop); } -static struct file_operations proc_nommu_vma_list_operations = { +static const struct file_operations proc_nommu_vma_list_operations = { .open = proc_nommu_vma_list_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 5e2d4359c29..e2c4c0a5c90 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -223,7 +223,7 @@ static int fragmentation_open(struct inode *inode, struct file *file) return seq_open(file, &fragmentation_op); } -static struct file_operations fragmentation_file_operations = { +static const struct file_operations fragmentation_file_operations = { .open = fragmentation_open, .read = seq_read, .llseek = seq_lseek, @@ -236,7 +236,7 @@ static int zoneinfo_open(struct inode *inode, struct file *file) return seq_open(file, &zoneinfo_op); } -static struct file_operations proc_zoneinfo_file_operations = { +static const struct file_operations proc_zoneinfo_file_operations = { .open = zoneinfo_open, .read = seq_read, .llseek = seq_lseek, @@ -261,7 +261,7 @@ static int cpuinfo_open(struct inode *inode, struct file *file) return seq_open(file, &cpuinfo_op); } -static struct file_operations proc_cpuinfo_operations = { +static const struct file_operations proc_cpuinfo_operations = { .open = cpuinfo_open, .read = seq_read, .llseek = seq_lseek, @@ -320,7 +320,7 @@ static int devinfo_open(struct inode *inode, struct file *filp) return seq_open(filp, &devinfo_ops); } -static struct file_operations proc_devinfo_operations = { +static const struct file_operations proc_devinfo_operations = { .open = devinfo_open, .read = seq_read, .llseek = seq_lseek, @@ -332,7 +332,7 @@ static int vmstat_open(struct inode *inode, struct file *file) { return seq_open(file, &vmstat_op); } -static struct file_operations proc_vmstat_file_operations = { +static const struct file_operations proc_vmstat_file_operations = { .open = vmstat_open, .read = seq_read, .llseek = seq_lseek, @@ -363,7 +363,7 @@ static int partitions_open(struct inode *inode, struct file *file) { return seq_open(file, &partitions_op); } -static struct file_operations proc_partitions_operations = { +static const struct file_operations proc_partitions_operations = { .open = partitions_open, .read = seq_read, .llseek = seq_lseek, @@ -375,7 +375,7 @@ static int diskstats_open(struct inode *inode, struct file *file) { return seq_open(file, &diskstats_op); } -static struct file_operations proc_diskstats_operations = { +static const struct file_operations proc_diskstats_operations = { .open = diskstats_open, .read = seq_read, .llseek = seq_lseek, @@ -389,7 +389,7 @@ static int modules_open(struct inode *inode, struct file *file) { return seq_open(file, &modules_op); } -static struct file_operations proc_modules_operations = { +static const struct file_operations proc_modules_operations = { .open = modules_open, .read = seq_read, .llseek = seq_lseek, @@ -404,7 +404,7 @@ static int slabinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &slabinfo_op); } -static struct file_operations proc_slabinfo_operations = { +static const struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, .write = slabinfo_write, @@ -438,7 +438,7 @@ static int slabstats_release(struct inode *inode, struct file *file) return seq_release(inode, file); } -static struct file_operations proc_slabstats_operations = { +static const struct file_operations proc_slabstats_operations = { .open = slabstats_open, .read = seq_read, .llseek = seq_lseek, @@ -551,7 +551,7 @@ static int stat_open(struct inode *inode, struct file *file) kfree(buf); return res; } -static struct file_operations proc_stat_operations = { +static const struct file_operations proc_stat_operations = { .open = stat_open, .read = seq_read, .llseek = seq_lseek, @@ -593,7 +593,7 @@ static int interrupts_open(struct inode *inode, struct file *filp) return seq_open(filp, &int_seq_ops); } -static struct file_operations proc_interrupts_operations = { +static const struct file_operations proc_interrupts_operations = { .open = interrupts_open, .read = seq_read, .llseek = seq_lseek, @@ -650,7 +650,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, return count; } -static struct file_operations proc_sysrq_trigger_operations = { +static const struct file_operations proc_sysrq_trigger_operations = { .write = write_sysrq_trigger, }; #endif diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index 15c4455b09e..c1bbfbeb035 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c @@ -138,7 +138,7 @@ static int tty_drivers_open(struct inode *inode, struct file *file) return seq_open(file, &tty_drivers_op); } -static struct file_operations proc_tty_drivers_operations = { +static const struct file_operations proc_tty_drivers_operations = { .open = tty_drivers_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/proc/root.c b/fs/proc/root.c index 64d242b6dcf..af154458b54 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -136,7 +136,7 @@ static int proc_root_readdir(struct file * filp, * <pid> directories. Thus we don't use the generic * directory handling functions for that.. */ -static struct file_operations proc_root_operations = { +static const struct file_operations proc_root_operations = { .read = generic_read_dir, .readdir = proc_root_readdir, }; @@ -144,7 +144,7 @@ static struct file_operations proc_root_operations = { /* * proc root can do almost nothing.. */ -static struct inode_operations proc_root_inode_operations = { +static const struct inode_operations proc_root_inode_operations = { .lookup = proc_root_lookup, .getattr = proc_root_getattr, }; diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 55ade0d1562..7445980c802 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -434,7 +434,7 @@ static int maps_open(struct inode *inode, struct file *file) return do_maps_open(inode, file, &proc_pid_maps_op); } -struct file_operations proc_maps_operations = { +const struct file_operations proc_maps_operations = { .open = maps_open, .read = seq_read, .llseek = seq_lseek, @@ -456,7 +456,7 @@ static int numa_maps_open(struct inode *inode, struct file *file) return do_maps_open(inode, file, &proc_pid_numa_maps_op); } -struct file_operations proc_numa_maps_operations = { +const struct file_operations proc_numa_maps_operations = { .open = numa_maps_open, .read = seq_read, .llseek = seq_lseek, @@ -469,7 +469,7 @@ static int smaps_open(struct inode *inode, struct file *file) return do_maps_open(inode, file, &proc_pid_smaps_op); } -struct file_operations proc_smaps_operations = { +const struct file_operations proc_smaps_operations = { .open = smaps_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index fcc5caf93f5..7cddf6b8635 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -220,7 +220,7 @@ static int maps_open(struct inode *inode, struct file *file) return ret; } -struct file_operations proc_maps_operations = { +const struct file_operations proc_maps_operations = { .open = maps_open, .read = seq_read, .llseek = seq_lseek, diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index c94db1db7a7..ea9ffefb48a 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c @@ -87,7 +87,7 @@ const struct file_operations qnx4_dir_operations = .fsync = file_fsync, }; -struct inode_operations qnx4_dir_inode_operations = +const struct inode_operations qnx4_dir_inode_operations = { .lookup = qnx4_lookup, #ifdef CONFIG_QNX4FS_RW diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index 467e5ac7280..44649981bbc 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c @@ -33,7 +33,7 @@ const struct file_operations qnx4_file_operations = #endif }; -struct inode_operations qnx4_file_inode_operations = +const struct inode_operations qnx4_file_inode_operations = { #ifdef CONFIG_QNX4FS_RW .truncate = qnx4_truncate, diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index c047dc654d5..83bc8e7824c 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -30,7 +30,7 @@ #define QNX4_VERSION 4 #define QNX4_BMNAME ".bitmap" -static struct super_operations qnx4_sops; +static const struct super_operations qnx4_sops; #ifdef CONFIG_QNX4FS_RW @@ -129,7 +129,7 @@ static void qnx4_read_inode(struct inode *); static int qnx4_remount(struct super_block *sb, int *flags, char *data); static int qnx4_statfs(struct dentry *, struct kstatfs *); -static struct super_operations qnx4_sops = +static const struct super_operations qnx4_sops = { .alloc_inode = qnx4_alloc_inode, .destroy_inode = qnx4_destroy_inode, diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index b935a3dd4b6..2f14774a124 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c @@ -45,6 +45,6 @@ const struct file_operations ramfs_file_operations = { .llseek = generic_file_llseek, }; -struct inode_operations ramfs_file_inode_operations = { +const struct inode_operations ramfs_file_inode_operations = { .getattr = simple_getattr, }; diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index d05e09ac9a9..d3fd7c6732d 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -47,7 +47,7 @@ const struct file_operations ramfs_file_operations = { .llseek = generic_file_llseek, }; -struct inode_operations ramfs_file_inode_operations = { +const struct inode_operations ramfs_file_inode_operations = { .setattr = ramfs_nommu_setattr, .getattr = simple_getattr, }; diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 2faf4cdf61b..ff1f7639707 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -40,8 +40,8 @@ /* some random number */ #define RAMFS_MAGIC 0x858458f6 -static struct super_operations ramfs_ops; -static struct inode_operations ramfs_dir_inode_operations; +static const struct super_operations ramfs_ops; +static const struct inode_operations ramfs_dir_inode_operations; static struct backing_dev_info ramfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ @@ -143,7 +143,7 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * return error; } -static struct inode_operations ramfs_dir_inode_operations = { +static const struct inode_operations ramfs_dir_inode_operations = { .create = ramfs_create, .lookup = simple_lookup, .link = simple_link, @@ -155,7 +155,7 @@ static struct inode_operations ramfs_dir_inode_operations = { .rename = simple_rename, }; -static struct super_operations ramfs_ops = { +static const struct super_operations ramfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, }; diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h index c2bb58e7465..af7cc074a47 100644 --- a/fs/ramfs/internal.h +++ b/fs/ramfs/internal.h @@ -12,4 +12,4 @@ extern const struct address_space_operations ramfs_aops; extern const struct file_operations ramfs_file_operations; -extern struct inode_operations ramfs_file_inode_operations; +extern const struct inode_operations ramfs_file_inode_operations; diff --git a/fs/read_write.c b/fs/read_write.c index bcb0ef2aae3..1f8dc373ede 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -197,13 +197,13 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count struct inode *inode; loff_t pos; + inode = file->f_path.dentry->d_inode; if (unlikely((ssize_t) count < 0)) goto Einval; pos = *ppos; if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) goto Einval; - inode = file->f_path.dentry->d_inode; if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) { int retval = locks_mandatory_area( read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index fba304e64de..f85c5cf4934 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c @@ -19,6 +19,7 @@ #include <linux/time.h> #include <linux/reiserfs_fs.h> #include <linux/buffer_head.h> +#include <linux/kernel.h> #ifdef CONFIG_REISERFS_CHECK @@ -1756,7 +1757,7 @@ static void store_thrown(struct tree_balance *tb, struct buffer_head *bh) if (buffer_dirty(bh)) reiserfs_warning(tb->tb_sb, "store_thrown deals with dirty buffer"); - for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++) + for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) if (!tb->thrown[i]) { tb->thrown[i] = bh; get_bh(bh); /* free_thrown puts this */ @@ -1769,7 +1770,7 @@ static void free_thrown(struct tree_balance *tb) { int i; b_blocknr_t blocknr; - for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++) { + for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) { if (tb->thrown[i]) { blocknr = tb->thrown[i]->b_blocknr; if (buffer_dirty(tb->thrown[i])) diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 5109f1d5e7f..abfada2f52d 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -1556,7 +1556,7 @@ const struct file_operations reiserfs_file_operations = { .splice_write = generic_file_splice_write, }; -struct inode_operations reiserfs_file_inode_operations = { +const struct inode_operations reiserfs_file_inode_operations = { .truncate = reiserfs_vfs_truncate_file, .setattr = reiserfs_setattr, .setxattr = reiserfs_setxattr, diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 23f5cd5bbf5..a2161840bc7 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -1525,7 +1525,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, /* * directories can handle most operations... */ -struct inode_operations reiserfs_dir_inode_operations = { +const struct inode_operations reiserfs_dir_inode_operations = { //&reiserfs_dir_operations, /* default_file_ops */ .create = reiserfs_create, .lookup = reiserfs_lookup, @@ -1548,7 +1548,7 @@ struct inode_operations reiserfs_dir_inode_operations = { * symlink operations.. same as page_symlink_inode_operations, with xattr * stuff added */ -struct inode_operations reiserfs_symlink_inode_operations = { +const struct inode_operations reiserfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, @@ -1564,7 +1564,7 @@ struct inode_operations reiserfs_symlink_inode_operations = { /* * special file operations.. just xattr/acl stuff */ -struct inode_operations reiserfs_special_inode_operations = { +const struct inode_operations reiserfs_special_inode_operations = { .setattr = reiserfs_setattr, .setxattr = reiserfs_setxattr, .getxattr = reiserfs_getxattr, diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 58ad4551a7c..f13a7f164dc 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -593,7 +593,7 @@ static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t, loff_t); #endif -static struct super_operations reiserfs_sops = { +static const struct super_operations reiserfs_sops = { .alloc_inode = reiserfs_alloc_inode, .destroy_inode = reiserfs_destroy_inode, .write_inode = reiserfs_write_inode, diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index d3e243a6f60..fd601014813 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -110,7 +110,7 @@ romfs_checksum(void *data, int size) return sum; } -static struct super_operations romfs_ops; +static const struct super_operations romfs_ops; static int romfs_fill_super(struct super_block *s, void *data, int silent) { @@ -468,7 +468,7 @@ static const struct file_operations romfs_dir_operations = { .readdir = romfs_readdir, }; -static struct inode_operations romfs_dir_inode_operations = { +static const struct inode_operations romfs_dir_inode_operations = { .lookup = romfs_lookup, }; @@ -598,7 +598,7 @@ static int romfs_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations romfs_ops = { +static const struct super_operations romfs_ops = { .alloc_inode = romfs_alloc_inode, .destroy_inode = romfs_destroy_inode, .read_inode = romfs_read_inode, diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index b1e58d1ac9c..50136b1a3ec 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -42,7 +42,7 @@ const struct file_operations smb_dir_operations = .open = smb_dir_open, }; -struct inode_operations smb_dir_inode_operations = +const struct inode_operations smb_dir_inode_operations = { .create = smb_create, .lookup = smb_lookup, @@ -54,7 +54,7 @@ struct inode_operations smb_dir_inode_operations = .setattr = smb_notify_change, }; -struct inode_operations smb_dir_inode_operations_unix = +const struct inode_operations smb_dir_inode_operations_unix = { .create = smb_create, .lookup = smb_lookup, diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index e50533a7951..f161797160c 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -418,7 +418,7 @@ const struct file_operations smb_file_operations = .sendfile = smb_file_sendfile, }; -struct inode_operations smb_file_inode_operations = +const struct inode_operations smb_file_inode_operations = { .permission = smb_file_permission, .getattr = smb_getattr, diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 84dfe3f3482..5faba4f1c9a 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -98,7 +98,7 @@ static int smb_remount(struct super_block *sb, int *flags, char *data) return 0; } -static struct super_operations smb_sops = +static const struct super_operations smb_sops = { .alloc_inode = smb_alloc_inode, .destroy_inode = smb_destroy_inode, diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h index 34fb462b237..03f456c1b7d 100644 --- a/fs/smbfs/proto.h +++ b/fs/smbfs/proto.h @@ -36,8 +36,8 @@ extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, stru extern void smb_install_null_ops(struct smb_ops *ops); /* dir.c */ extern const struct file_operations smb_dir_operations; -extern struct inode_operations smb_dir_inode_operations; -extern struct inode_operations smb_dir_inode_operations_unix; +extern const struct inode_operations smb_dir_inode_operations; +extern const struct inode_operations smb_dir_inode_operations_unix; extern void smb_new_dentry(struct dentry *dentry); extern void smb_renew_times(struct dentry *dentry); /* cache.c */ @@ -65,7 +65,7 @@ extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); /* file.c */ extern const struct address_space_operations smb_file_aops; extern const struct file_operations smb_file_operations; -extern struct inode_operations smb_file_inode_operations; +extern const struct inode_operations smb_file_inode_operations; /* ioctl.c */ extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); /* smbiod.c */ @@ -84,4 +84,4 @@ extern int smb_request_send_server(struct smb_sb_info *server); extern int smb_request_recv(struct smb_sb_info *server); /* symlink.c */ extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname); -extern struct inode_operations smb_link_inode_operations; +extern const struct inode_operations smb_link_inode_operations; diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c index cdc53c4fb38..e4bf3456d07 100644 --- a/fs/smbfs/symlink.c +++ b/fs/smbfs/symlink.c @@ -62,7 +62,7 @@ static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p) __putname(s); } -struct inode_operations smb_link_inode_operations = +const struct inode_operations smb_link_inode_operations = { .readlink = generic_readlink, .follow_link = smb_follow_link, diff --git a/fs/super.c b/fs/super.c index 3e7458c2bb7..60b1e50cbf5 100644 --- a/fs/super.c +++ b/fs/super.c @@ -285,7 +285,7 @@ int fsync_super(struct super_block *sb) */ void generic_shutdown_super(struct super_block *sb) { - struct super_operations *sop = sb->s_op; + const struct super_operations *sop = sb->s_op; if (sb->s_root) { shrink_dcache_for_umount(sb); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9e95e7abaf6..8813990304f 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -296,7 +296,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, return ERR_PTR(err); } -struct inode_operations sysfs_dir_inode_operations = { +const struct inode_operations sysfs_dir_inode_operations = { .lookup = sysfs_lookup, .setattr = sysfs_setattr, }; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 542d2bcc73d..dd1344b007f 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -29,7 +29,7 @@ static struct backing_dev_info sysfs_backing_dev_info = { .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, }; -static struct inode_operations sysfs_inode_operations ={ +static const struct inode_operations sysfs_inode_operations ={ .setattr = sysfs_setattr, }; diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index f6a87a82488..23a48a38e6a 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -21,7 +21,7 @@ struct kmem_cache *sysfs_dir_cachep; static void sysfs_clear_inode(struct inode *inode); -static struct super_operations sysfs_ops = { +static const struct super_operations sysfs_ops = { .statfs = simple_statfs, .drop_inode = sysfs_delete_inode, .clear_inode = sysfs_clear_inode, diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 4869f611192..7b9c5bfde92 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -181,7 +181,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co free_page((unsigned long)page); } -struct inode_operations sysfs_symlink_inode_operations = { +const struct inode_operations sysfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = sysfs_follow_link, .put_link = sysfs_put_link, diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index fe1cbfd208e..d976b000554 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -26,8 +26,8 @@ extern struct super_block * sysfs_sb; extern const struct file_operations sysfs_dir_operations; extern const struct file_operations sysfs_file_operations; extern const struct file_operations bin_fops; -extern struct inode_operations sysfs_dir_inode_operations; -extern struct inode_operations sysfs_symlink_inode_operations; +extern const struct inode_operations sysfs_dir_inode_operations; +extern const struct inode_operations sysfs_symlink_inode_operations; struct sysfs_symlink { char * link_name; diff --git a/fs/sysv/file.c b/fs/sysv/file.c index 47a4b728f15..0732ddb9020 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -30,7 +30,7 @@ const struct file_operations sysv_file_operations = { .sendfile = generic_file_sendfile, }; -struct inode_operations sysv_file_inode_operations = { +const struct inode_operations sysv_file_inode_operations = { .truncate = sysv_truncate, .getattr = sysv_getattr, }; diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index ead9864567e..9311cac186f 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -142,7 +142,7 @@ static inline void write3byte(struct sysv_sb_info *sbi, } } -static struct inode_operations sysv_symlink_inode_operations = { +static const struct inode_operations sysv_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, .put_link = page_put_link, @@ -327,7 +327,7 @@ static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags) inode_init_once(&si->vfs_inode); } -struct super_operations sysv_sops = { +const struct super_operations sysv_sops = { .alloc_inode = sysv_alloc_inode, .destroy_inode = sysv_destroy_inode, .read_inode = sysv_read_inode, diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index f7c08db8e34..4e48abbd2b5 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -292,7 +292,7 @@ out: /* * directories can handle most operations... */ -struct inode_operations sysv_dir_inode_operations = { +const struct inode_operations sysv_dir_inode_operations = { .create = sysv_create, .lookup = sysv_lookup, .link = sysv_link, diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c index b85ce61d635..00d2f8a43e4 100644 --- a/fs/sysv/symlink.c +++ b/fs/sysv/symlink.c @@ -14,7 +14,7 @@ static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations sysv_fast_symlink_inode_operations = { +const struct inode_operations sysv_fast_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = sysv_follow_link, }; diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index dcb18b2171f..5b4fedf17cc 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h @@ -159,13 +159,13 @@ extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct page **); extern ino_t sysv_inode_by_name(struct dentry *); -extern struct inode_operations sysv_file_inode_operations; -extern struct inode_operations sysv_dir_inode_operations; -extern struct inode_operations sysv_fast_symlink_inode_operations; +extern const struct inode_operations sysv_file_inode_operations; +extern const struct inode_operations sysv_dir_inode_operations; +extern const struct inode_operations sysv_fast_symlink_inode_operations; extern const struct file_operations sysv_file_operations; extern const struct file_operations sysv_dir_operations; extern const struct address_space_operations sysv_aops; -extern struct super_operations sysv_sops; +extern const struct super_operations sysv_sops; extern struct dentry_operations sysv_dentry_operations; diff --git a/fs/udf/file.c b/fs/udf/file.c index d81f2db7b0e..40d5047defe 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -263,6 +263,6 @@ const struct file_operations udf_file_operations = { .sendfile = generic_file_sendfile, }; -struct inode_operations udf_file_inode_operations = { +const struct inode_operations udf_file_inode_operations = { .truncate = udf_truncate, }; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 73163325e5e..fe361cd19a9 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -1308,7 +1308,7 @@ end_rename: return retval; } -struct inode_operations udf_dir_inode_operations = { +const struct inode_operations udf_dir_inode_operations = { .lookup = udf_lookup, .create = udf_create, .link = udf_link, diff --git a/fs/udf/super.c b/fs/udf/super.c index 1dbc2955f02..8672b88f7ff 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -160,7 +160,7 @@ static void destroy_inodecache(void) } /* Superblock operations */ -static struct super_operations udf_sb_ops = { +static const struct super_operations udf_sb_ops = { .alloc_inode = udf_alloc_inode, .destroy_inode = udf_destroy_inode, .write_inode = udf_write_inode, diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1033b7cf293..ee1dece1f6f 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -42,9 +42,9 @@ struct task_struct; struct buffer_head; struct super_block; -extern struct inode_operations udf_dir_inode_operations; +extern const struct inode_operations udf_dir_inode_operations; extern const struct file_operations udf_dir_operations; -extern struct inode_operations udf_file_inode_operations; +extern const struct inode_operations udf_file_inode_operations; extern const struct file_operations udf_file_operations; extern const struct address_space_operations udf_aops; extern const struct address_space_operations udf_adinicb_aops; diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 638f4c585e8..0e97a4f79c3 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -4,6 +4,8 @@ * Copyright (C) 1998 * Daniel Pirkl <daniel.pirkl@email.cz> * Charles University, Faculty of Mathematics and Physics + * + * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007 */ #include <linux/fs.h> @@ -21,38 +23,42 @@ #include "swab.h" #include "util.h" -static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *); -static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *); -static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *); -static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned); +#define INVBLOCK ((u64)-1L) + +static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *); +static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *); +static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *); +static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned); static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[]; static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int); /* * Free 'count' fragments from fragment number 'fragment' */ -void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count) +void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) { struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; - unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno; + unsigned cgno, bit, end_bit, bbase, blkmap, i; + u64 blkno; sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; usb1 = ubh_get_usb_first(uspi); - UFSD("ENTER, fragment %u, count %u\n", fragment, count); + UFSD("ENTER, fragment %llu, count %u\n", + (unsigned long long)fragment, count); if (ufs_fragnum(fragment) + count > uspi->s_fpg) ufs_error (sb, "ufs_free_fragments", "internal error"); lock_super(sb); - cgno = ufs_dtog(fragment); - bit = ufs_dtogd(fragment); + cgno = ufs_dtog(uspi, fragment); + bit = ufs_dtogd(uspi, fragment); if (cgno >= uspi->s_ncg) { ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device"); goto failed; @@ -101,9 +107,13 @@ void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count) fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); uspi->cs_total.cs_nbfree++; fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); - cylno = ufs_cbtocylno (bbase); - fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1); - fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); + if (uspi->fs_magic != UFS2_MAGIC) { + unsigned cylno = ufs_cbtocylno (bbase); + + fs16_add(sb, &ubh_cg_blks(ucpi, cylno, + ufs_cbtorpos(bbase)), 1); + fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); + } } ubh_mark_buffer_dirty (USPI_UBH(uspi)); @@ -127,24 +137,27 @@ failed: /* * Free 'count' fragments from fragment number 'fragment' (free whole blocks) */ -void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count) +void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) { struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; - unsigned overflow, cgno, bit, end_bit, blkno, i, cylno; + unsigned overflow, cgno, bit, end_bit, i; + u64 blkno; sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; usb1 = ubh_get_usb_first(uspi); - UFSD("ENTER, fragment %u, count %u\n", fragment, count); + UFSD("ENTER, fragment %llu, count %u\n", + (unsigned long long)fragment, count); if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) { ufs_error (sb, "ufs_free_blocks", "internal error, " - "fragment %u, count %u\n", fragment, count); + "fragment %llu, count %u\n", + (unsigned long long)fragment, count); goto failed; } @@ -152,8 +165,8 @@ void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count) do_more: overflow = 0; - cgno = ufs_dtog (fragment); - bit = ufs_dtogd (fragment); + cgno = ufs_dtog(uspi, fragment); + bit = ufs_dtogd(uspi, fragment); if (cgno >= uspi->s_ncg) { ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device"); goto failed_unlock; @@ -187,9 +200,14 @@ do_more: fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); uspi->cs_total.cs_nbfree++; fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); - cylno = ufs_cbtocylno(i); - fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1); - fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); + + if (uspi->fs_magic != UFS2_MAGIC) { + unsigned cylno = ufs_cbtocylno(i); + + fs16_add(sb, &ubh_cg_blks(ucpi, cylno, + ufs_cbtorpos(i)), 1); + fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); + } } ubh_mark_buffer_dirty (USPI_UBH(uspi)); @@ -308,15 +326,19 @@ static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n, } } -unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, - unsigned goal, unsigned count, int * err, struct page *locked_page) +u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, + u64 goal, unsigned count, int *err, + struct page *locked_page) { struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; - unsigned cgno, oldcount, newcount, tmp, request, result; + unsigned cgno, oldcount, newcount; + u64 tmp, request, result; - UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count); + UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n", + inode->i_ino, (unsigned long long)fragment, + (unsigned long long)goal, count); sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; @@ -324,11 +346,12 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, *err = -ENOSPC; lock_super (sb); - - tmp = fs32_to_cpu(sb, *p); + tmp = ufs_data_ptr_to_cpu(sb, p); + if (count + ufs_fragnum(fragment) > uspi->s_fpb) { - ufs_warning (sb, "ufs_new_fragments", "internal warning" - " fragment %u, count %u", fragment, count); + ufs_warning(sb, "ufs_new_fragments", "internal warning" + " fragment %llu, count %u", + (unsigned long long)fragment, count); count = uspi->s_fpb - ufs_fragnum(fragment); } oldcount = ufs_fragnum (fragment); @@ -339,10 +362,12 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, */ if (oldcount) { if (!tmp) { - ufs_error (sb, "ufs_new_fragments", "internal error, " - "fragment %u, tmp %u\n", fragment, tmp); - unlock_super (sb); - return (unsigned)-1; + ufs_error(sb, "ufs_new_fragments", "internal error, " + "fragment %llu, tmp %llu\n", + (unsigned long long)fragment, + (unsigned long long)tmp); + unlock_super(sb); + return INVBLOCK; } if (fragment < UFS_I(inode)->i_lastfrag) { UFSD("EXIT (ALREADY ALLOCATED)\n"); @@ -372,7 +397,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, if (goal == 0) cgno = ufs_inotocg (inode->i_ino); else - cgno = ufs_dtog (goal); + cgno = ufs_dtog(uspi, goal); /* * allocate new fragment @@ -380,14 +405,16 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, if (oldcount == 0) { result = ufs_alloc_fragments (inode, cgno, goal, count, err); if (result) { - *p = cpu_to_fs32(sb, result); + ufs_cpu_to_data_ptr(sb, p, result); *err = 0; - UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); - ufs_clear_frags(inode, result + oldcount, newcount - oldcount, - locked_page != NULL); + UFS_I(inode)->i_lastfrag = + max_t(u32, UFS_I(inode)->i_lastfrag, + fragment + count); + ufs_clear_frags(inode, result + oldcount, + newcount - oldcount, locked_page != NULL); } unlock_super(sb); - UFSD("EXIT, result %u\n", result); + UFSD("EXIT, result %llu\n", (unsigned long long)result); return result; } @@ -401,7 +428,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, ufs_clear_frags(inode, result + oldcount, newcount - oldcount, locked_page != NULL); unlock_super(sb); - UFSD("EXIT, result %u\n", result); + UFSD("EXIT, result %llu\n", (unsigned long long)result); return result; } @@ -433,15 +460,14 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, locked_page != NULL); ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp, result, locked_page); - - *p = cpu_to_fs32(sb, result); + ufs_cpu_to_data_ptr(sb, p, result); *err = 0; UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); unlock_super(sb); if (newcount < request) ufs_free_fragments (inode, result + newcount, request - newcount); ufs_free_fragments (inode, tmp, oldcount); - UFSD("EXIT, result %u\n", result); + UFSD("EXIT, result %llu\n", (unsigned long long)result); return result; } @@ -450,9 +476,8 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, return 0; } -static unsigned -ufs_add_fragments (struct inode * inode, unsigned fragment, - unsigned oldcount, unsigned newcount, int * err) +static u64 ufs_add_fragments(struct inode *inode, u64 fragment, + unsigned oldcount, unsigned newcount, int *err) { struct super_block * sb; struct ufs_sb_private_info * uspi; @@ -461,14 +486,15 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, struct ufs_cylinder_group * ucg; unsigned cgno, fragno, fragoff, count, fragsize, i; - UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount); + UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n", + (unsigned long long)fragment, oldcount, newcount); sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; usb1 = ubh_get_usb_first (uspi); count = newcount - oldcount; - cgno = ufs_dtog(fragment); + cgno = ufs_dtog(uspi, fragment); if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count) return 0; if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb) @@ -483,7 +509,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, return 0; } - fragno = ufs_dtogd (fragment); + fragno = ufs_dtogd(uspi, fragment); fragoff = ufs_fragnum (fragno); for (i = oldcount; i < newcount; i++) if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) @@ -521,7 +547,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, } sb->s_dirt = 1; - UFSD("EXIT, fragment %u\n", fragment); + UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); return fragment; } @@ -534,17 +560,19 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \ goto cg_found; -static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno, - unsigned goal, unsigned count, int * err) +static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno, + u64 goal, unsigned count, int *err) { struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_cg_private_info * ucpi; struct ufs_cylinder_group * ucg; - unsigned oldcg, i, j, k, result, allocsize; + unsigned oldcg, i, j, k, allocsize; + u64 result; - UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count); + UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n", + inode->i_ino, cgno, (unsigned long long)goal, count); sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; @@ -593,7 +621,7 @@ cg_found: if (count == uspi->s_fpb) { result = ufs_alloccg_block (inode, ucpi, goal, err); - if (result == (unsigned)-1) + if (result == INVBLOCK) return 0; goto succed; } @@ -604,9 +632,9 @@ cg_found: if (allocsize == uspi->s_fpb) { result = ufs_alloccg_block (inode, ucpi, goal, err); - if (result == (unsigned)-1) + if (result == INVBLOCK) return 0; - goal = ufs_dtogd (result); + goal = ufs_dtogd(uspi, result); for (i = count; i < uspi->s_fpb; i++) ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); i = uspi->s_fpb - count; @@ -620,7 +648,7 @@ cg_found: } result = ufs_bitmap_search (sb, ucpi, goal, allocsize); - if (result == (unsigned)-1) + if (result == INVBLOCK) return 0; if(DQUOT_ALLOC_BLOCK(inode, count)) { *err = -EDQUOT; @@ -647,20 +675,21 @@ succed: sb->s_dirt = 1; result += cgno * uspi->s_fpg; - UFSD("EXIT3, result %u\n", result); + UFSD("EXIT3, result %llu\n", (unsigned long long)result); return result; } -static unsigned ufs_alloccg_block (struct inode * inode, - struct ufs_cg_private_info * ucpi, unsigned goal, int * err) +static u64 ufs_alloccg_block(struct inode *inode, + struct ufs_cg_private_info *ucpi, + u64 goal, int *err) { struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_cylinder_group * ucg; - unsigned result, cylno, blkno; + u64 result, blkno; - UFSD("ENTER, goal %u\n", goal); + UFSD("ENTER, goal %llu\n", (unsigned long long)goal); sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; @@ -672,7 +701,7 @@ static unsigned ufs_alloccg_block (struct inode * inode, goto norot; } goal = ufs_blknum (goal); - goal = ufs_dtogd (goal); + goal = ufs_dtogd(uspi, goal); /* * If the requested block is available, use it. @@ -684,8 +713,8 @@ static unsigned ufs_alloccg_block (struct inode * inode, norot: result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb); - if (result == (unsigned)-1) - return (unsigned)-1; + if (result == INVBLOCK) + return INVBLOCK; ucpi->c_rotor = result; gotit: blkno = ufs_fragstoblks(result); @@ -694,17 +723,22 @@ gotit: ufs_clusteracct (sb, ucpi, blkno, -1); if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) { *err = -EDQUOT; - return (unsigned)-1; + return INVBLOCK; } fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1); uspi->cs_total.cs_nbfree--; fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1); - cylno = ufs_cbtocylno(result); - fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1); - fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1); + + if (uspi->fs_magic != UFS2_MAGIC) { + unsigned cylno = ufs_cbtocylno((unsigned)result); + + fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, + ufs_cbtorpos((unsigned)result)), 1); + fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1); + } - UFSD("EXIT, result %u\n", result); + UFSD("EXIT, result %llu\n", (unsigned long long)result); return result; } @@ -744,9 +778,9 @@ static unsigned ubh_scanc(struct ufs_sb_private_info *uspi, * @goal: near which block we want find new one * @count: specified size */ -static unsigned ufs_bitmap_search(struct super_block *sb, - struct ufs_cg_private_info *ucpi, - unsigned goal, unsigned count) +static u64 ufs_bitmap_search(struct super_block *sb, + struct ufs_cg_private_info *ucpi, + u64 goal, unsigned count) { /* * Bit patterns for identifying fragments in the block map @@ -761,16 +795,18 @@ static unsigned ufs_bitmap_search(struct super_block *sb, struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_super_block_first *usb1; struct ufs_cylinder_group *ucg; - unsigned start, length, loc, result; + unsigned start, length, loc; unsigned pos, want, blockmap, mask, end; + u64 result; - UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count); + UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx, + (unsigned long long)goal, count); usb1 = ubh_get_usb_first (uspi); ucg = ubh_get_ucg(UCPI_UBH(ucpi)); if (goal) - start = ufs_dtogd(goal) >> 3; + start = ufs_dtogd(uspi, goal) >> 3; else start = ucpi->c_frotor >> 3; @@ -790,7 +826,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb, " length %u, count %u, freeoff %u\n", ucpi->c_cgx, start, length, count, ucpi->c_freeoff); - return (unsigned)-1; + return INVBLOCK; } start = 0; } @@ -808,7 +844,8 @@ static unsigned ufs_bitmap_search(struct super_block *sb, want = want_arr[count]; for (pos = 0; pos <= uspi->s_fpb - count; pos++) { if ((blockmap & mask) == want) { - UFSD("EXIT, result %u\n", result); + UFSD("EXIT, result %llu\n", + (unsigned long long)result); return result + pos; } mask <<= 1; @@ -819,7 +856,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb, ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n", ucpi->c_cgx); UFSD("EXIT (FAILED)\n"); - return (unsigned)-1; + return INVBLOCK; } static void ufs_clusteracct(struct super_block * sb, diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 2ad1259c6ec..b868878009b 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -18,6 +18,9 @@ * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 + * + * UFS2 write support added by + * Evgeniy Dushistov <dushistov@mail.ru>, 2007 */ #include <linux/fs.h> @@ -126,6 +129,47 @@ void ufs_free_inode (struct inode * inode) } /* + * Nullify new chunk of inodes, + * BSD people also set ui_gen field of inode + * during nullification, but we not care about + * that because of linux ufs do not support NFS + */ +static void ufs2_init_inodes_chunk(struct super_block *sb, + struct ufs_cg_private_info *ucpi, + struct ufs_cylinder_group *ucg) +{ + struct buffer_head *bh; + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; + sector_t beg = uspi->s_sbbase + + ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg + + fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk)); + sector_t end = beg + uspi->s_fpb; + + UFSD("ENTER cgno %d\n", ucpi->c_cgx); + + for (; beg < end; ++beg) { + bh = sb_getblk(sb, beg); + lock_buffer(bh); + memset(bh->b_data, 0, sb->s_blocksize); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + unlock_buffer(bh); + if (sb->s_flags & MS_SYNCHRONOUS) + sync_dirty_buffer(bh); + brelse(bh); + } + + fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); + ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); + if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); + ubh_wait_on_buffer(UCPI_UBH(ucpi)); + } + + UFSD("EXIT\n"); +} + +/* * There are two policies for allocating an inode. If the new inode is * a directory, then a forward search is made for a block group with both * free space and a low directory-to-inode ratio; if that fails, then of @@ -146,6 +190,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) struct inode * inode; unsigned cg, bit, i, j, start; struct ufs_inode_info *ufsi; + int err = -ENOSPC; UFSD("ENTER\n"); @@ -198,13 +243,15 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) goto cg_found; } } - + goto failed; cg_found: ucpi = ufs_load_cylinder (sb, cg); - if (!ucpi) + if (!ucpi) { + err = -EIO; goto failed; + } ucg = ubh_get_ucg(UCPI_UBH(ucpi)); if (!ufs_cg_chkmagic(sb, ucg)) ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); @@ -216,6 +263,7 @@ cg_found: if (!(bit < start)) { ufs_error (sb, "ufs_new_inode", "cylinder group %u corrupted - error in inode bitmap\n", cg); + err = -EIO; goto failed; } } @@ -224,9 +272,18 @@ cg_found: ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); else { ufs_panic (sb, "ufs_new_inode", "internal error"); + err = -EIO; goto failed; } - + + if (uspi->fs_magic == UFS2_MAGIC) { + u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk); + + if (bit + uspi->s_inopb > initediblk && + initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk)) + ufs2_init_inodes_chunk(sb, ucpi, ucg); + } + fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); uspi->cs_total.cs_nifree--; fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); @@ -236,7 +293,6 @@ cg_found: uspi->cs_total.cs_ndir++; fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); } - ubh_mark_buffer_dirty (USPI_UBH(uspi)); ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); if (sb->s_flags & MS_SYNCHRONOUS) { @@ -245,6 +301,7 @@ cg_found: } sb->s_dirt = 1; + inode->i_ino = cg * uspi->s_ipg + bit; inode->i_mode = mode; inode->i_uid = current->fsuid; if (dir->i_mode & S_ISGID) { @@ -254,39 +311,72 @@ cg_found: } else inode->i_gid = current->fsgid; - inode->i_ino = cg * uspi->s_ipg + bit; inode->i_blocks = 0; + inode->i_generation = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; ufsi->i_flags = UFS_I(dir)->i_flags; ufsi->i_lastfrag = 0; - ufsi->i_gen = 0; ufsi->i_shadow = 0; ufsi->i_osync = 0; ufsi->i_oeftflag = 0; ufsi->i_dir_start_lookup = 0; memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); - insert_inode_hash(inode); mark_inode_dirty(inode); + if (uspi->fs_magic == UFS2_MAGIC) { + struct buffer_head *bh; + struct ufs2_inode *ufs2_inode; + + /* + * setup birth date, we do it here because of there is no sense + * to hold it in struct ufs_inode_info, and lose 64 bit + */ + bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); + if (!bh) { + ufs_warning(sb, "ufs_read_inode", + "unable to read inode %lu\n", + inode->i_ino); + err = -EIO; + goto fail_remove_inode; + } + lock_buffer(bh); + ufs2_inode = (struct ufs2_inode *)bh->b_data; + ufs2_inode += ufs_inotofsbo(inode->i_ino); + ufs2_inode->ui_birthtime.tv_sec = + cpu_to_fs32(sb, CURRENT_TIME_SEC.tv_sec); + ufs2_inode->ui_birthtime.tv_usec = 0; + mark_buffer_dirty(bh); + unlock_buffer(bh); + if (sb->s_flags & MS_SYNCHRONOUS) + sync_dirty_buffer(bh); + brelse(bh); + } + unlock_super (sb); if (DQUOT_ALLOC_INODE(inode)) { DQUOT_DROP(inode); - inode->i_flags |= S_NOQUOTA; - inode->i_nlink = 0; - iput(inode); - return ERR_PTR(-EDQUOT); + err = -EDQUOT; + goto fail_without_unlock; } UFSD("allocating inode %lu\n", inode->i_ino); UFSD("EXIT\n"); return inode; +fail_remove_inode: + unlock_super(sb); +fail_without_unlock: + inode->i_flags |= S_NOQUOTA; + inode->i_nlink = 0; + iput(inode); + UFSD("EXIT (FAILED): err %d\n", err); + return ERR_PTR(err); failed: unlock_super (sb); make_bad_inode(inode); iput (inode); - UFSD("EXIT (FAILED)\n"); - return ERR_PTR(-ENOSPC); + UFSD("EXIT (FAILED): err %d\n", err); + return ERR_PTR(err); } diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 4295ca91cf8..fb34ad03e22 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -170,7 +170,7 @@ out: * @locked_page - for ufs_new_fragments() */ static struct buffer_head * -ufs_inode_getfrag(struct inode *inode, unsigned int fragment, +ufs_inode_getfrag(struct inode *inode, u64 fragment, sector_t new_fragment, unsigned int required, int *err, long *phys, int *new, struct page *locked_page) { @@ -178,12 +178,12 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct buffer_head * result; - unsigned block, blockoff, lastfrag, lastblock, lastblockoff; - unsigned tmp, goal; - __fs32 * p, * p2; + unsigned blockoff, lastblockoff; + u64 tmp, goal, lastfrag, block, lastblock; + void *p, *p2; - UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, " - "metadata %d\n", inode->i_ino, fragment, + UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, " + "metadata %d\n", inode->i_ino, (unsigned long long)fragment, (unsigned long long)new_fragment, required, !phys); /* TODO : to be done for write support @@ -193,17 +193,20 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, block = ufs_fragstoblks (fragment); blockoff = ufs_fragnum (fragment); - p = ufsi->i_u1.i_data + block; + p = ufs_get_direct_data_ptr(uspi, ufsi, block); + goal = 0; repeat: - tmp = fs32_to_cpu(sb, *p); + tmp = ufs_data_ptr_to_cpu(sb, p); + lastfrag = ufsi->i_lastfrag; if (tmp && fragment < lastfrag) { if (!phys) { result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); - if (tmp == fs32_to_cpu(sb, *p)) { - UFSD("EXIT, result %u\n", tmp + blockoff); + if (tmp == ufs_data_ptr_to_cpu(sb, p)) { + UFSD("EXIT, result %llu\n", + (unsigned long long)tmp + blockoff); return result; } brelse (result); @@ -224,10 +227,11 @@ repeat: * We must reallocate last allocated block */ if (lastblockoff) { - p2 = ufsi->i_u1.i_data + lastblock; - tmp = ufs_new_fragments (inode, p2, lastfrag, - fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, - err, locked_page); + p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock); + tmp = ufs_new_fragments(inode, p2, lastfrag, + ufs_data_ptr_to_cpu(sb, p2), + uspi->s_fpb - lastblockoff, + err, locked_page); if (!tmp) { if (lastfrag != ufsi->i_lastfrag) goto repeat; @@ -237,27 +241,31 @@ repeat: lastfrag = ufsi->i_lastfrag; } - tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]); + tmp = ufs_data_ptr_to_cpu(sb, + ufs_get_direct_data_ptr(uspi, ufsi, + lastblock)); if (tmp) goal = tmp + uspi->s_fpb; tmp = ufs_new_fragments (inode, p, fragment - blockoff, goal, required + blockoff, err, phys != NULL ? locked_page : NULL); - } + } else if (lastblock == block) { /* * We will extend last allocated block */ - else if (lastblock == block) { - tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), - fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), + tmp = ufs_new_fragments(inode, p, fragment - + (blockoff - lastblockoff), + ufs_data_ptr_to_cpu(sb, p), + required + (blockoff - lastblockoff), err, phys != NULL ? locked_page : NULL); } else /* (lastblock > block) */ { /* * We will allocate new block before last allocated block */ if (block) { - tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]); + tmp = ufs_data_ptr_to_cpu(sb, + ufs_get_direct_data_ptr(uspi, ufsi, block - 1)); if (tmp) goal = tmp + uspi->s_fpb; } @@ -266,7 +274,7 @@ repeat: phys != NULL ? locked_page : NULL); } if (!tmp) { - if ((!blockoff && *p) || + if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) || (blockoff && lastfrag != ufsi->i_lastfrag)) goto repeat; *err = -ENOSPC; @@ -286,7 +294,7 @@ repeat: if (IS_SYNC(inode)) ufs_sync_inode (inode); mark_inode_dirty(inode); - UFSD("EXIT, result %u\n", tmp + blockoff); + UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff); return result; /* This part : To be implemented .... @@ -320,20 +328,22 @@ repeat2: */ static struct buffer_head * ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, - unsigned int fragment, sector_t new_fragment, int *err, + u64 fragment, sector_t new_fragment, int *err, long *phys, int *new, struct page *locked_page) { struct super_block *sb = inode->i_sb; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct buffer_head * result; - unsigned tmp, goal, block, blockoff; - __fs32 * p; + unsigned blockoff; + u64 tmp, goal, block; + void *p; block = ufs_fragstoblks (fragment); blockoff = ufs_fragnum (fragment); - UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n", - inode->i_ino, fragment, (unsigned long long)new_fragment, !phys); + UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n", + inode->i_ino, (unsigned long long)fragment, + (unsigned long long)new_fragment, !phys); result = NULL; if (!bh) @@ -344,14 +354,16 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, if (!buffer_uptodate(bh)) goto out; } - - p = (__fs32 *) bh->b_data + block; + if (uspi->fs_magic == UFS2_MAGIC) + p = (__fs64 *)bh->b_data + block; + else + p = (__fs32 *)bh->b_data + block; repeat: - tmp = fs32_to_cpu(sb, *p); + tmp = ufs_data_ptr_to_cpu(sb, p); if (tmp) { if (!phys) { result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); - if (tmp == fs32_to_cpu(sb, *p)) + if (tmp == ufs_data_ptr_to_cpu(sb, p)) goto out; brelse (result); goto repeat; @@ -361,14 +373,16 @@ repeat: } } - if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]))) + if (block && (uspi->fs_magic == UFS2_MAGIC ? + (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) : + (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1])))) goal = tmp + uspi->s_fpb; else goal = bh->b_blocknr + uspi->s_fpb; tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err, locked_page); if (!tmp) { - if (fs32_to_cpu(sb, *p)) + if (ufs_data_ptr_to_cpu(sb, p)) goto repeat; goto out; } @@ -386,7 +400,7 @@ repeat: sync_dirty_buffer(bh); inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); - UFSD("result %u\n", tmp + blockoff); + UFSD("result %llu\n", (unsigned long long)tmp + blockoff); out: brelse (bh); UFSD("EXIT\n"); @@ -616,8 +630,8 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); + inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen); ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); - ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen); ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); @@ -661,8 +675,8 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); + inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen); ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); - ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen); /* ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); @@ -731,34 +745,11 @@ bad_inode: make_bad_inode(inode); } -static int ufs_update_inode(struct inode * inode, int do_sync) +static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) { - struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block * sb; - struct ufs_sb_private_info * uspi; - struct buffer_head * bh; - struct ufs_inode * ufs_inode; - unsigned i; - unsigned flags; - - UFSD("ENTER, ino %lu\n", inode->i_ino); - - sb = inode->i_sb; - uspi = UFS_SB(sb)->s_uspi; - flags = UFS_SB(sb)->s_flags; - - if (inode->i_ino < UFS_ROOTINO || - inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { - ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); - return -1; - } - - bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); - if (!bh) { - ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); - return -1; - } - ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode)); + struct super_block *sb = inode->i_sb; + struct ufs_inode_info *ufsi = UFS_I(inode); + unsigned i; ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); @@ -775,9 +766,9 @@ static int ufs_update_inode(struct inode * inode, int do_sync) ufs_inode->ui_mtime.tv_usec = 0; ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks); ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); - ufs_inode->ui_gen = cpu_to_fs32(sb, ufsi->i_gen); + ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); - if ((flags & UFS_UID_MASK) == UFS_UID_EFT) { + if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) { ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow); ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); } @@ -796,6 +787,78 @@ static int ufs_update_inode(struct inode * inode, int do_sync) if (!inode->i_nlink) memset (ufs_inode, 0, sizeof(struct ufs_inode)); +} + +static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) +{ + struct super_block *sb = inode->i_sb; + struct ufs_inode_info *ufsi = UFS_I(inode); + unsigned i; + + UFSD("ENTER\n"); + ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); + ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); + + ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid); + ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid); + + ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); + ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); + ufs_inode->ui_atime.tv_usec = 0; + ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec); + ufs_inode->ui_ctime.tv_usec = 0; + ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec); + ufs_inode->ui_mtime.tv_usec = 0; + + ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks); + ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); + ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); + + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ + ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0]; + } else if (inode->i_blocks) { + for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) + ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i]; + } else { + for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) + ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; + } + + if (!inode->i_nlink) + memset (ufs_inode, 0, sizeof(struct ufs2_inode)); + UFSD("EXIT\n"); +} + +static int ufs_update_inode(struct inode * inode, int do_sync) +{ + struct super_block *sb = inode->i_sb; + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; + struct buffer_head * bh; + + UFSD("ENTER, ino %lu\n", inode->i_ino); + + if (inode->i_ino < UFS_ROOTINO || + inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { + ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); + return -1; + } + + bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); + if (!bh) { + ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); + return -1; + } + if (uspi->fs_magic == UFS2_MAGIC) { + struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; + + ufs2_update_inode(inode, + ufs2_inode + ufs_inotofsbo(inode->i_ino)); + } else { + struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data; + + ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino)); + } mark_buffer_dirty(bh); if (do_sync) diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index e84c0ecf073..a059ccd064e 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -355,7 +355,7 @@ out: return err; } -struct inode_operations ufs_dir_inode_operations = { +const struct inode_operations ufs_dir_inode_operations = { .create = ufs_create, .lookup = ufs_lookup, .link = ufs_link, diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 209be95e9d1..b5a6461ec66 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -61,6 +61,8 @@ * UFS2 (of FreeBSD 5.x) support added by * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004 * + * UFS2 write support added by + * Evgeniy Dushistov <dushistov@mail.ru>, 2007 */ @@ -93,14 +95,16 @@ /* * Print contents of ufs_super_block, useful for debugging */ -static void ufs_print_super_stuff(struct super_block *sb, unsigned flags, +static void ufs_print_super_stuff(struct super_block *sb, struct ufs_super_block_first *usb1, struct ufs_super_block_second *usb2, struct ufs_super_block_third *usb3) { + u32 magic = fs32_to_cpu(sb, usb3->fs_magic); + printk("ufs_print_super_stuff\n"); - printk(" magic: 0x%x\n", fs32_to_cpu(sb, usb3->fs_magic)); - if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { + printk(" magic: 0x%x\n", magic); + if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { printk(" fs_size: %llu\n", (unsigned long long) fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); printk(" fs_dsize: %llu\n", (unsigned long long) @@ -117,6 +121,12 @@ static void ufs_print_super_stuff(struct super_block *sb, unsigned flags, printk(" cs_nbfree(No of free blocks): %llu\n", (unsigned long long) fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); + printk(KERN_INFO" cs_nifree(Num of free inodes): %llu\n", + (unsigned long long) + fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); + printk(KERN_INFO" cs_nffree(Num of free frags): %llu\n", + (unsigned long long) + fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); } else { printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); @@ -199,11 +209,11 @@ static void ufs_print_cylinder_stuff(struct super_block *sb, printk("\n"); } #else -# define ufs_print_super_stuff(sb, flags, usb1, usb2, usb3) /**/ +# define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/ # define ufs_print_cylinder_stuff(sb, cg) /**/ #endif /* CONFIG_UFS_DEBUG */ -static struct super_operations ufs_super_ops; +static const struct super_operations ufs_super_ops; static char error_buf[1024]; @@ -422,7 +432,6 @@ static int ufs_read_cylinder_structures(struct super_block *sb) { struct ufs_sb_info *sbi = UFS_SB(sb); struct ufs_sb_private_info *uspi = sbi->s_uspi; - unsigned flags = sbi->s_flags; struct ufs_buffer_head * ubh; unsigned char * base, * space; unsigned size, blks, i; @@ -446,11 +455,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb) if (i + uspi->s_fpb > blks) size = (blks - i) * uspi->s_fsize; - if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) - ubh = ubh_bread(sb, - fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr) + i, size); - else - ubh = ubh_bread(sb, uspi->s_csaddr + i, size); + ubh = ubh_bread(sb, uspi->s_csaddr + i, size); if (!ubh) goto failed; @@ -545,6 +550,7 @@ static void ufs_put_cstotal(struct super_block *sb) cpu_to_fs32(sb, uspi->cs_total.cs_nffree); } ubh_mark_buffer_dirty(USPI_UBH(uspi)); + ufs_print_super_stuff(sb, usb1, usb2, usb3); UFSD("EXIT\n"); } @@ -572,7 +578,9 @@ static void ufs_put_super_internal(struct super_block *sb) size = uspi->s_bsize; if (i + uspi->s_fpb > blks) size = (blks - i) * uspi->s_fsize; + ubh = ubh_bread(sb, uspi->s_csaddr + i, size); + ubh_memcpyubh (ubh, space, size); space += size; ubh_mark_buffer_uptodate (ubh, 1); @@ -674,10 +682,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_sbsize = super_block_size = 1536; uspi->s_sbbase = 0; flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; - if (!(sb->s_flags & MS_RDONLY)) { - printk(KERN_INFO "ufstype=ufs2 is supported read-only\n"); - sb->s_flags |= MS_RDONLY; - } break; case UFS_MOUNT_UFSTYPE_SUN: @@ -890,7 +894,7 @@ magic_found: } - ufs_print_super_stuff(sb, flags, usb1, usb2, usb3); + ufs_print_super_stuff(sb, usb1, usb2, usb3); /* * Check, if file system was correctly unmounted. @@ -973,7 +977,12 @@ magic_found: uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3); uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave); uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew); - uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); + + if (uspi->fs_magic == UFS2_MAGIC) + uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr); + else + uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); + uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize); uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize); uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak); @@ -1060,7 +1069,6 @@ static void ufs_write_super(struct super_block *sb) unsigned flags; lock_kernel(); - UFSD("ENTER\n"); flags = UFS_SB(sb)->s_flags; uspi = UFS_SB(sb)->s_uspi; @@ -1156,7 +1164,8 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) #else if (ufstype != UFS_MOUNT_UFSTYPE_SUN && ufstype != UFS_MOUNT_UFSTYPE_44BSD && - ufstype != UFS_MOUNT_UFSTYPE_SUNx86) { + ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && + ufstype != UFS_MOUNT_UFSTYPE_UFS2) { printk("this ufstype is read-only supported\n"); return -EINVAL; } @@ -1255,7 +1264,7 @@ static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t); static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t); #endif -static struct super_operations ufs_super_ops = { +static const struct super_operations ufs_super_ops = { .alloc_inode = ufs_alloc_inode, .destroy_inode = ufs_destroy_inode, .read_inode = ufs_read_inode, diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c index 337512ed578..d8549f807e8 100644 --- a/fs/ufs/symlink.c +++ b/fs/ufs/symlink.c @@ -36,7 +36,7 @@ static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -struct inode_operations ufs_fast_symlink_inode_operations = { +const struct inode_operations ufs_fast_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = ufs_follow_link, }; diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 0437b0a6fe9..749581fa772 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -30,8 +30,8 @@ */ /* - * Modified to avoid infinite loop on 2006 by - * Evgeniy Dushistov <dushistov@mail.ru> + * Adoptation to use page cache and UFS2 write support by + * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007 */ #include <linux/errno.h> @@ -63,13 +63,13 @@ #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) -static int ufs_trunc_direct (struct inode * inode) +static int ufs_trunc_direct(struct inode *inode) { struct ufs_inode_info *ufsi = UFS_I(inode); struct super_block * sb; struct ufs_sb_private_info * uspi; - __fs32 * p; - unsigned frag1, frag2, frag3, frag4, block1, block2; + void *p; + u64 frag1, frag2, frag3, frag4, block1, block2; unsigned frag_to_free, free_count; unsigned i, tmp; int retry; @@ -91,13 +91,16 @@ static int ufs_trunc_direct (struct inode * inode) if (frag2 > frag3) { frag2 = frag4; frag3 = frag4 = 0; - } - else if (frag2 < frag3) { + } else if (frag2 < frag3) { block1 = ufs_fragstoblks (frag2); block2 = ufs_fragstoblks (frag3); } - UFSD("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4); + UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu," + " frag4 %llu\n", + (unsigned long long)frag1, (unsigned long long)frag2, + (unsigned long long)block1, (unsigned long long)block2, + (unsigned long long)frag3, (unsigned long long)frag4); if (frag1 >= frag2) goto next1; @@ -105,8 +108,8 @@ static int ufs_trunc_direct (struct inode * inode) /* * Free first free fragments */ - p = ufsi->i_u1.i_data + ufs_fragstoblks (frag1); - tmp = fs32_to_cpu(sb, *p); + p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1)); + tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp ) ufs_panic (sb, "ufs_trunc_direct", "internal error"); frag2 -= frag1; @@ -121,12 +124,11 @@ next1: * Free whole blocks */ for (i = block1 ; i < block2; i++) { - p = ufsi->i_u1.i_data + i; - tmp = fs32_to_cpu(sb, *p); + p = ufs_get_direct_data_ptr(uspi, ufsi, i); + tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) continue; - - *p = 0; + ufs_data_ptr_clear(uspi, p); if (free_count == 0) { frag_to_free = tmp; @@ -150,13 +152,12 @@ next1: /* * Free last free fragments */ - p = ufsi->i_u1.i_data + ufs_fragstoblks (frag3); - tmp = fs32_to_cpu(sb, *p); + p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3)); + tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp ) ufs_panic(sb, "ufs_truncate_direct", "internal error"); frag4 = ufs_fragnum (frag4); - - *p = 0; + ufs_data_ptr_clear(uspi, p); ufs_free_fragments (inode, tmp, frag4); mark_inode_dirty(inode); @@ -167,17 +168,20 @@ next1: } -static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) +static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) { struct super_block * sb; struct ufs_sb_private_info * uspi; struct ufs_buffer_head * ind_ubh; - __fs32 * ind; - unsigned indirect_block, i, tmp; - unsigned frag_to_free, free_count; + void *ind; + u64 tmp, indirect_block, i, frag_to_free; + unsigned free_count; int retry; - UFSD("ENTER\n"); + UFSD("ENTER: ino %lu, offset %llu, p: %p\n", + inode->i_ino, (unsigned long long)offset, p); + + BUG_ON(!p); sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; @@ -186,27 +190,27 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) free_count = 0; retry = 0; - tmp = fs32_to_cpu(sb, *p); + tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) return 0; ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); - if (tmp != fs32_to_cpu(sb, *p)) { + if (tmp != ufs_data_ptr_to_cpu(sb, p)) { ubh_brelse (ind_ubh); return 1; } if (!ind_ubh) { - *p = 0; + ufs_data_ptr_clear(uspi, p); return 0; } indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; for (i = indirect_block; i < uspi->s_apb; i++) { - ind = ubh_get_addr32 (ind_ubh, i); - tmp = fs32_to_cpu(sb, *ind); + ind = ubh_get_data_ptr(uspi, ind_ubh, i); + tmp = ufs_data_ptr_to_cpu(sb, ind); if (!tmp) continue; - *ind = 0; + ufs_data_ptr_clear(uspi, ind); ubh_mark_buffer_dirty(ind_ubh); if (free_count == 0) { frag_to_free = tmp; @@ -226,11 +230,12 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) ufs_free_blocks (inode, frag_to_free, free_count); } for (i = 0; i < uspi->s_apb; i++) - if (*ubh_get_addr32(ind_ubh,i)) + if (!ufs_is_data_ptr_zero(uspi, + ubh_get_data_ptr(uspi, ind_ubh, i))) break; if (i >= uspi->s_apb) { - tmp = fs32_to_cpu(sb, *p); - *p = 0; + tmp = ufs_data_ptr_to_cpu(sb, p); + ufs_data_ptr_clear(uspi, p); ufs_free_blocks (inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); @@ -248,13 +253,13 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) return retry; } -static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) +static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) { struct super_block * sb; struct ufs_sb_private_info * uspi; - struct ufs_buffer_head * dind_bh; - unsigned i, tmp, dindirect_block; - __fs32 * dind; + struct ufs_buffer_head *dind_bh; + u64 i, tmp, dindirect_block; + void *dind; int retry = 0; UFSD("ENTER\n"); @@ -266,22 +271,22 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; retry = 0; - tmp = fs32_to_cpu(sb, *p); + tmp = ufs_data_ptr_to_cpu(sb, p); if (!tmp) return 0; dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); - if (tmp != fs32_to_cpu(sb, *p)) { + if (tmp != ufs_data_ptr_to_cpu(sb, p)) { ubh_brelse (dind_bh); return 1; } if (!dind_bh) { - *p = 0; + ufs_data_ptr_clear(uspi, p); return 0; } for (i = dindirect_block ; i < uspi->s_apb ; i++) { - dind = ubh_get_addr32 (dind_bh, i); - tmp = fs32_to_cpu(sb, *dind); + dind = ubh_get_data_ptr(uspi, dind_bh, i); + tmp = ufs_data_ptr_to_cpu(sb, dind); if (!tmp) continue; retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); @@ -289,11 +294,12 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) } for (i = 0; i < uspi->s_apb; i++) - if (*ubh_get_addr32 (dind_bh, i)) + if (!ufs_is_data_ptr_zero(uspi, + ubh_get_data_ptr(uspi, dind_bh, i))) break; if (i >= uspi->s_apb) { - tmp = fs32_to_cpu(sb, *p); - *p = 0; + tmp = ufs_data_ptr_to_cpu(sb, p); + ufs_data_ptr_clear(uspi, p); ufs_free_blocks(inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); @@ -311,34 +317,33 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) return retry; } -static int ufs_trunc_tindirect (struct inode * inode) +static int ufs_trunc_tindirect(struct inode *inode) { + struct super_block *sb = inode->i_sb; + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block * sb; - struct ufs_sb_private_info * uspi; struct ufs_buffer_head * tind_bh; - unsigned tindirect_block, tmp, i; - __fs32 * tind, * p; + u64 tindirect_block, tmp, i; + void *tind, *p; int retry; UFSD("ENTER\n"); - sb = inode->i_sb; - uspi = UFS_SB(sb)->s_uspi; retry = 0; tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; - p = ufsi->i_u1.i_data + UFS_TIND_BLOCK; - if (!(tmp = fs32_to_cpu(sb, *p))) + + p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); + if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) return 0; tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); - if (tmp != fs32_to_cpu(sb, *p)) { + if (tmp != ufs_data_ptr_to_cpu(sb, p)) { ubh_brelse (tind_bh); return 1; } if (!tind_bh) { - *p = 0; + ufs_data_ptr_clear(uspi, p); return 0; } @@ -349,11 +354,12 @@ static int ufs_trunc_tindirect (struct inode * inode) ubh_mark_buffer_dirty(tind_bh); } for (i = 0; i < uspi->s_apb; i++) - if (*ubh_get_addr32 (tind_bh, i)) + if (!ufs_is_data_ptr_zero(uspi, + ubh_get_data_ptr(uspi, tind_bh, i))) break; if (i >= uspi->s_apb) { - tmp = fs32_to_cpu(sb, *p); - *p = 0; + tmp = ufs_data_ptr_to_cpu(sb, p); + ufs_data_ptr_clear(uspi, p); ufs_free_blocks(inode, tmp, uspi->s_fpb); mark_inode_dirty(inode); @@ -375,7 +381,8 @@ static int ufs_alloc_lastblock(struct inode *inode) int err = 0; struct address_space *mapping = inode->i_mapping; struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; - unsigned lastfrag, i, end; + unsigned i, end; + sector_t lastfrag; struct page *lastpage; struct buffer_head *bh; @@ -430,7 +437,9 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; int retry, err = 0; - UFSD("ENTER\n"); + UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n", + inode->i_ino, (unsigned long long)i_size_read(inode), + (unsigned long long)old_i_size); if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) @@ -450,10 +459,12 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) lock_kernel(); while (1) { retry = ufs_trunc_direct(inode); - retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK, - (__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]); - retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb, - (__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]); + retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK, + ufs_get_direct_data_ptr(uspi, ufsi, + UFS_IND_BLOCK)); + retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb, + ufs_get_direct_data_ptr(uspi, ufsi, + UFS_DIND_BLOCK)); retry |= ufs_trunc_tindirect (inode); if (!retry) break; @@ -502,6 +513,6 @@ static int ufs_setattr(struct dentry *dentry, struct iattr *attr) return inode_setattr(inode, attr); } -struct inode_operations ufs_file_inode_operations = { +const struct inode_operations ufs_file_inode_operations = { .setattr = ufs_setattr, }; diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 7dd12bb1d62..06d344839c4 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -305,8 +305,22 @@ static inline void *get_usb_offset(struct ufs_sb_private_info *uspi, (((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \ ((begin) & ((uspi->s_fsize>>2) - 1))) +#define ubh_get_addr64(ubh,begin) \ + (((__fs64*)((ubh)->bh[(begin) >> (uspi->s_fshift-3)]->b_data)) + \ + ((begin) & ((uspi->s_fsize>>3) - 1))) + #define ubh_get_addr ubh_get_addr8 +static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi, + struct ufs_buffer_head *ubh, + u64 blk) +{ + if (uspi->fs_magic == UFS2_MAGIC) + return ubh_get_addr64(ubh, blk); + else + return ubh_get_addr32(ubh, blk); +} + #define ubh_blkmap(ubh,begin,bit) \ ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb))) @@ -507,3 +521,46 @@ static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap, if (fragsize > 0 && fragsize < uspi->s_fpb) fs32_add(sb, &fraglist[fragsize], cnt); } + +static inline void *ufs_get_direct_data_ptr(struct ufs_sb_private_info *uspi, + struct ufs_inode_info *ufsi, + unsigned blk) +{ + BUG_ON(blk > UFS_TIND_BLOCK); + return uspi->fs_magic == UFS2_MAGIC ? + (void *)&ufsi->i_u1.u2_i_data[blk] : + (void *)&ufsi->i_u1.i_data[blk]; +} + +static inline u64 ufs_data_ptr_to_cpu(struct super_block *sb, void *p) +{ + return UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC ? + fs64_to_cpu(sb, *(__fs64 *)p) : + fs32_to_cpu(sb, *(__fs32 *)p); +} + +static inline void ufs_cpu_to_data_ptr(struct super_block *sb, void *p, u64 val) +{ + if (UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC) + *(__fs64 *)p = cpu_to_fs64(sb, val); + else + *(__fs32 *)p = cpu_to_fs32(sb, val); +} + +static inline void ufs_data_ptr_clear(struct ufs_sb_private_info *uspi, + void *p) +{ + if (uspi->fs_magic == UFS2_MAGIC) + *(__fs64 *)p = 0; + else + *(__fs32 *)p = 0; +} + +static inline int ufs_is_data_ptr_zero(struct ufs_sb_private_info *uspi, + void *p) +{ + if (uspi->fs_magic == UFS2_MAGIC) + return *(__fs64 *)p == 0; + else + return *(__fs32 *)p == 0; +} diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 0afd745a37c..c28add2fbe9 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -996,7 +996,7 @@ error_inode: goto out; } -static struct inode_operations vfat_dir_inode_operations = { +static const struct inode_operations vfat_dir_inode_operations = { .create = vfat_create, .lookup = vfat_lookup, .unlink = vfat_unlink, diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index f3cc4ab20ba..143ffc851c9 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -56,8 +56,6 @@ xfs_count_page_state( do { if (buffer_uptodate(bh) && !buffer_mapped(bh)) (*unmapped) = 1; - else if (buffer_unwritten(bh) && !buffer_delay(bh)) - clear_buffer_unwritten(bh); else if (buffer_unwritten(bh)) (*unwritten) = 1; else if (buffer_delay(bh)) @@ -1272,7 +1270,6 @@ __xfs_get_blocks( if (direct) bh_result->b_private = inode; set_buffer_unwritten(bh_result); - set_buffer_delay(bh_result); } } diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index aa4c3b8cae0..0b5fa124bef 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -813,7 +813,7 @@ xfs_vn_removexattr( } -struct inode_operations xfs_inode_operations = { +const struct inode_operations xfs_inode_operations = { .permission = xfs_vn_permission, .truncate = xfs_vn_truncate, .getattr = xfs_vn_getattr, @@ -824,7 +824,7 @@ struct inode_operations xfs_inode_operations = { .removexattr = xfs_vn_removexattr, }; -struct inode_operations xfs_dir_inode_operations = { +const struct inode_operations xfs_dir_inode_operations = { .create = xfs_vn_create, .lookup = xfs_vn_lookup, .link = xfs_vn_link, @@ -843,7 +843,7 @@ struct inode_operations xfs_dir_inode_operations = { .removexattr = xfs_vn_removexattr, }; -struct inode_operations xfs_symlink_inode_operations = { +const struct inode_operations xfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = xfs_vn_follow_link, .put_link = xfs_vn_put_link, diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index ad6173da567..95a69398fce 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -18,9 +18,9 @@ #ifndef __XFS_IOPS_H__ #define __XFS_IOPS_H__ -extern struct inode_operations xfs_inode_operations; -extern struct inode_operations xfs_dir_inode_operations; -extern struct inode_operations xfs_symlink_inode_operations; +extern const struct inode_operations xfs_inode_operations; +extern const struct inode_operations xfs_dir_inode_operations; +extern const struct inode_operations xfs_symlink_inode_operations; extern const struct file_operations xfs_file_operations; extern const struct file_operations xfs_dir_file_operations; diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 2b0e0018738..715adad7dd4 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -109,16 +109,6 @@ #undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ #endif -/* - * State flag for unwritten extent buffers. - * - * We need to be able to distinguish between these and delayed - * allocate buffers within XFS. The generic IO path code does - * not need to distinguish - we use the BH_Delay flag for both - * delalloc and these ondisk-uninitialised buffers. - */ -BUFFER_FNS(PrivateStart, unwritten); - #define restricted_chown xfs_params.restrict_chown.val #define irix_sgid_inherit xfs_params.sgid_inherit.val #define irix_symlink_mode xfs_params.symlink_mode.val |