diff options
Diffstat (limited to 'fs/ecryptfs/inode.c')
| -rw-r--r-- | fs/ecryptfs/inode.c | 138 | 
1 files changed, 29 insertions, 109 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index bd33f87a190..b592938a84b 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -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) { @@ -349,75 +350,6 @@ out:  }  /** - * 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   * @ecryptfs_dentry: The eCryptfs dentry that we are looking up @@ -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;  	}  |