static void v9fs_kill_super(struct super_block *s) { struct v9fs_session_info *v9ses = s->s_fs_info; p9_debug(P9_DEBUG_VFS, " %p\n", s); kill_anon_super(s); v9fs_session_cancel(v9ses); v9fs_session_close(v9ses); kfree(v9ses); s->s_fs_info = NULL; p9_debug(P9_DEBUG_VFS, "exiting kill_super\n"); }
static void v9fs_kill_super(struct super_block *s) { struct v9fs_session_info *v9ses = s->s_fs_info; P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); v9fs_dentry_release(s->s_root); /* clunk root */ kill_anon_super(s); v9fs_session_close(v9ses); kfree(v9ses); P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); }
static void v9fs_kill_super(struct super_block *s) { struct v9fs_session_info *v9ses = s->s_fs_info; P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); #if RHEL6_COMPAT v9fs_dentry_release(s->s_root); /* clunk root */ #endif kill_anon_super(s); v9fs_session_cancel(v9ses); v9fs_session_close(v9ses); kfree(v9ses); s->s_fs_info = NULL; P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); }
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 inode *inode = NULL; struct dentry *root = NULL; struct v9fs_session_info *v9ses = NULL; struct p9_stat *st = NULL; int mode = S_IRWXUGO | S_ISVTX; uid_t uid = current->fsuid; gid_t gid = current->fsgid; struct p9_fid *fid; int retval = 0; P9_DPRINTK(P9_DEBUG_VFS, " \n"); st = NULL; v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) return -ENOMEM; fid = v9fs_session_init(v9ses, dev_name, data); if (IS_ERR(fid)) { retval = PTR_ERR(fid); fid = NULL; kfree(v9ses); v9ses = NULL; goto error; } st = p9_client_stat(fid); if (IS_ERR(st)) { retval = PTR_ERR(st); goto error; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); goto error; } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); if (IS_ERR(inode)) { retval = PTR_ERR(inode); goto error; } inode->i_uid = uid; inode->i_gid = gid; root = d_alloc_root(inode); if (!root) { retval = -ENOMEM; goto error; } sb->s_root = root; root->d_inode->i_ino = v9fs_qid2ino(&st->qid); v9fs_stat2inode(st, root->d_inode, sb); v9fs_fid_add(root, fid); kfree(st); return simple_set_mnt(mnt, sb); error: kfree(st); if (fid) p9_client_clunk(fid); if (v9ses) { v9fs_session_close(v9ses); kfree(v9ses); } if (sb) { up_write(&sb->s_umount); deactivate_super(sb); } 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 inode *inode = NULL; struct dentry *root = NULL; struct v9fs_session_info *v9ses = NULL; int mode = S_IRWXUGO | S_ISVTX; struct p9_fid *fid; int retval = 0; P9_DPRINTK(P9_DEBUG_VFS, " \n"); v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) return -ENOMEM; fid = v9fs_session_init(v9ses, dev_name, data); if (IS_ERR(fid)) { retval = PTR_ERR(fid); /* * we need to call session_close to tear down some * of the data structure setup by session_init */ goto close_session; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); goto clunk_fid; } v9fs_fill_super(sb, v9ses, flags, data); inode = v9fs_get_inode(sb, S_IFDIR | mode); if (IS_ERR(inode)) { retval = PTR_ERR(inode); goto release_sb; } root = d_alloc_root(inode); if (!root) { iput(inode); retval = -ENOMEM; goto release_sb; } sb->s_root = root; if (v9fs_proto_dotl(v9ses)) { struct p9_stat_dotl *st = NULL; st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); if (IS_ERR(st)) { retval = PTR_ERR(st); goto release_sb; } v9fs_stat2inode_dotl(st, root->d_inode); kfree(st); } else { struct p9_wstat *st = NULL; st = p9_client_stat(fid); if (IS_ERR(st)) { retval = PTR_ERR(st); goto release_sb; } root->d_inode->i_ino = v9fs_qid2ino(&st->qid); v9fs_stat2inode(st, root->d_inode, sb); p9stat_free(st); kfree(st); } retval = v9fs_get_acl(inode, fid); if (retval) goto release_sb; v9fs_fid_add(root, fid); P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); simple_set_mnt(mnt, sb); return 0; clunk_fid: p9_client_clunk(fid); close_session: v9fs_session_close(v9ses); kfree(v9ses); return retval; release_sb: /* * we will do the session_close and root dentry release * in the below call. But we need to clunk fid, because we haven't * attached the fid to dentry so it won't get clunked * automatically. */ p9_client_clunk(fid); deactivate_locked_super(sb); return retval; }
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; }
struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, const char *dev_name, char *data) { int retval = -EINVAL; struct p9_transport *trans; struct p9_fid *fid; v9ses->name = __getname(); if (!v9ses->name) return ERR_PTR(-ENOMEM); v9ses->remotename = __getname(); if (!v9ses->remotename) { __putname(v9ses->name); return ERR_PTR(-ENOMEM); } strcpy(v9ses->name, V9FS_DEFUSER); strcpy(v9ses->remotename, V9FS_DEFANAME); v9fs_parse_options(data, v9ses); switch (v9ses->proto) { case PROTO_TCP: trans = p9_trans_create_tcp(dev_name, v9ses->port); break; case PROTO_UNIX: trans = p9_trans_create_unix(dev_name); *v9ses->remotename = 0; break; case PROTO_FD: trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno); *v9ses->remotename = 0; break; #ifdef CONFIG_PCI_9P case PROTO_PCI: trans = p9pci_trans_create(); *v9ses->remotename = 0; break; #endif default: printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); retval = -ENOPROTOOPT; goto error; }; if (IS_ERR(trans)) { retval = PTR_ERR(trans); trans = NULL; goto error; } v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ, v9ses->extended); if (IS_ERR(v9ses->clnt)) { retval = PTR_ERR(v9ses->clnt); v9ses->clnt = NULL; P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n"); goto error; } fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name, v9ses->remotename); if (IS_ERR(fid)) { retval = PTR_ERR(fid); fid = NULL; P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n"); goto error; } return fid; error: v9fs_session_close(v9ses); return ERR_PTR(retval); }
static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { struct super_block *sb = NULL; struct inode *inode = NULL; struct dentry *root = NULL; struct v9fs_session_info *v9ses = NULL; umode_t mode = S_IRWXUGO | S_ISVTX; struct p9_fid *fid; int retval = 0; p9_debug(P9_DEBUG_VFS, "\n"); v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) return ERR_PTR(-ENOMEM); fid = v9fs_session_init(v9ses, dev_name, data); if (IS_ERR(fid)) { retval = PTR_ERR(fid); goto free_session; } sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); goto clunk_fid; } v9fs_fill_super(sb, v9ses, flags, data); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) sb->s_d_op = &v9fs_cached_dentry_operations; else sb->s_d_op = &v9fs_dentry_operations; inode = v9fs_get_inode(sb, S_IFDIR | mode, 0); if (IS_ERR(inode)) { retval = PTR_ERR(inode); goto release_sb; } root = d_make_root(inode); if (!root) { retval = -ENOMEM; goto release_sb; } sb->s_root = root; if (v9fs_proto_dotl(v9ses)) { struct p9_stat_dotl *st = NULL; st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); if (IS_ERR(st)) { retval = PTR_ERR(st); goto release_sb; } d_inode(root)->i_ino = v9fs_qid2ino(&st->qid); v9fs_stat2inode_dotl(st, d_inode(root)); kfree(st); } else { struct p9_wstat *st = NULL; st = p9_client_stat(fid); if (IS_ERR(st)) { retval = PTR_ERR(st); goto release_sb; } d_inode(root)->i_ino = v9fs_qid2ino(&st->qid); v9fs_stat2inode(st, d_inode(root), sb); p9stat_free(st); kfree(st); } retval = v9fs_get_acl(inode, fid); if (retval) goto release_sb; v9fs_fid_add(root, fid); p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n"); return dget(sb->s_root); clunk_fid: p9_client_clunk(fid); v9fs_session_close(v9ses); free_session: kfree(v9ses); return ERR_PTR(retval); release_sb: /* * we will do the session_close and root dentry release * in the below call. But we need to clunk fid, because we haven't * attached the fid to dentry so it won't get clunked * automatically. */ p9_client_clunk(fid); deactivate_locked_super(sb); return ERR_PTR(retval); }