int v9fs_dir_release(struct inode *inode, struct file *filp) { struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); struct v9fs_fid *fid = filp->private_data; int fidnum = -1; dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); fidnum = fid->fid; filemap_write_and_wait(inode->i_mapping); if (fidnum >= 0) { dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, fid->fid); if (v9fs_t_clunk(v9ses, fidnum)) dprintk(DEBUG_ERROR, "clunk failed\n"); kfree(fid->rdir_fcall); kfree(fid); filp->private_data = NULL; } return 0; }
void v9fs_dentry_release(struct dentry *dentry) { int err; dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); if (dentry->d_fsdata != NULL) { struct list_head *fid_list = dentry->d_fsdata; struct v9fs_fid *temp = NULL; struct v9fs_fid *current_fid = NULL; list_for_each_entry_safe(current_fid, temp, fid_list, list) { err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid); if (err < 0) dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n", err, dentry->d_iname); v9fs_fid_destroy(current_fid); } kfree(dentry->d_fsdata); /* free the list_head */ }
int v9fs_session_init(struct v9fs_session_info *v9ses, const char *dev_name, char *data) { struct v9fs_fcall *fcall = NULL; struct v9fs_transport *trans_proto; int n = 0; int newfid = -1; int retval = -EINVAL; struct v9fs_str *version; v9ses->name = __getname(); if (!v9ses->name) return -ENOMEM; v9ses->remotename = __getname(); if (!v9ses->remotename) { __putname(v9ses->name); return -ENOMEM; } strcpy(v9ses->name, V9FS_DEFUSER); strcpy(v9ses->remotename, V9FS_DEFANAME); v9fs_parse_options(data, v9ses); /* set global debug level */ v9fs_debug_level = v9ses->debug; /* id pools that are session-dependent: fids and tags */ idr_init(&v9ses->fidpool.pool); init_MUTEX(&v9ses->fidpool.lock); switch (v9ses->proto) { case PROTO_TCP: trans_proto = &v9fs_trans_tcp; break; case PROTO_UNIX: trans_proto = &v9fs_trans_unix; *v9ses->remotename = 0; break; case PROTO_FD: trans_proto = &v9fs_trans_fd; *v9ses->remotename = 0; break; default: printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); retval = -ENOPROTOOPT; goto SessCleanUp; }; v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); if (!v9ses->transport) { retval = -ENOMEM; goto SessCleanUp; } memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { eprintk(KERN_ERR, "problem initializing transport\n"); goto SessCleanUp; } v9ses->inprogress = 0; v9ses->shutdown = 0; v9ses->session_hung = 0; v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ, &v9ses->extended); if (IS_ERR(v9ses->mux)) { retval = PTR_ERR(v9ses->mux); v9ses->mux = NULL; dprintk(DEBUG_ERROR, "problem initializing mux\n"); goto SessCleanUp; } if (v9ses->afid == ~0) { if (v9ses->extended) retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u", &fcall); else retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000", &fcall); if (retval < 0) { dprintk(DEBUG_ERROR, "v9fs_t_version failed\n"); goto FreeFcall; } version = &fcall->params.rversion.version; if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) { dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); v9ses->extended = 1; } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) { dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n"); v9ses->extended = 0; } else { retval = -EREMOTEIO; goto FreeFcall; } n = fcall->params.rversion.msize; kfree(fcall); if (n < v9ses->maxdata) v9ses->maxdata = n; } newfid = v9fs_get_idpool(&v9ses->fidpool); if (newfid < 0) { eprintk(KERN_WARNING, "couldn't allocate FID\n"); retval = -ENOMEM; goto SessCleanUp; } /* it is a little bit ugly, but we have to prevent newfid */ /* being the same as afid, so if it is, get a new fid */ if (v9ses->afid != ~0 && newfid == v9ses->afid) { newfid = v9fs_get_idpool(&v9ses->fidpool); if (newfid < 0) { eprintk(KERN_WARNING, "couldn't allocate FID\n"); retval = -ENOMEM; goto SessCleanUp; } } if ((retval = v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid, v9ses->afid, NULL)) < 0) { dprintk(DEBUG_ERROR, "cannot attach\n"); goto SessCleanUp; } if (v9ses->afid != ~0) { dprintk(DEBUG_ERROR, "afid not equal to ~0\n"); if (v9fs_t_clunk(v9ses, v9ses->afid)) dprintk(DEBUG_ERROR, "clunk failed\n"); } return newfid; FreeFcall: kfree(fcall); SessCleanUp: v9fs_session_close(v9ses); return retval; }
static int v9fs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { struct super_block *sb = NULL; struct v9fs_fcall *fcall = NULL; struct inode *inode = NULL; struct dentry *root = NULL; struct v9fs_session_info *v9ses = NULL; struct v9fs_fid *root_fid = NULL; int mode = S_IRWXUGO | S_ISVTX; uid_t uid = current->fsuid; gid_t gid = current->fsgid; int stat_result = 0; int newfid = 0; int retval = 0; dprintk(DEBUG_VFS, " \n"); v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) return -ENOMEM; if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { dprintk(DEBUG_ERROR, "problem initiating session\n"); retval = newfid; goto out_free_session; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); goto out_close_session; } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); if (IS_ERR(inode)) { retval = PTR_ERR(inode); goto put_back_sb; } inode->i_uid = uid; inode->i_gid = gid; root = d_alloc_root(inode); if (!root) { retval = -ENOMEM; goto put_back_sb; } sb->s_root = root; stat_result = v9fs_t_stat(v9ses, newfid, &fcall); if (stat_result < 0) { dprintk(DEBUG_ERROR, "stat error\n"); v9fs_t_clunk(v9ses, newfid); } else { /* Setup the Root Inode */ root_fid = v9fs_fid_create(v9ses, newfid); if (root_fid == NULL) { retval = -ENOMEM; goto put_back_sb; } retval = v9fs_fid_insert(root_fid, root); if (retval < 0) { kfree(fcall); goto put_back_sb; } root_fid->qid = fcall->params.rstat.stat.qid; root->d_inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb); } kfree(fcall); if (stat_result < 0) { retval = stat_result; goto put_back_sb; } return simple_set_mnt(mnt, sb); out_close_session: v9fs_session_close(v9ses); out_free_session: kfree(v9ses); return retval; put_back_sb: /* deactivate_super calls v9fs_kill_super which will frees the rest */ up_write(&sb->s_umount); deactivate_super(sb); return retval; }