📄 client.c
字号:
/* * net/9p/clnt.c * * 9P Client * * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to: * Free Software Foundation * 51 Franklin Street, Fifth Floor * Boston, MA 02111-1301 USA * */#include <linux/module.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/idr.h>#include <linux/mutex.h>#include <linux/sched.h>#include <linux/uaccess.h>#include <net/9p/9p.h>#include <linux/parser.h>#include <net/9p/transport.h>#include <net/9p/conn.h>#include <net/9p/client.h>static struct p9_fid *p9_fid_create(struct p9_client *clnt);static void p9_fid_destroy(struct p9_fid *fid);static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);struct p9_client *p9_client_create(struct p9_trans *trans, int msize, int dotu){ int err, n; struct p9_client *clnt; struct p9_fcall *tc, *rc; struct p9_str *version; err = 0; tc = NULL; rc = NULL; clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); if (!clnt) return ERR_PTR(-ENOMEM); P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", clnt, trans, msize, dotu); spin_lock_init(&clnt->lock); clnt->trans = trans; clnt->msize = msize; clnt->dotu = dotu; INIT_LIST_HEAD(&clnt->fidlist); clnt->fidpool = p9_idpool_create(); if (!clnt->fidpool) { err = PTR_ERR(clnt->fidpool); clnt->fidpool = NULL; goto error; } clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu); if (IS_ERR(clnt->conn)) { err = PTR_ERR(clnt->conn); clnt->conn = NULL; goto error; } tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto error; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) goto error; version = &rc->params.rversion.version; if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8)) clnt->dotu = 1; else if (version->len == 6 && !memcmp(version->str, "9P2000", 6)) clnt->dotu = 0; else { err = -EREMOTEIO; goto error; } n = rc->params.rversion.msize; if (n < clnt->msize) clnt->msize = n; kfree(tc); kfree(rc); return clnt;error: kfree(tc); kfree(rc); p9_client_destroy(clnt); return ERR_PTR(err);}EXPORT_SYMBOL(p9_client_create);void p9_client_destroy(struct p9_client *clnt){ struct p9_fid *fid, *fidptr; P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); if (clnt->conn) { p9_conn_destroy(clnt->conn); clnt->conn = NULL; } if (clnt->trans) { clnt->trans->close(clnt->trans); kfree(clnt->trans); clnt->trans = NULL; } list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) p9_fid_destroy(fid); if (clnt->fidpool) p9_idpool_destroy(clnt->fidpool); kfree(clnt);}EXPORT_SYMBOL(p9_client_destroy);void p9_client_disconnect(struct p9_client *clnt){ P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); clnt->trans->status = Disconnected; p9_conn_cancel(clnt->conn, -EIO);}EXPORT_SYMBOL(p9_client_disconnect);struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, char *uname, u32 n_uname, char *aname){ int err; struct p9_fcall *tc, *rc; struct p9_fid *fid; P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n", clnt, afid?afid->fid:-1, uname, aname); err = 0; tc = NULL; rc = NULL; fid = p9_fid_create(clnt); if (IS_ERR(fid)) { err = PTR_ERR(fid); fid = NULL; goto error; } tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname, n_uname, clnt->dotu); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto error; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) goto error; memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid)); kfree(tc); kfree(rc); return fid;error: kfree(tc); kfree(rc); if (fid) p9_fid_destroy(fid); return ERR_PTR(err);}EXPORT_SYMBOL(p9_client_attach);struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname){ int err; struct p9_fcall *tc, *rc; struct p9_fid *fid; P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname, aname); err = 0; tc = NULL; rc = NULL; fid = p9_fid_create(clnt); if (IS_ERR(fid)) { err = PTR_ERR(fid); fid = NULL; goto error; } tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto error; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) goto error; memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid)); kfree(tc); kfree(rc); return fid;error: kfree(tc); kfree(rc); if (fid) p9_fid_destroy(fid); return ERR_PTR(err);}EXPORT_SYMBOL(p9_client_auth);struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, int clone){ int err; struct p9_fcall *tc, *rc; struct p9_client *clnt; struct p9_fid *fid; P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n", oldfid->fid, nwname, wnames?wnames[0]:NULL); err = 0; tc = NULL; rc = NULL; clnt = oldfid->clnt; if (clone) { fid = p9_fid_create(clnt); if (IS_ERR(fid)) { err = PTR_ERR(fid); fid = NULL; goto error; } fid->uid = oldfid->uid; } else fid = oldfid; tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto error; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) { if (rc && rc->id == P9_RWALK) goto clunk_fid; else goto error; } if (rc->params.rwalk.nwqid != nwname) { err = -ENOENT; goto clunk_fid; } if (nwname) memmove(&fid->qid, &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1], sizeof(struct p9_qid)); else fid->qid = oldfid->qid; kfree(tc); kfree(rc); return fid;clunk_fid: kfree(tc); kfree(rc); rc = NULL; tc = p9_create_tclunk(fid->fid); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto error; } p9_conn_rpc(clnt->conn, tc, &rc);error: kfree(tc); kfree(rc); if (fid && (fid != oldfid)) p9_fid_destroy(fid); return ERR_PTR(err);}EXPORT_SYMBOL(p9_client_walk);int p9_client_open(struct p9_fid *fid, int mode){ int err; struct p9_fcall *tc, *rc; struct p9_client *clnt; P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode); err = 0; tc = NULL; rc = NULL; clnt = fid->clnt; if (fid->mode != -1) return -EINVAL; tc = p9_create_topen(fid->fid, mode); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto done; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) goto done; fid->mode = mode; fid->iounit = rc->params.ropen.iounit;done: kfree(tc); kfree(rc); return err;}EXPORT_SYMBOL(p9_client_open);int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, char *extension){ int err; struct p9_fcall *tc, *rc; struct p9_client *clnt; P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid, name, perm, mode); err = 0; tc = NULL; rc = NULL; clnt = fid->clnt; if (fid->mode != -1) return -EINVAL; tc = p9_create_tcreate(fid->fid, name, perm, mode, extension, clnt->dotu); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto done; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) goto done; fid->mode = mode; fid->iounit = rc->params.ropen.iounit;done: kfree(tc); kfree(rc); return err;}EXPORT_SYMBOL(p9_client_fcreate);int p9_client_clunk(struct p9_fid *fid){ int err; struct p9_fcall *tc, *rc; struct p9_client *clnt; P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); err = 0; tc = NULL; rc = NULL; clnt = fid->clnt; tc = p9_create_tclunk(fid->fid); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto done; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) goto done; p9_fid_destroy(fid);done: kfree(tc); kfree(rc); return err;}EXPORT_SYMBOL(p9_client_clunk);int p9_client_remove(struct p9_fid *fid){ int err; struct p9_fcall *tc, *rc; struct p9_client *clnt; P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); err = 0; tc = NULL; rc = NULL; clnt = fid->clnt; tc = p9_create_tremove(fid->fid); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto done; } err = p9_conn_rpc(clnt->conn, tc, &rc); if (err) goto done; p9_fid_destroy(fid);done: kfree(tc); kfree(rc); return err;}EXPORT_SYMBOL(p9_client_remove);int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count){ int err, n, rsize, total; struct p9_fcall *tc, *rc; struct p9_client *clnt; P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid, (long long unsigned) offset, count); err = 0; tc = NULL; rc = NULL; clnt = fid->clnt; total = 0; rsize = fid->iounit; if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) rsize = clnt->msize - P9_IOHDRSZ; do { if (count < rsize) rsize = count; tc = p9_create_tread(fid->fid, offset, rsize); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; goto error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -