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_debug(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_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); if (v9ses->cache) v9fs_cache_inode_set_cookie(inode, file); return 0; out_error: p9_client_clunk(file->private_data); file->private_data = NULL; return err; }
int v9fs_file_open(struct inode *inode, struct file *file) { int err; struct v9fs_session_info *v9ses; struct p9_fid *fid; int omode; P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file); v9ses = v9fs_inode2v9ses(inode); 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 (omode & P9_OTRUNC) { i_size_write(inode, 0); inode->i_blocks = 0; } if ((file->f_flags & O_APPEND) && (!v9fs_proto_dotu(v9ses))) generic_file_llseek(file, 0, SEEK_END); } file->private_data = fid; if ((fid->qid.version) && (v9ses->cache)) { P9_DPRINTK(P9_DEBUG_VFS, "cached"); /* enable cached file options */ if(file->f_op == &v9fs_file_operations) file->f_op = &v9fs_cached_file_operations; #ifdef CONFIG_9P_FSCACHE v9fs_cache_inode_set_cookie(inode, file); #endif } return 0; }
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; }