@ -74,16 +74,20 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode,
unsigned int flags_save ;
int rc ;
dentry_save = nd - > path . dentry ;
vfsmount_save = nd - > path . mnt ;
flags_save = nd - > flags ;
nd - > path . dentry = lower_dentry ;
nd - > path . mnt = lower_mnt ;
nd - > flags & = ~ LOOKUP_OPEN ;
if ( nd ) {
dentry_save = nd - > path . dentry ;
vfsmount_save = nd - > path . mnt ;
flags_save = nd - > flags ;
nd - > path . dentry = lower_dentry ;
nd - > path . mnt = lower_mnt ;
nd - > flags & = ~ LOOKUP_OPEN ;
}
rc = vfs_create ( lower_dir_inode , lower_dentry , mode , nd ) ;
nd - > path . dentry = dentry_save ;
nd - > path . mnt = vfsmount_save ;
nd - > flags = flags_save ;
if ( nd ) {
nd - > path . dentry = dentry_save ;
nd - > path . mnt = vfsmount_save ;
nd - > flags = flags_save ;
}
return rc ;
}
@ -241,8 +245,7 @@ out:
*/
int ecryptfs_lookup_and_interpose_lower ( struct dentry * ecryptfs_dentry ,
struct dentry * lower_dentry ,
struct inode * ecryptfs_dir_inode ,
struct nameidata * ecryptfs_nd )
struct inode * ecryptfs_dir_inode )
{
struct dentry * lower_dir_dentry ;
struct vfsmount * lower_mnt ;
@ -290,8 +293,6 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
goto out ;
if ( special_file ( lower_inode - > i_mode ) )
goto out ;
if ( ! ecryptfs_nd )
goto out ;
/* Released in this function */
page_virt = kmem_cache_zalloc ( ecryptfs_header_cache_2 , GFP_USER ) ;
if ( ! page_virt ) {
@ -348,75 +349,6 @@ out:
return rc ;
}
/**
* ecryptfs_new_lower_dentry
* @ name : The name of the new dentry .
* @ lower_dir_dentry : Parent directory of the new dentry .
* @ nd : nameidata from last lookup .
*
* Create a new dentry or get it from lower parent dir .
*/
static struct dentry *
ecryptfs_new_lower_dentry ( struct qstr * name , struct dentry * lower_dir_dentry ,
struct nameidata * nd )
{
struct dentry * new_dentry ;
struct dentry * tmp ;
struct inode * lower_dir_inode ;
lower_dir_inode = lower_dir_dentry - > d_inode ;
tmp = d_alloc ( lower_dir_dentry , name ) ;
if ( ! tmp )
return ERR_PTR ( - ENOMEM ) ;
mutex_lock ( & lower_dir_inode - > i_mutex ) ;
new_dentry = lower_dir_inode - > i_op - > lookup ( lower_dir_inode , tmp , nd ) ;
mutex_unlock ( & lower_dir_inode - > i_mutex ) ;
if ( ! new_dentry )
new_dentry = tmp ;
else
dput ( tmp ) ;
return new_dentry ;
}
/**
* ecryptfs_lookup_one_lower
* @ ecryptfs_dentry : The eCryptfs dentry that we are looking up
* @ lower_dir_dentry : lower parent directory
* @ name : lower file name
*
* Get the lower dentry from vfs . If lower dentry does not exist yet ,
* create it .
*/
static struct dentry *
ecryptfs_lookup_one_lower ( struct dentry * ecryptfs_dentry ,
struct dentry * lower_dir_dentry , struct qstr * name )
{
struct nameidata nd ;
struct vfsmount * lower_mnt ;
int err ;
lower_mnt = mntget ( ecryptfs_dentry_to_lower_mnt (
ecryptfs_dentry - > d_parent ) ) ;
err = vfs_path_lookup ( lower_dir_dentry , lower_mnt , name - > name , 0 , & nd ) ;
mntput ( lower_mnt ) ;
if ( ! err ) {
/* we dont need the mount */
mntput ( nd . path . mnt ) ;
return nd . path . dentry ;
}
if ( err ! = - ENOENT )
return ERR_PTR ( err ) ;
/* create a new lower dentry */
return ecryptfs_new_lower_dentry ( name , lower_dir_dentry , & nd ) ;
}
/**
* ecryptfs_lookup
* @ ecryptfs_dir_inode : The eCryptfs directory inode
@ -434,7 +366,6 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
size_t encrypted_and_encoded_name_size ;
struct ecryptfs_mount_crypt_stat * mount_crypt_stat = NULL ;
struct dentry * lower_dir_dentry , * lower_dentry ;
struct qstr lower_name ;
int rc = 0 ;
if ( ( ecryptfs_dentry - > d_name . len = = 1
@ -444,20 +375,14 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
goto out_d_drop ;
}
lower_dir_dentry = ecryptfs_dentry_to_lower ( ecryptfs_dentry - > d_parent ) ;
lower_name . name = ecryptfs_dentry - > d_name . name ;
lower_name . len = ecryptfs_dentry - > d_name . len ;
lower_name . hash = ecryptfs_dentry - > d_name . hash ;
if ( lower_dir_dentry - > d_op & & lower_dir_dentry - > d_op - > d_hash ) {
rc = lower_dir_dentry - > d_op - > d_hash ( lower_dir_dentry ,
lower_dir_dentry - > d_inode , & lower_name ) ;
if ( rc < 0 )
goto out_d_drop ;
}
lower_dentry = ecryptfs_lookup_one_lower ( ecryptfs_dentry ,
lower_dir_dentry , & lower_name ) ;
mutex_lock ( & lower_dir_dentry - > d_inode - > i_mutex ) ;
lower_dentry = lookup_one_len ( ecryptfs_dentry - > d_name . name ,
lower_dir_dentry ,
ecryptfs_dentry - > d_name . len ) ;
mutex_unlock ( & lower_dir_dentry - > d_inode - > i_mutex ) ;
if ( IS_ERR ( lower_dentry ) ) {
rc = PTR_ERR ( lower_dentry ) ;
ecryptfs_printk ( KERN_DEBUG , " %s: lookup_one_lower () returned "
ecryptfs_printk ( KERN_DEBUG , " %s: lookup_one_len() returned "
" [%d] on lower_dentry = [%s] \n " , __func__ , rc ,
encrypted_and_encoded_name ) ;
goto out_d_drop ;
@ -479,28 +404,21 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
" filename; rc = [%d] \n " , __func__ , rc ) ;
goto out_d_drop ;
}
lower_name . name = encrypted_and_encoded_name ;
lower_name . len = encrypted_and_encoded_name_size ;
lower_name . hash = full_name_hash ( lower_name . name , lower_name . len ) ;
if ( lower_dir_dentry - > d_op & & lower_dir_dentry - > d_op - > d_hash ) {
rc = lower_dir_dentry - > d_op - > d_hash ( lower_dir_dentry ,
lower_dir_dentry - > d_inode , & lower_name ) ;
if ( rc < 0 )
goto out_d_drop ;
}
lower_dentry = ecryptfs_lookup_one_lower ( ecryptfs_dentry ,
lower_dir_dentry , & lower_name ) ;
mutex_lock ( & lower_dir_dentry - > d_inode - > i_mutex ) ;
lower_dentry = lookup_one_len ( encrypted_and_encoded_name ,
lower_dir_dentry ,
encrypted_and_encoded_name_size ) ;
mutex_unlock ( & lower_dir_dentry - > d_inode - > i_mutex ) ;
if ( IS_ERR ( lower_dentry ) ) {
rc = PTR_ERR ( lower_dentry ) ;
ecryptfs_printk ( KERN_DEBUG , " %s: lookup_one_lower () returned "
ecryptfs_printk ( KERN_DEBUG , " %s: lookup_one_len() returned "
" [%d] on lower_dentry = [%s] \n " , __func__ , rc ,
encrypted_and_encoded_name ) ;
goto out_d_drop ;
}
lookup_and_interpose :
rc = ecryptfs_lookup_and_interpose_lower ( ecryptfs_dentry , lower_dentry ,
ecryptfs_dir_inode ,
ecryptfs_nd ) ;
ecryptfs_dir_inode ) ;
goto out ;
out_d_drop :
d_drop ( ecryptfs_dentry ) ;
@ -1092,6 +1010,8 @@ int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
rc = vfs_getattr ( ecryptfs_dentry_to_lower_mnt ( dentry ) ,
ecryptfs_dentry_to_lower ( dentry ) , & lower_stat ) ;
if ( ! rc ) {
fsstack_copy_attr_all ( dentry - > d_inode ,
ecryptfs_inode_to_lower ( dentry - > d_inode ) ) ;
generic_fillattr ( dentry - > d_inode , stat ) ;
stat - > blocks = lower_stat . blocks ;
}