From: Michael Halcrow Modify inode number generation to account for differences in the inode number data type sizes in lower filesystems. Use containter_of() rather than i_private to gain access to the eCryptFS private data from the inode as this will result in the assembly code using subtraction or addition to get the address rather than using a LOAD instruction to read i_private. This should result in slightly faster code and possibly the use of one fewer registers in some functions. Because of this, ecryptfs_set_inode_private() is no longer necessary, and the same goes for any checks that the result of ecryptfs_get_inode_private() is non-NULL (which can be assumed if inode is non-NULL). Also move the embedded vfs_inode struct to the beginning of ecryptfs_inode_info so that the VFS inode address and the private data address are coincident. This permits the offset to be optimised away. It is possible that moving vfs_node before wii_inode is not the best thing to do, but if the address of wii_inode is always derived by offset from inode, then it should make no difference as register+offset addressing modes will always have to be used, one way or another. Since because i_private is made available by the first part of the patch, wii_inode could be dispensed with entirely and i_private used instead, thus reducing the amount of memory used. [dhowells@redhat.com: the container_of() part] Signed-off-by: David Howells Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton --- fs/ecryptfs/ecryptfs_kernel.h | 19 +++++++------------ fs/ecryptfs/inode.c | 15 +++++++++++++++ fs/ecryptfs/main.c | 29 +++++++++++++---------------- fs/ecryptfs/super.c | 13 ++++--------- 4 files changed, 39 insertions(+), 37 deletions(-) diff -puN fs/ecryptfs/ecryptfs_kernel.h~ecryptfs-inode-numbering-fixes fs/ecryptfs/ecryptfs_kernel.h --- a/fs/ecryptfs/ecryptfs_kernel.h~ecryptfs-inode-numbering-fixes +++ a/fs/ecryptfs/ecryptfs_kernel.h @@ -211,8 +211,8 @@ struct ecryptfs_crypt_stat { /* inode private data. */ struct ecryptfs_inode_info { - struct inode *wii_inode; struct inode vfs_inode; + struct inode *wii_inode; struct ecryptfs_crypt_stat crypt_stat; }; @@ -289,26 +289,18 @@ ecryptfs_set_file_lower(struct file *fil static inline struct ecryptfs_inode_info * ecryptfs_inode_to_private(struct inode *inode) { - return (struct ecryptfs_inode_info *)inode->i_private; -} - -static inline void -ecryptfs_set_inode_private(struct inode *inode, - struct ecryptfs_inode_info *inode_info) -{ - inode->i_private = inode_info; + return container_of(inode, struct ecryptfs_inode_info, vfs_inode); } static inline struct inode *ecryptfs_inode_to_lower(struct inode *inode) { - return ((struct ecryptfs_inode_info *)inode->i_private)->wii_inode; + return ecryptfs_inode_to_private(inode)->wii_inode; } static inline void ecryptfs_set_inode_lower(struct inode *inode, struct inode *lower_inode) { - ((struct ecryptfs_inode_info *)inode->i_private)->wii_inode = - lower_inode; + ecryptfs_inode_to_private(inode)->wii_inode = lower_inode; } static inline struct ecryptfs_sb_info * @@ -474,5 +466,8 @@ int ecryptfs_truncate(struct dentry *den int ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, char *cipher_name, size_t key_size); +int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); +int ecryptfs_inode_set(struct inode *inode, void *lower_inode); +void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode); #endif /* #ifndef ECRYPTFS_KERNEL_H */ diff -puN fs/ecryptfs/inode.c~ecryptfs-inode-numbering-fixes fs/ecryptfs/inode.c --- a/fs/ecryptfs/inode.c~ecryptfs-inode-numbering-fixes +++ a/fs/ecryptfs/inode.c @@ -1024,6 +1024,21 @@ out: return rc; } +int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode) +{ + if ((ecryptfs_inode_to_lower(inode) + == (struct inode *)candidate_lower_inode)) + return 1; + else + return 0; +} + +int ecryptfs_inode_set(struct inode *inode, void *lower_inode) +{ + ecryptfs_init_inode(inode, (struct inode *)lower_inode); + return 0; +} + struct inode_operations ecryptfs_symlink_iops = { .readlink = ecryptfs_readlink, .follow_link = ecryptfs_follow_link, diff -puN fs/ecryptfs/main.c~ecryptfs-inode-numbering-fixes fs/ecryptfs/main.c --- a/fs/ecryptfs/main.c~ecryptfs-inode-numbering-fixes +++ a/fs/ecryptfs/main.c @@ -68,39 +68,36 @@ void __ecryptfs_printk(const char *fmt, * * Interposes upper and lower dentries. * - * This function will allocate an ecryptfs_inode through the call to - * iget(sb, lower_inode->i_ino). - * * Returns zero on success; non-zero otherwise */ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, struct super_block *sb, int flag) { struct inode *lower_inode; - int rc = 0; struct inode *inode; + int rc = 0; lower_inode = lower_dentry->d_inode; if (lower_inode->i_sb != ecryptfs_superblock_to_lower(sb)) { rc = -EXDEV; goto out; } - inode = iget(sb, lower_inode->i_ino); - if (!inode) { - rc = -EACCES; + if (!igrab(lower_inode)) { + rc = -ESTALE; goto out; } - /* This check is required here because if we failed to allocated the - * required space for an inode_info_cache struct, then the only way - * we know we failed, is by the pointer being NULL */ - if (!ecryptfs_inode_to_private(inode)) { - ecryptfs_printk(KERN_ERR, "Out of memory. Failure to " - "allocate memory in ecryptfs_read_inode.\n"); - rc = -ENOMEM; + inode = iget5_locked(sb, (unsigned long)lower_inode, + ecryptfs_inode_test, ecryptfs_inode_set, + lower_inode); + if (!inode) { + rc = -EACCES; + iput(lower_inode); goto out; } - if (!ecryptfs_inode_to_lower(inode)) - ecryptfs_set_inode_lower(inode, igrab(lower_inode)); + if (inode->i_state & I_NEW) + unlock_new_inode(inode); + else + iput(lower_inode); if (S_ISLNK(lower_inode->i_mode)) inode->i_op = &ecryptfs_symlink_iops; else if (S_ISDIR(lower_inode->i_mode)) diff -puN fs/ecryptfs/super.c~ecryptfs-inode-numbering-fixes fs/ecryptfs/super.c --- a/fs/ecryptfs/super.c~ecryptfs-inode-numbering-fixes +++ a/fs/ecryptfs/super.c @@ -78,19 +78,15 @@ static void ecryptfs_destroy_inode(struc } /** - * ecryptfs_read_inode + * ecryptfs_init_inode * @inode: The ecryptfs inode * * Set up the ecryptfs inode. */ -static void ecryptfs_read_inode(struct inode *inode) +void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode) { - /* This is where we setup the self-reference in the vfs_inode's - * i_private. That way we don't have to walk the list again. */ - ecryptfs_set_inode_private(inode, - list_entry(inode, struct ecryptfs_inode_info, - vfs_inode)); - ecryptfs_set_inode_lower(inode, NULL); + ecryptfs_set_inode_lower(inode, lower_inode); + inode->i_ino = lower_inode->i_ino; inode->i_version++; inode->i_op = &ecryptfs_main_iops; inode->i_fop = &ecryptfs_main_fops; @@ -192,7 +188,6 @@ out: struct super_operations ecryptfs_sops = { .alloc_inode = ecryptfs_alloc_inode, .destroy_inode = ecryptfs_destroy_inode, - .read_inode = ecryptfs_read_inode, .drop_inode = generic_delete_inode, .put_super = ecryptfs_put_super, .statfs = ecryptfs_statfs, _