/** * v9fs_clear_inode - release an inode * @inode: inode to release * */ void v9fs_evict_inode(struct inode *inode) { struct v9fs_inode *v9inode = V9FS_I(inode); truncate_inode_pages(inode->i_mapping, 0); end_writeback(inode); filemap_fdatawrite(inode->i_mapping); #ifdef CONFIG_9P_FSCACHE v9fs_cache_inode_put_cookie(inode); #endif /* clunk the fid stashed in writeback_fid */ if (v9inode->writeback_fid) { p9_client_clunk(v9inode->writeback_fid); v9inode->writeback_fid = NULL; } }
void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) { struct v9fs_inode *v9inode = V9FS_I(inode); struct p9_fid *fid; if (!v9inode->fscache) return; spin_lock(&v9inode->fscache_lock); fid = filp->private_data; if ((filp->f_flags & O_ACCMODE) != O_RDONLY) v9fs_cache_inode_flush_cookie(inode); else v9fs_cache_inode_get_cookie(inode); spin_unlock(&v9inode->fscache_lock); }
static int v9fs_write_inode(struct inode *inode, struct writeback_control *wbc) { int ret; struct p9_wstat wstat; struct v9fs_inode *v9inode; p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); v9inode = V9FS_I(inode); if (!v9inode->writeback_fid) return 0; v9fs_blank_wstat(&wstat); ret = p9_client_wstat(v9inode->writeback_fid, &wstat); if (ret < 0) { __mark_inode_dirty(inode, I_DIRTY_DATASYNC); return ret; } return 0; }
void v9fs_cache_inode_get_cookie(struct inode *inode) { struct v9fs_inode *v9inode; struct v9fs_session_info *v9ses; if (!S_ISREG(inode->i_mode)) return; v9inode = V9FS_I(inode); if (v9inode->fscache) return; v9ses = v9fs_inode2v9ses(inode); v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, &v9fs_cache_inode_index_def, v9inode); p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", inode, v9inode->fscache); }
static int v9fs_write_inode_dotl(struct inode *inode, struct writeback_control *wbc) { int ret; struct v9fs_inode *v9inode; /* * send an fsync request to server irrespective of * wbc->sync_mode. */ P9_DPRINTK(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); v9inode = V9FS_I(inode); if (!v9inode->writeback_fid) return 0; ret = p9_client_fsync(v9inode->writeback_fid, 0); if (ret < 0) { __mark_inode_dirty(inode, I_DIRTY_DATASYNC); return ret; } return 0; }
static int v9fs_test_inode_dotl(struct inode *inode, void *data) { struct v9fs_inode *v9inode = V9FS_I(inode); struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; /* don't match inode of different type */ if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) return 0; if (inode->i_generation != st->st_gen) return 0; /* compare qid details */ if (memcmp(&v9inode->qid.version, &st->qid.version, sizeof(v9inode->qid.version))) return 0; if (v9inode->qid.type != st->qid.type) return 0; return 1; }
static int v9fs_test_inode(struct inode *inode, void *data) { int umode; struct v9fs_inode *v9inode = V9FS_I(inode); struct p9_wstat *st = (struct p9_wstat *)data; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); umode = p9mode2unixmode(v9ses, st->mode); /* don't match inode of different type */ if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) return 0; /* compare qid details */ if (memcmp(&v9inode->qid.version, &st->qid.version, sizeof(v9inode->qid.version))) return 0; if (v9inode->qid.type != st->qid.type) return 0; return 1; }
void v9fs_cache_inode_reset_cookie(struct inode *inode) { struct v9fs_inode *v9inode = V9FS_I(inode); struct v9fs_session_info *v9ses; struct fscache_cookie *old; if (!v9inode->fscache) return; old = v9inode->fscache; spin_lock(&v9inode->fscache_lock); fscache_relinquish_cookie(v9inode->fscache, 1); v9ses = v9fs_inode2v9ses(inode); v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, &v9fs_cache_inode_index_def, v9inode); p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n", inode, old, v9inode->fscache); spin_unlock(&v9inode->fscache_lock); }
static int v9fs_mmap_file_mmap(struct file *filp, struct vm_area_struct *vma) { int retval; struct inode *inode; struct v9fs_inode *v9inode; struct p9_fid *fid; inode = file_inode(filp); v9inode = V9FS_I(inode); mutex_lock(&v9inode->v_mutex); if (!v9inode->writeback_fid && (vma->vm_flags & VM_WRITE)) { /* * clone a fid and add it to writeback_fid * we do it during mmap instead of * page dirty time via write_begin/page_mkwrite * because we want write after unlink usecase * to work. */ fid = v9fs_writeback_fid(file_dentry(filp)); if (IS_ERR(fid)) { retval = PTR_ERR(fid); mutex_unlock(&v9inode->v_mutex); return retval; } v9inode->writeback_fid = (void *) fid; } mutex_unlock(&v9inode->v_mutex); retval = generic_file_mmap(filp, vma); if (!retval) vma->vm_ops = &v9fs_mmap_file_vm_ops; return retval; }
int v9fs_file_open(struct inode *inode, struct file *file) { int err; struct v9fs_inode *v9inode; struct v9fs_session_info *v9ses; struct p9_fid *fid; int omode; P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); v9inode = V9FS_I(inode); v9ses = v9fs_inode2v9ses(inode); if (v9fs_proto_dotl(v9ses)) omode = v9fs_open_to_dotl_flags(file->f_flags); else omode = v9fs_uflags2omode(file->f_flags, v9fs_proto_dotu(v9ses)); fid = file->private_data; if (!fid) { fid = v9fs_fid_clone(file->f_path.dentry); if (IS_ERR(fid)) return PTR_ERR(fid); err = p9_client_open(fid, omode); if (err < 0) { p9_client_clunk(fid); return err; } if (file->f_flags & O_TRUNC) { i_size_write(inode, 0); inode->i_blocks = 0; } if ((file->f_flags & O_APPEND) && (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))) generic_file_llseek(file, 0, SEEK_END); } file->private_data = fid; mutex_lock(&v9inode->v_mutex); if (v9ses->cache && !v9inode->writeback_fid && ((file->f_flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of * page dirty time via write_begin/page_mkwrite * because we want write after unlink usecase * to work. */ fid = v9fs_writeback_fid(file->f_path.dentry); if (IS_ERR(fid)) { err = PTR_ERR(fid); mutex_unlock(&v9inode->v_mutex); goto out_error; } v9inode->writeback_fid = (void *) fid; } mutex_unlock(&v9inode->v_mutex); #ifdef CONFIG_9P_FSCACHE if (v9ses->cache) v9fs_cache_inode_set_cookie(inode, file); #endif return 0; out_error: p9_client_clunk(file->private_data); file->private_data = NULL; return err; }
static void v9fs_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); INIT_LIST_HEAD(&inode->i_dentry); kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); }
static void v9fs_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); }
void v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) { struct v9fs_inode *v9inode = V9FS_I(inode); if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { inode->i_atime.tv_sec = stat->st_atime_sec; inode->i_atime.tv_nsec = stat->st_atime_nsec; inode->i_mtime.tv_sec = stat->st_mtime_sec; inode->i_mtime.tv_nsec = stat->st_mtime_nsec; inode->i_ctime.tv_sec = stat->st_ctime_sec; inode->i_ctime.tv_nsec = stat->st_ctime_nsec; inode->i_uid = stat->st_uid; inode->i_gid = stat->st_gid; inode->i_nlink = stat->st_nlink; inode->i_mode = stat->st_mode; inode->i_rdev = new_decode_dev(stat->st_rdev); if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) init_special_inode(inode, inode->i_mode, inode->i_rdev); i_size_write(inode, stat->st_size); inode->i_blocks = stat->st_blocks; } else { if (stat->st_result_mask & P9_STATS_ATIME) { inode->i_atime.tv_sec = stat->st_atime_sec; inode->i_atime.tv_nsec = stat->st_atime_nsec; } if (stat->st_result_mask & P9_STATS_MTIME) { inode->i_mtime.tv_sec = stat->st_mtime_sec; inode->i_mtime.tv_nsec = stat->st_mtime_nsec; } if (stat->st_result_mask & P9_STATS_CTIME) { inode->i_ctime.tv_sec = stat->st_ctime_sec; inode->i_ctime.tv_nsec = stat->st_ctime_nsec; } if (stat->st_result_mask & P9_STATS_UID) inode->i_uid = stat->st_uid; if (stat->st_result_mask & P9_STATS_GID) inode->i_gid = stat->st_gid; if (stat->st_result_mask & P9_STATS_NLINK) inode->i_nlink = stat->st_nlink; if (stat->st_result_mask & P9_STATS_MODE) { inode->i_mode = stat->st_mode; if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) init_special_inode(inode, inode->i_mode, inode->i_rdev); } if (stat->st_result_mask & P9_STATS_RDEV) inode->i_rdev = new_decode_dev(stat->st_rdev); if (stat->st_result_mask & P9_STATS_SIZE) i_size_write(inode, stat->st_size); if (stat->st_result_mask & P9_STATS_BLOCKS) inode->i_blocks = stat->st_blocks; } if (stat->st_result_mask & P9_STATS_GEN) inode->i_generation = stat->st_gen; /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION * because the inode structure does not have fields for them. */ v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; }
static int v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, struct nameidata *nd) { int err = 0; gid_t gid; int flags; mode_t mode; char *name = NULL; struct file *filp; struct p9_qid qid; struct inode *inode; struct p9_fid *fid = NULL; struct v9fs_inode *v9inode; struct p9_fid *dfid, *ofid, *inode_fid; struct v9fs_session_info *v9ses; struct posix_acl *pacl = NULL, *dacl = NULL; v9ses = v9fs_inode2v9ses(dir); if (nd && nd->flags & LOOKUP_OPEN) flags = nd->intent.open.flags - 1; else { /* * create call without LOOKUP_OPEN is due * to mknod of regular files. So use mknod * operation. */ return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); } name = (char *) dentry->d_name.name; P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " "mode:0x%x\n", name, flags, omode); dfid = v9fs_fid_lookup(dentry->d_parent); if (IS_ERR(dfid)) { err = PTR_ERR(dfid); P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); return err; } /* clone a fid to use for creation */ ofid = p9_client_walk(dfid, 0, NULL, 1); if (IS_ERR(ofid)) { err = PTR_ERR(ofid); P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); return err; } gid = v9fs_get_fsgid_for_create(dir); mode = omode; /* Update mode based on ACL value */ err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); if (err) { P9_DPRINTK(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n", err); goto error; } err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); if (err < 0) { P9_DPRINTK(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n", err); goto error; } v9fs_invalidate_inode_attr(dir); /* instantiate inode and assign the unopened fid to the dentry */ fid = p9_client_walk(dfid, 1, &name, 1); if (IS_ERR(fid)) { err = PTR_ERR(fid); P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); fid = NULL; goto error; } inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); if (IS_ERR(inode)) { err = PTR_ERR(inode); P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); goto error; } d_instantiate(dentry, inode); err = v9fs_fid_add(dentry, fid); if (err < 0) goto error; /* Now set the ACL based on the default value */ v9fs_set_create_acl(dentry, dacl, pacl); v9inode = V9FS_I(inode); mutex_lock(&v9inode->v_mutex); if (v9ses->cache && !v9inode->writeback_fid && ((flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of * page dirty time via write_begin/page_mkwrite * because we want write after unlink usecase * to work. */ inode_fid = v9fs_writeback_fid(dentry); if (IS_ERR(inode_fid)) { err = PTR_ERR(inode_fid); mutex_unlock(&v9inode->v_mutex); goto error; } v9inode->writeback_fid = (void *) inode_fid; } mutex_unlock(&v9inode->v_mutex); /* Since we are opening a file, assign the open fid to the file */ filp = lookup_instantiate_filp(nd, dentry, generic_file_open); if (IS_ERR(filp)) { p9_client_clunk(ofid); return PTR_ERR(filp); } filp->private_data = ofid; #ifdef CONFIG_9P_FSCACHE if (v9ses->cache) v9fs_cache_inode_set_cookie(inode, filp); #endif return 0; error: if (ofid) p9_client_clunk(ofid); if (fid) p9_client_clunk(fid); return err; }