diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 2abb110..e3ea484 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -650,5 +650,6 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, int ecryptfs_read(char *data, loff_t offset, size_t size, struct file *ecryptfs_file); struct page *ecryptfs_get_locked_page(struct file *file, loff_t index); +int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry); #endif /* #ifndef ECRYPTFS_KERNEL_H */ diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c98c469..fcf2924 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -117,9 +117,20 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) struct inode *inode; struct ecryptfs_getdents_callback buf; + inode = file->f_path.dentry->d_inode; lower_file = ecryptfs_file_to_lower(file); + if (!lower_file) { + rc = ecryptfs_init_persistent_file(file->f_dentry); + if (rc) { + printk(KERN_ERR "%s: Failure to init persistent file; " + "rc = [%d]\n", __FUNCTION__, rc); + goto out; + } + ecryptfs_set_file_lower( + file, ecryptfs_inode_to_private(inode)->lower_file); + lower_file = ecryptfs_file_to_lower(file); + } lower_file->f_pos = file->f_pos; - inode = file->f_path.dentry->d_inode; memset(&buf, 0, sizeof(buf)); buf.dirent = dirent; buf.dentry = file->f_path.dentry; @@ -129,13 +140,17 @@ retry: buf.entries_written = 0; buf.err = 0; rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); - if (buf.err) + if (buf.err) { rc = buf.err; + printk(KERN_ERR "%s: vfs_readdir() returned buf.err = [%d]\n", + __FUNCTION__, rc); + } if (buf.filldir_called && !buf.entries_written) goto retry; file->f_pos = lower_file->f_pos; if (rc >= 0) fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode); +out: return rc; } @@ -240,13 +255,31 @@ static int ecryptfs_flush(struct file *file, fl_owner_t td) struct file *lower_file = NULL; lower_file = ecryptfs_file_to_lower(file); - if (lower_file->f_op && lower_file->f_op->flush) + if (lower_file && lower_file->f_op && lower_file->f_op->flush) rc = lower_file->f_op->flush(lower_file, td); return rc; } static int ecryptfs_release(struct inode *inode, struct file *file) { + struct ecryptfs_inode_info *inode_info = ecryptfs_inode_to_private(inode); + + if (S_ISDIR(inode->i_mode)) { + mutex_lock(&inode_info->lower_file_mutex); + 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; + ecryptfs_set_file_lower(file, NULL); + d_drop(lower_dentry); + } + } + mutex_unlock(&inode_info->lower_file_mutex); + } kmem_cache_free(ecryptfs_file_info_cache, ecryptfs_file_to_private(file)); return 0; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 5a71918..1f940a8 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -279,21 +279,17 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, d_drop(dentry); goto out; } - ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " - "= [%d]\n", encoded_name, encoded_namelen); lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, encoded_namelen - 1); kfree(encoded_name); if (IS_ERR(lower_dentry)) { - ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); rc = PTR_ERR(lower_dentry); + printk(KERN_ERR "%s: lookup_one_len() returned [%d]\n", + __FUNCTION__, rc); d_drop(dentry); goto out; } lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); - ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" - "d_name.name = [%s]\n", lower_dentry, - lower_dentry->d_name.name); lower_inode = lower_dentry->d_inode; fsstack_copy_attr_atime(dir, lower_dir_dentry->d_inode); BUG_ON(!atomic_read(&lower_dentry->d_count)); @@ -302,8 +298,9 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, GFP_KERNEL)); if (!ecryptfs_dentry_to_private(dentry)) { rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Out of memory whilst attempting " - "to allocate ecryptfs_dentry_info struct\n"); + printk(KERN_ERR "%s: Out of memory whilst attempting " + "to allocate ecryptfs_dentry_info struct\n", + __FUNCTION__); goto out_dput; } ecryptfs_set_dentry_lower(dentry, lower_dentry); @@ -315,24 +312,19 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, } rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 1); if (rc) { - ecryptfs_printk(KERN_ERR, "Error interposing\n"); + printk(KERN_ERR "%s: Error interposing\n", __FUNCTION__); goto out_dput; } if (S_ISDIR(lower_inode->i_mode)) { - ecryptfs_printk(KERN_DEBUG, "Is a directory; returning\n"); goto out; } if (S_ISLNK(lower_inode->i_mode)) { - ecryptfs_printk(KERN_DEBUG, "Is a symlink; returning\n"); goto out; } if (special_file(lower_inode->i_mode)) { - ecryptfs_printk(KERN_DEBUG, "Is a special file; returning\n"); goto out; } if (!nd) { - ecryptfs_printk(KERN_DEBUG, "We have a NULL nd, just leave" - "as we *think* we are about to unlink\n"); goto out; } /* Released in this function */ diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c