diff options
Diffstat (limited to 'fs/ecryptfs/inode.c')
| -rw-r--r-- | fs/ecryptfs/inode.c | 60 | 
1 files changed, 32 insertions, 28 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index f99051b7ada..4d4cc6a90cd 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)  				"context; rc = [%d]\n", rc);  		goto out;  	} -	rc = ecryptfs_init_persistent_file(ecryptfs_dentry); +	rc = ecryptfs_get_lower_file(ecryptfs_dentry);  	if (rc) {  		printk(KERN_ERR "%s: Error attempting to initialize " -			"the persistent file for the dentry with name " +			"the lower file for the dentry with name "  			"[%s]; rc = [%d]\n", __func__,  			ecryptfs_dentry->d_name.name, rc);  		goto out;  	}  	rc = ecryptfs_write_metadata(ecryptfs_dentry); -	if (rc) { +	if (rc)  		printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); -		goto out; -	} +	ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);  out:  	return rc;  } @@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,  	struct dentry *lower_dir_dentry;  	struct vfsmount *lower_mnt;  	struct inode *lower_inode; -	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;  	struct ecryptfs_crypt_stat *crypt_stat;  	char *page_virt = NULL; -	u64 file_size; -	int rc = 0; +	int put_lower = 0, rc = 0;  	lower_dir_dentry = lower_dentry->d_parent;  	lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( @@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,  		rc = -ENOMEM;  		goto out;  	} -	rc = ecryptfs_init_persistent_file(ecryptfs_dentry); +	rc = ecryptfs_get_lower_file(ecryptfs_dentry);  	if (rc) {  		printk(KERN_ERR "%s: Error attempting to initialize " -			"the persistent file for the dentry with name " +			"the lower file for the dentry with name "  			"[%s]; rc = [%d]\n", __func__,  			ecryptfs_dentry->d_name.name, rc);  		goto out_free_kmem;  	} +	put_lower = 1;  	crypt_stat = &ecryptfs_inode_to_private(  					ecryptfs_dentry->d_inode)->crypt_stat;  	/* TODO: lock for crypt_stat comparison */ @@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,  		}  		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;  	} -	mount_crypt_stat = &ecryptfs_superblock_to_private( -		ecryptfs_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->metadata_size -				     + i_size_read(lower_dentry->d_inode)); -		else -			file_size = i_size_read(lower_dentry->d_inode); -	} else { -		file_size = get_unaligned_be64(page_virt); -	} -	i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); +	ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);  out_free_kmem:  	kmem_cache_free(ecryptfs_header_cache_2, page_virt);  	goto out; @@ -322,6 +309,8 @@ out_put:  	mntput(lower_mnt);  	d_drop(ecryptfs_dentry);  out: +	if (put_lower) +		ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);  	return rc;  } @@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)  	dget(lower_dentry);  	rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);  	dput(lower_dentry); -	if (!rc) -		d_delete(lower_dentry);  	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);  	dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;  	unlock_dir(lower_dir_dentry); @@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);  out_lock:  	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); -	dput(lower_new_dentry->d_parent); -	dput(lower_old_dentry->d_parent); +	dput(lower_new_dir_dentry); +	dput(lower_old_dir_dentry);  	dput(lower_new_dentry);  	dput(lower_old_dentry);  	return rc; @@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,  	if (unlikely((ia->ia_size == i_size))) {  		lower_ia->ia_valid &= ~ATTR_SIZE; -		goto out; +		return 0;  	} +	rc = ecryptfs_get_lower_file(dentry); +	if (rc) +		return rc;  	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;  	/* Switch on growing or shrinking file */  	if (ia->ia_size > i_size) { @@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,  			lower_ia->ia_valid &= ~ATTR_SIZE;  	}  out: +	ecryptfs_put_lower_file(inode);  	return rc;  } @@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  		mount_crypt_stat = &ecryptfs_superblock_to_private(  			dentry->d_sb)->mount_crypt_stat; +		rc = ecryptfs_get_lower_file(dentry); +		if (rc) { +			mutex_unlock(&crypt_stat->cs_mutex); +			goto out; +		}  		rc = ecryptfs_read_metadata(dentry); +		ecryptfs_put_lower_file(inode);  		if (rc) {  			if (!(mount_crypt_stat->flags  			      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { @@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  				goto out;  			}  			rc = 0; -			crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); +			crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED +					       | ECRYPTFS_ENCRYPTED);  		}  	}  	mutex_unlock(&crypt_stat->cs_mutex); +	if (S_ISREG(inode->i_mode)) { +		rc = filemap_write_and_wait(inode->i_mapping); +		if (rc) +			goto out; +		fsstack_copy_attr_all(inode, lower_inode); +	}  	memcpy(&lower_ia, ia, sizeof(lower_ia));  	if (ia->ia_valid & ATTR_FILE)  		lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);  |