Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ecryptfs/ecryptfs-2.6: eCryptfs: Flush dirty pages in setattr eCryptfs: Handle failed metadata read in lookup eCryptfs: Add reference counting to lower files eCryptfs: dput dentries returned from dget_parent eCryptfs: Remove extra d_delete in ecryptfs_rmdir
This commit is contained in:
Коммит
cd2e49e90f
|
@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
|
|||
crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
|
||||
}
|
||||
|
||||
void ecryptfs_i_size_init(const char *page_virt, struct inode *inode)
|
||||
{
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
u64 file_size;
|
||||
|
||||
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
mount_crypt_stat =
|
||||
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
|
||||
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
|
||||
file_size = i_size_read(ecryptfs_inode_to_lower(inode));
|
||||
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
|
||||
file_size += crypt_stat->metadata_size;
|
||||
} else
|
||||
file_size = get_unaligned_be64(page_virt);
|
||||
i_size_write(inode, (loff_t)file_size);
|
||||
crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED;
|
||||
}
|
||||
|
||||
/**
|
||||
* ecryptfs_read_headers_virt
|
||||
* @page_virt: The virtual address into which to read the headers
|
||||
|
@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt,
|
|||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED))
|
||||
ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
|
||||
offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
|
||||
rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset),
|
||||
&bytes_read);
|
||||
|
|
|
@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat {
|
|||
#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800
|
||||
#define ECRYPTFS_ENCFN_USE_FEK 0x00001000
|
||||
#define ECRYPTFS_UNLINK_SIGS 0x00002000
|
||||
#define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000
|
||||
u32 flags;
|
||||
unsigned int file_version;
|
||||
size_t iv_bytes;
|
||||
|
@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat {
|
|||
struct ecryptfs_inode_info {
|
||||
struct inode vfs_inode;
|
||||
struct inode *wii_inode;
|
||||
struct mutex lower_file_mutex;
|
||||
atomic_t lower_file_count;
|
||||
struct file *lower_file;
|
||||
struct ecryptfs_crypt_stat crypt_stat;
|
||||
};
|
||||
|
@ -626,6 +629,7 @@ struct ecryptfs_open_req {
|
|||
int ecryptfs_interpose(struct dentry *hidden_dentry,
|
||||
struct dentry *this_dentry, struct super_block *sb,
|
||||
u32 flags);
|
||||
void ecryptfs_i_size_init(const char *page_virt, struct inode *inode);
|
||||
int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
|
||||
struct dentry *lower_dentry,
|
||||
struct inode *ecryptfs_dir_inode);
|
||||
|
@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
|
|||
struct dentry *lower_dentry,
|
||||
struct vfsmount *lower_mnt,
|
||||
const struct cred *cred);
|
||||
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
|
||||
int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry);
|
||||
void ecryptfs_put_lower_file(struct inode *inode);
|
||||
int
|
||||
ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
|
||||
size_t *packet_size,
|
||||
|
|
|
@ -191,10 +191,10 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
| ECRYPTFS_ENCRYPTED);
|
||||
}
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
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;
|
||||
|
@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE)
|
||||
== O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) {
|
||||
rc = -EPERM;
|
||||
printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
|
||||
printk(KERN_WARNING "%s: Lower file is RO; eCryptfs "
|
||||
"file must hence be opened RO\n", __func__);
|
||||
goto out_free;
|
||||
goto out_put;
|
||||
}
|
||||
ecryptfs_set_file_lower(
|
||||
file, ecryptfs_inode_to_private(inode)->lower_file);
|
||||
|
@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
"Plaintext passthrough mode is not "
|
||||
"enabled; returning -EIO\n");
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
goto out_free;
|
||||
goto out_put;
|
||||
}
|
||||
rc = 0;
|
||||
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
|
||||
crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
|
||||
| ECRYPTFS_ENCRYPTED);
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
goto out;
|
||||
}
|
||||
|
@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
"[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
|
||||
(unsigned long long)i_size_read(inode));
|
||||
goto out;
|
||||
out_put:
|
||||
ecryptfs_put_lower_file(inode);
|
||||
out_free:
|
||||
kmem_cache_free(ecryptfs_file_info_cache,
|
||||
ecryptfs_file_to_private(file));
|
||||
|
@ -254,17 +257,13 @@ out:
|
|||
|
||||
static int ecryptfs_flush(struct file *file, fl_owner_t td)
|
||||
{
|
||||
int rc = 0;
|
||||
struct file *lower_file = NULL;
|
||||
|
||||
lower_file = ecryptfs_file_to_lower(file);
|
||||
if (lower_file->f_op && lower_file->f_op->flush)
|
||||
rc = lower_file->f_op->flush(lower_file, td);
|
||||
return rc;
|
||||
return file->f_mode & FMODE_WRITE
|
||||
? filemap_write_and_wait(file->f_mapping) : 0;
|
||||
}
|
||||
|
||||
static int ecryptfs_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
ecryptfs_put_lower_file(inode);
|
||||
kmem_cache_free(ecryptfs_file_info_cache,
|
||||
ecryptfs_file_to_private(file));
|
||||
return 0;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread;
|
|||
* @ignored: ignored
|
||||
*
|
||||
* The eCryptfs kernel thread that has the responsibility of getting
|
||||
* the lower persistent file with RW permissions.
|
||||
* the lower file with RW permissions.
|
||||
*
|
||||
* Returns zero on success; non-zero otherwise
|
||||
*/
|
||||
|
@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
|
|||
int rc = 0;
|
||||
|
||||
/* Corresponding dput() and mntput() are done when the
|
||||
* persistent file is fput() when the eCryptfs inode is
|
||||
* destroyed. */
|
||||
* lower file is fput() when all eCryptfs files for the inode are
|
||||
* released. */
|
||||
dget(lower_dentry);
|
||||
mntget(lower_mnt);
|
||||
flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
|
||||
|
|
|
@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...)
|
|||
}
|
||||
|
||||
/**
|
||||
* ecryptfs_init_persistent_file
|
||||
* ecryptfs_init_lower_file
|
||||
* @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
|
||||
* the lower dentry and the lower mount set
|
||||
*
|
||||
|
@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...)
|
|||
* inode. All I/O operations to the lower inode occur through that
|
||||
* file. When the first eCryptfs dentry that interposes with the first
|
||||
* lower dentry for that inode is created, this function creates the
|
||||
* persistent file struct and associates it with the eCryptfs
|
||||
* inode. When the eCryptfs inode is destroyed, the file is closed.
|
||||
* lower file struct and associates it with the eCryptfs
|
||||
* inode. When all eCryptfs files associated with the inode are released, the
|
||||
* file is closed.
|
||||
*
|
||||
* The persistent file will be opened with read/write permissions, if
|
||||
* The lower file will be opened with read/write permissions, if
|
||||
* possible. Otherwise, it is opened read-only.
|
||||
*
|
||||
* This function does nothing if a lower persistent file is already
|
||||
* This function does nothing if a lower file is already
|
||||
* associated with the eCryptfs inode.
|
||||
*
|
||||
* Returns zero on success; non-zero otherwise
|
||||
*/
|
||||
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
|
||||
static int ecryptfs_init_lower_file(struct dentry *dentry,
|
||||
struct file **lower_file)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
struct ecryptfs_inode_info *inode_info =
|
||||
ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
|
||||
int rc = 0;
|
||||
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
|
||||
int rc;
|
||||
|
||||
if (!inode_info->lower_file) {
|
||||
struct dentry *lower_dentry;
|
||||
struct vfsmount *lower_mnt =
|
||||
ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
|
||||
rc = ecryptfs_privileged_open(&inode_info->lower_file,
|
||||
lower_dentry, lower_mnt, cred);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Error opening lower persistent file "
|
||||
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
|
||||
"rc = [%d]\n", lower_dentry, lower_mnt, rc);
|
||||
inode_info->lower_file = NULL;
|
||||
}
|
||||
rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt,
|
||||
cred);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Error opening lower file "
|
||||
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
|
||||
"rc = [%d]\n", lower_dentry, lower_mnt, rc);
|
||||
(*lower_file) = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ecryptfs_get_lower_file(struct dentry *dentry)
|
||||
{
|
||||
struct ecryptfs_inode_info *inode_info =
|
||||
ecryptfs_inode_to_private(dentry->d_inode);
|
||||
int count, rc = 0;
|
||||
|
||||
mutex_lock(&inode_info->lower_file_mutex);
|
||||
count = atomic_inc_return(&inode_info->lower_file_count);
|
||||
if (WARN_ON_ONCE(count < 1))
|
||||
rc = -EINVAL;
|
||||
else if (count == 1) {
|
||||
rc = ecryptfs_init_lower_file(dentry,
|
||||
&inode_info->lower_file);
|
||||
if (rc)
|
||||
atomic_set(&inode_info->lower_file_count, 0);
|
||||
}
|
||||
mutex_unlock(&inode_info->lower_file_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ecryptfs_put_lower_file(struct inode *inode)
|
||||
{
|
||||
struct ecryptfs_inode_info *inode_info;
|
||||
|
||||
inode_info = ecryptfs_inode_to_private(inode);
|
||||
if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
|
||||
&inode_info->lower_file_mutex)) {
|
||||
fput(inode_info->lower_file);
|
||||
inode_info->lower_file = NULL;
|
||||
mutex_unlock(&inode_info->lower_file_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static struct inode *ecryptfs_get_inode(struct inode *lower_inode,
|
||||
struct super_block *sb)
|
||||
{
|
||||
|
|
|
@ -55,6 +55,8 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
|
|||
if (unlikely(!inode_info))
|
||||
goto out;
|
||||
ecryptfs_init_crypt_stat(&inode_info->crypt_stat);
|
||||
mutex_init(&inode_info->lower_file_mutex);
|
||||
atomic_set(&inode_info->lower_file_count, 0);
|
||||
inode_info->lower_file = NULL;
|
||||
inode = &inode_info->vfs_inode;
|
||||
out:
|
||||
|
@ -77,8 +79,7 @@ static void ecryptfs_i_callback(struct rcu_head *head)
|
|||
*
|
||||
* This is used during the final destruction of the inode. All
|
||||
* allocation of memory related to the inode, including allocated
|
||||
* memory in the crypt_stat struct, will be released here. This
|
||||
* function also fput()'s the persistent file for the lower inode.
|
||||
* memory in the crypt_stat struct, will be released here.
|
||||
* There should be no chance that this deallocation will be missed.
|
||||
*/
|
||||
static void ecryptfs_destroy_inode(struct inode *inode)
|
||||
|
@ -86,16 +87,7 @@ static void ecryptfs_destroy_inode(struct inode *inode)
|
|||
struct ecryptfs_inode_info *inode_info;
|
||||
|
||||
inode_info = ecryptfs_inode_to_private(inode);
|
||||
if (inode_info->lower_file) {
|
||||
struct dentry *lower_dentry =
|
||||
inode_info->lower_file->f_dentry;
|
||||
|
||||
BUG_ON(!lower_dentry);
|
||||
if (lower_dentry->d_inode) {
|
||||
fput(inode_info->lower_file);
|
||||
inode_info->lower_file = NULL;
|
||||
}
|
||||
}
|
||||
BUG_ON(inode_info->lower_file);
|
||||
ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
|
||||
call_rcu(&inode->i_rcu, ecryptfs_i_callback);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче