static ssize_t sdcardfskk_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int err; struct file *lower_file; struct dentry *dentry = file->f_path.dentry; #ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE struct backing_dev_info *bdi; #endif lower_file = sdcardfskk_lower_file(file); #ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE if (file->f_mode & FMODE_NOACTIVE) { if (!(lower_file->f_mode & FMODE_NOACTIVE)) { bdi = lower_file->f_mapping->backing_dev_info; lower_file->f_ra.ra_pages = bdi->ra_pages * 2; spin_lock(&lower_file->f_lock); lower_file->f_mode |= FMODE_NOACTIVE; spin_unlock(&lower_file->f_lock); } } #endif err = vfs_read(lower_file, buf, count, ppos); /* update our inode atime upon a successful lower read */ if (err >= 0) fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); return err; }
/** * ecryptfs_readdir * @file: The eCryptfs directory file * @dirent: Directory entry handle * @filldir: The filldir callback function */ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) { int rc; struct file *lower_file; struct inode *inode; struct ecryptfs_getdents_callback buf; lower_file = ecryptfs_file_to_lower(file); lower_file->f_pos = file->f_pos; inode = file_inode(file); memset(&buf, 0, sizeof(buf)); buf.dirent = dirent; buf.dentry = file->f_path.dentry; buf.filldir = filldir; buf.filldir_called = 0; buf.entries_written = 0; buf.ctx.actor = ecryptfs_filldir; rc = iterate_dir(lower_file, &buf.ctx); file->f_pos = lower_file->f_pos; if (rc < 0) goto out; if (buf.filldir_called && !buf.entries_written) goto out; if (rc >= 0) fsstack_copy_attr_atime(inode, file_inode(lower_file)); out: return rc; }
struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct dentry *ret, *parent; struct path lower_parent_path; int err = 0; BUG_ON(!nd); parent = dget_parent(dentry); wrapfs_get_lower_path(parent, &lower_parent_path); /* allocate dentry private data. We free it in ->d_release */ err = new_dentry_private_data(dentry); if (err) { ret = ERR_PTR(err); goto out; } ret = __wrapfs_lookup(dentry, nd->flags, &lower_parent_path); if (IS_ERR(ret)) goto out; if (ret) dentry = ret; if (dentry->d_inode) fsstack_copy_attr_times(dentry->d_inode, wrapfs_lower_inode(dentry->d_inode)); /* update parent directory's atime */ fsstack_copy_attr_atime(parent->d_inode, wrapfs_lower_inode(parent->d_inode)); out: wrapfs_put_lower_path(parent, &lower_parent_path); dput(parent); return ret; }
/** * ecryptfs_readdir * @file: The ecryptfs file struct * @dirent: Directory entry * @filldir: The filldir callback function */ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) { int rc; struct file *lower_file; struct inode *inode; struct ecryptfs_getdents_callback buf; 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; buf.filldir = filldir; retry: buf.filldir_called = 0; buf.entries_written = 0; buf.err = 0; rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); if (buf.err) rc = buf.err; 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); return rc; }
static int wrapfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) { int err; struct dentry *lower_dentry; struct path lower_path; if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE) DEBUG_MESG("Enter"); wrapfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; if (!lower_dentry->d_inode->i_op || !lower_dentry->d_inode->i_op->readlink) { err = -EINVAL; goto out; } err = lower_dentry->d_inode->i_op->readlink(lower_dentry, buf, bufsiz); if (err < 0) goto out; fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); out: wrapfs_put_lower_path(dentry, &lower_path); if(wrapfs_get_debug(dentry->d_sb) & DEBUG_INODE) DEBUG_RETURN("Exit", err); return err; }
static int u2fs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) { int err; struct dentry *lower_dentry; struct path lower_path; if((U2FS_D(dentry)->lower_path[LEFT].dentry) != NULL && (U2FS_D(dentry)->lower_path[LEFT].mnt) != NULL) u2fs_get_lower_path(dentry, &lower_path, LEFT); else u2fs_get_lower_path(dentry, &lower_path, RIGHT); lower_dentry = lower_path.dentry; if (!lower_dentry->d_inode->i_op || !lower_dentry->d_inode->i_op->readlink) { err = -EINVAL; goto out; } err = lower_dentry->d_inode->i_op->readlink(lower_dentry, buf, bufsiz); if (err < 0) goto out; fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); out: u2fs_put_lower_path(dentry, &lower_path); return err; }
static int sdcardfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) { int err; struct dentry *lower_dentry; struct path lower_path; /* XXX readlink does not requires overriding credential */ sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; if (!lower_dentry->d_inode->i_op || !lower_dentry->d_inode->i_op->readlink) { err = -EINVAL; goto out; } err = lower_dentry->d_inode->i_op->readlink(lower_dentry, buf, bufsiz); if (err < 0) goto out; fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); out: sdcardfs_put_lower_path(dentry, &lower_path); return err; }
static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir) { int err = 0; struct file *lower_file = NULL; struct dentry *dentry = file->f_path.dentry; struct dentry *parent; struct inode *inode = NULL; int bindex = 0; inode = dentry->d_inode; parent = dget_parent(dentry); for (bindex = 0; bindex <= 1; bindex++) { lower_file = wrapfs_lower_file_idx(file, bindex); if (!lower_file) continue; err = vfs_readdir(lower_file, filldir, dirent); file->f_pos = lower_file->f_pos; if (err >= 0) { /* copy the atime */ fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); } } dput(parent); return err; }
static int diaryfs_readlink(struct dentry * dentry, char __user *buf, int bufsize) { int err; struct dentry * lower_dentry; struct path lower_path; diaryfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; if (!lower_dentry->d_inode->i_op || !lower_dentry->d_inode->i_op->readlink) { err = -EINVAL; goto out; } /* err = lower_dentry->d_inode->i_op->readilnk(lower_dentry, buf, bufsize); if (err < 0) goto out; /FIXME */ fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); out: diaryfs_put_lower_path(dentry, &lower_path); return err; }
static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { ssize_t err; struct file *lower_file; struct dentry *dentry = file->f_path.dentry; struct dentry *parent; unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); err = unionfs_file_revalidate(file, parent, false); if (unlikely(err)) goto out; lower_file = unionfs_lower_file(file); err = vfs_splice_to(lower_file, ppos, pipe, len, flags); /* update our inode atime upon a successful lower splice-read */ if (err >= 0) { fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); unionfs_check_file(file); } out: unionfs_unlock_dentry(dentry); unionfs_unlock_parent(dentry, parent); unionfs_read_unlock(dentry->d_sb); return err; }
static ssize_t unionfs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int err; struct file *lower_file; struct dentry *dentry = file->f_path.dentry; struct dentry *parent; unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); err = unionfs_file_revalidate(file, parent, false); if (unlikely(err)) goto out; lower_file = unionfs_lower_file(file); err = vfs_read(lower_file, buf, count, ppos); /* update our inode atime upon a successful lower read */ if (err >= 0) { fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); unionfs_check_file(file); } out: unionfs_unlock_dentry(dentry); unionfs_unlock_parent(dentry, parent); unionfs_read_unlock(dentry->d_sb); return err; }
/* * On success: * fills dentry object appropriate values and returns NULL. * On fail (== error) * returns error ptr * * @dir : Parent inode. It is locked (dir->i_mutex) * @dentry : Target dentry to lookup. we should set each of fields. * (dentry->d_name is initialized already) * @nd : nameidata of parent inode */ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct dentry *ret = NULL, *parent; struct path lower_parent_path; int err = 0; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); const struct cred *saved_cred = NULL; parent = dget_parent(dentry); if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name, sbi->options.derive, 0, 0)) { ret = ERR_PTR(-EACCES); printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" " dentry: %s, task:%s\n", __func__, dentry->d_name.name, current->comm); goto out_err; } /* save current_cred and override it */ OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred); sdcardfs_get_lower_path(parent, &lower_parent_path); /* allocate dentry private data. We free it in ->d_release */ err = new_dentry_private_data(dentry); if (err) { ret = ERR_PTR(err); goto out; } ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path); if (IS_ERR(ret)) { goto out; } if (ret) dentry = ret; if (dentry->d_inode) { fsstack_copy_attr_times(dentry->d_inode, sdcardfs_lower_inode(dentry->d_inode)); /* get drived permission */ get_derived_permission(parent, dentry); fix_derived_permission(dentry->d_inode); } /* update parent directory's atime */ fsstack_copy_attr_atime(parent->d_inode, sdcardfs_lower_inode(parent->d_inode)); out: sdcardfs_put_lower_path(parent, &lower_parent_path); REVERT_CRED(saved_cred); out_err: dput(parent); return ret; }
static int ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) { char *lower_buf; struct dentry *lower_dentry; struct ecryptfs_crypt_stat *crypt_stat; char *plaintext_name; size_t plaintext_name_size; mm_segment_t old_fs; int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); if (!lower_dentry->d_inode->i_op->readlink) { rc = -EINVAL; goto out; } crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; /* Released in this function */ lower_buf = kmalloc(bufsiz, GFP_KERNEL); if (lower_buf == NULL) { printk(KERN_ERR "%s: Out of memory whilst attempting to " "kmalloc [%d] bytes\n", __func__, bufsiz); rc = -ENOMEM; goto out; } old_fs = get_fs(); set_fs(get_ds()); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, (char __user *)lower_buf, bufsiz); set_fs(old_fs); if (rc >= 0) { rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, &plaintext_name_size, dentry, lower_buf, rc); if (rc) { printk(KERN_ERR "%s: Error attempting to decode and " "decrypt filename; rc = [%d]\n", __func__, rc); goto out_free_lower_buf; } rc = copy_to_user(buf, plaintext_name, plaintext_name_size); if (rc) rc = -EFAULT; else rc = plaintext_name_size; kfree(plaintext_name); fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); } out_free_lower_buf: kfree(lower_buf); out: return rc; }
static const char *ecryptfs_follow_link(struct dentry *dentry, void **cookie) { size_t len; char *buf = ecryptfs_readlink_lower(dentry, &len); if (IS_ERR(buf)) return buf; fsstack_copy_attr_atime(d_inode(dentry), d_inode(ecryptfs_dentry_to_lower(dentry))); buf[len] = '\0'; return *cookie = buf; }
static int ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz) { int rc; struct dentry *lower_dentry; char *decoded_name; char *lower_buf; mm_segment_t old_fs; struct ecryptfs_crypt_stat *crypt_stat; lower_dentry = ecryptfs_dentry_to_lower(dentry); if (!lower_dentry->d_inode->i_op || !lower_dentry->d_inode->i_op->readlink) { rc = -EINVAL; goto out; } /* Released in this function */ lower_buf = kmalloc(bufsiz, GFP_KERNEL); if (lower_buf == NULL) { ecryptfs_printk(KERN_ERR, "Out of memory\n"); rc = -ENOMEM; goto out; } old_fs = get_fs(); set_fs(get_ds()); ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ " "lower_dentry->d_name.name = [%s]\n", lower_dentry->d_name.name); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, (char __user *)lower_buf, bufsiz); set_fs(old_fs); if (rc >= 0) { crypt_stat = NULL; rc = ecryptfs_decode_filename(crypt_stat, lower_buf, rc, &decoded_name); if (rc == -ENOMEM) goto out_free_lower_buf; if (rc > 0) { ecryptfs_printk(KERN_DEBUG, "Copying [%d] bytes " "to userspace: [%*s]\n", rc, decoded_name); if (copy_to_user(buf, decoded_name, rc)) rc = -EFAULT; } kfree(decoded_name); fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); } out_free_lower_buf: kfree(lower_buf); out: return rc; }
/** * ecryptfs_lookup_interpose - Dentry interposition for a lookup */ static int ecryptfs_lookup_interpose(struct dentry *dentry, struct dentry *lower_dentry, struct inode *dir_inode) { struct inode *inode, *lower_inode = lower_dentry->d_inode; struct ecryptfs_dentry_info *dentry_info; struct vfsmount *lower_mnt; int rc = 0; lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode); BUG_ON(!lower_dentry->d_count); dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); ecryptfs_set_dentry_private(dentry, dentry_info); if (!dentry_info) { printk(KERN_ERR "%s: Out of memory whilst attempting " "to allocate ecryptfs_dentry_info struct\n", __func__); dput(lower_dentry); mntput(lower_mnt); d_drop(dentry); return -ENOMEM; } ecryptfs_set_dentry_lower(dentry, lower_dentry); ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt); if (!lower_dentry->d_inode) { /* We want to add because we couldn't find in lower */ d_add(dentry, NULL); return 0; } inode = __ecryptfs_get_inode(lower_inode, dir_inode->i_sb); if (IS_ERR(inode)) { printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n", __func__, PTR_ERR(inode)); return PTR_ERR(inode); } if (S_ISREG(inode->i_mode)) { rc = ecryptfs_i_size_read(dentry, inode); if (rc) { make_bad_inode(inode); return rc; } } if (inode->i_state & I_NEW) unlock_new_inode(inode); d_add(dentry, inode); return rc; }
static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) { size_t len; char *buf = ecryptfs_readlink_lower(dentry, &len); if (IS_ERR(buf)) goto out; fsstack_copy_attr_atime(dentry->d_inode, ecryptfs_dentry_to_lower(dentry)->d_inode); buf[len] = '\0'; out: nd_set_link(nd, buf); return NULL; }
static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir) { int err = 0; struct file *lower_file = NULL; struct dentry *wrapfs_dentry = file->f_path.dentry; #ifdef EXTRA_CREDIT struct wrapfs_getdents_callback buf; if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_MESG("Enter"); #endif lower_file = wrapfs_lower_file(file); // lower_file->f_pos = file->f_pos; #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_OTHER) DEBUG_MESG("Encrypting and Decrypting filenames"); memset(&buf, 0, sizeof(buf)); buf.dirent = dirent; buf.dentry = wrapfs_dentry; buf.filldir = filldir; buf.filldir_called = 0; buf.entries_written = 0; err = vfs_readdir(lower_file, wrapfs_filldir, (void *)&buf); if(err<0) goto out; if(buf.filldir_called && !buf.entries_written) { printk(KERN_ERR "wrapfs_readdir: filldir called but entries not written\n"); goto out; } #else err = vfs_readdir(lower_file, filldir, dirent); #endif file->f_pos = lower_file->f_pos; if (err >= 0) /* copy the atime */ fsstack_copy_attr_atime(wrapfs_dentry->d_inode, lower_file->f_path.dentry->d_inode); #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_RETURN("Exit", err); out: #endif return err; }
static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir) { int err = 0; struct file *lower_file = NULL; struct dentry *dentry = file->f_path.dentry; lower_file = wrapfs_lower_file(file); err = vfs_readdir(lower_file, filldir, dirent); file->f_pos = lower_file->f_pos; if (err >= 0) /* copy the atime */ fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); return err; }
/** * ecryptfs_lookup_interpose - Dentry interposition for a lookup */ static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry, struct dentry *lower_dentry) { struct inode *inode, *lower_inode = d_inode(lower_dentry); struct ecryptfs_dentry_info *dentry_info; struct vfsmount *lower_mnt; int rc = 0; dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); if (!dentry_info) { printk(KERN_ERR "%s: Out of memory whilst attempting " "to allocate ecryptfs_dentry_info struct\n", __func__); dput(lower_dentry); return ERR_PTR(-ENOMEM); } lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); fsstack_copy_attr_atime(d_inode(dentry->d_parent), d_inode(lower_dentry->d_parent)); BUG_ON(!d_count(lower_dentry)); ecryptfs_set_dentry_private(dentry, dentry_info); dentry_info->lower_path.mnt = lower_mnt; dentry_info->lower_path.dentry = lower_dentry; if (d_really_is_negative(lower_dentry)) { /* We want to add because we couldn't find in lower */ d_add(dentry, NULL); return NULL; } inode = __ecryptfs_get_inode(lower_inode, dentry->d_sb); if (IS_ERR(inode)) { printk(KERN_ERR "%s: Error interposing; rc = [%ld]\n", __func__, PTR_ERR(inode)); return ERR_CAST(inode); } if (S_ISREG(inode->i_mode)) { rc = ecryptfs_i_size_read(dentry, inode); if (rc) { make_bad_inode(inode); return ERR_PTR(rc); } } if (inode->i_state & I_NEW) unlock_new_inode(inode); return d_splice_alias(inode, dentry); }
/* * scfs_readdir */ static int scfs_readdir(struct file *file, void *dirent, filldir_t filldir) { struct file *lower_file = NULL; struct dentry *dentry = file->f_path.dentry; int ret = 0; lower_file = scfs_lower_file(file); lower_file->f_pos = file->f_pos; ret = vfs_readdir(lower_file, filldir, dirent); file->f_pos = lower_file->f_pos; if (ret >= 0) fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); return ret; }
static ssize_t wrapfs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int err; struct file *lower_file; struct dentry *dentry = file->f_path.dentry; lower_file = wrapfs_lower_file(file); err = vfs_read(lower_file, buf, count, ppos); /* update our inode atime upon a successful lower read */ if (err >= 0) fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); return err; }
static int sdcardfs_readdir(struct file *file, struct dir_context *ctx) { int err = 0; struct file *lower_file = NULL; struct dentry *dentry = file->f_path.dentry; lower_file = sdcardfs_lower_file(file); lower_file->f_pos = file->f_pos; err = iterate_dir(lower_file, ctx); file->f_pos = lower_file->f_pos; if (err >= 0) /* copy the atime */ fsstack_copy_attr_atime(dentry->d_inode, lower_file->f_path.dentry->d_inode); return err; }
static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) { char *buf; size_t len = PATH_MAX; int rc; rc = ecryptfs_readlink_lower(dentry, &buf, &len); if (rc) goto out; fsstack_copy_attr_atime(dentry->d_inode, ecryptfs_dentry_to_lower(dentry)->d_inode); buf[len] = '\0'; out: nd_set_link(nd, buf); return NULL; }
static ssize_t fuse_shortcircuit_aio_read_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos, int do_write) { ssize_t ret_val; struct fuse_file *ff; struct file *fuse_file, *lower_file; struct inode *fuse_inode, *lower_inode; ff = iocb->ki_filp->private_data; fuse_file = iocb->ki_filp; lower_file = ff->rw_lower_file; /* lock lower file to prevent it from being released */ get_file(lower_file); iocb->ki_filp = lower_file; fuse_inode = fuse_file->f_path.dentry->d_inode; lower_inode = file_inode(lower_file); if (do_write) { if (!lower_file->f_op->aio_write) return -EIO; ret_val = lower_file->f_op->aio_write(iocb, iov, nr_segs, pos); if (ret_val >= 0 || ret_val == -EIOCBQUEUED) { fsstack_copy_inode_size(fuse_inode, lower_inode); fsstack_copy_attr_times(fuse_inode, lower_inode); } } else { if (!lower_file->f_op->aio_read) return -EIO; ret_val = lower_file->f_op->aio_read(iocb, iov, nr_segs, pos); if (ret_val >= 0 || ret_val == -EIOCBQUEUED) fsstack_copy_attr_atime(fuse_inode, lower_inode); } iocb->ki_filp = fuse_file; fput(lower_file); /* unlock lower file */ return ret_val; }
static int ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) { char *kbuf; size_t kbufsiz, copied; int rc; rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz); if (rc) goto out; copied = min_t(size_t, bufsiz, kbufsiz); rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied; kfree(kbuf); fsstack_copy_attr_atime(dentry->d_inode, ecryptfs_dentry_to_lower(dentry)->d_inode); out: return rc; }
/** * lofs_readdir * @file: The lofs directory file. * @dirent: Buffer to fill with directory entries. * @filldir: The filldir callback function */ static int lofs_readdir(struct file *file, void *dirent, filldir_t filldir) { int rc; struct file *lower_file; struct inode *inode; lower_file = lofs_file_to_lower(file); if (lower_file->f_pos != file->f_pos) { vfs_llseek(lower_file, file->f_pos, 0 /* SEEK_SET */); } inode = FILE_TO_DENTRY(file)->d_inode; rc = vfs_readdir(lower_file, filldir, dirent); file->f_pos = lower_file->f_pos; if (rc >= 0) { fsstack_copy_attr_atime(inode,FILE_TO_DENTRY(lower_file)->d_inode); } return rc; }
static ssize_t diaryfs_listxattr(struct dentry * dentry, char * buffer, size_t buffer_size) { int err; struct dentry * lower_dentry; struct path lower_path; diaryfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; if (!lower_dentry->d_inode->i_op->listxattr) { err = -EOPNOTSUPP; goto out; } err = vfs_listxattr(lower_dentry, buffer, buffer_size); if (err) goto out; fsstack_copy_attr_atime(dentry->d_inode, lower_path.dentry->d_inode); out: diaryfs_put_lower_path(dentry, &lower_path); return err; }
static const char *ecryptfs_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) { size_t len; char *buf; if (!dentry) return ERR_PTR(-ECHILD); buf = ecryptfs_readlink_lower(dentry, &len); if (IS_ERR(buf)) return buf; fsstack_copy_attr_atime(d_inode(dentry), d_inode(ecryptfs_dentry_to_lower(dentry))); buf[len] = '\0'; set_delayed_call(done, kfree_link, buf); return buf; }
int ccfs_readdir (struct file *filp, void *dirent, filldir_t filldir) { int rc; struct file *lower_file; struct inode *inode; lower_file = ccfs_get_nested_file(filp); mdbg(INFO3, "Read filp %p with lower file: %p Pos: %lu (Upper pos: %lu)", filp, lower_file, (unsigned long)lower_file->f_pos, (unsigned long)filp->f_pos); lower_file->f_pos = filp->f_pos; inode = filp->f_path.dentry->d_inode; rc = vfs_readdir(lower_file, filldir, dirent); mdbg(INFO3, "Read return code: %d", rc); filp->f_pos = lower_file->f_pos; if (rc >= 0) fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode); // The following does not seem to be true at least with kernel 2.6.33.1, so we leave dirs cacheable again // We need to disable file caching after readdir, as some filesystems (9P) are not able to repear readdirs on a same file! //ccfs_inode_to_private(inode)->cacheable = 0; return rc; }