1*e97ad33aSDoug Rabson /*- 2*e97ad33aSDoug Rabson * Copyright (c) 2017 Juniper Networks, Inc. 3*e97ad33aSDoug Rabson * All rights reserved. 4*e97ad33aSDoug Rabson * 5*e97ad33aSDoug Rabson * Redistribution and use in source and binary forms, with or without 6*e97ad33aSDoug Rabson * modification, are permitted provided that the following conditions 7*e97ad33aSDoug Rabson * are met: 8*e97ad33aSDoug Rabson * 1. Redistributions of source code must retain the above copyright 9*e97ad33aSDoug Rabson * notice, this list of conditions and the following disclaimer. 10*e97ad33aSDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 11*e97ad33aSDoug Rabson * notice, this list of conditions and the following disclaimer in the 12*e97ad33aSDoug Rabson * documentation and/or other materials provided with the distribution. 13*e97ad33aSDoug Rabson * 14*e97ad33aSDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*e97ad33aSDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*e97ad33aSDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*e97ad33aSDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*e97ad33aSDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*e97ad33aSDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*e97ad33aSDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*e97ad33aSDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*e97ad33aSDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*e97ad33aSDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*e97ad33aSDoug Rabson * SUCH DAMAGE. 25*e97ad33aSDoug Rabson */ 26*e97ad33aSDoug Rabson 27*e97ad33aSDoug Rabson /* 9P client definitions */ 28*e97ad33aSDoug Rabson 29*e97ad33aSDoug Rabson #ifndef FS_P9FS_P9_CLIENT_H 30*e97ad33aSDoug Rabson #define FS_P9FS_P9_CLIENT_H 31*e97ad33aSDoug Rabson 32*e97ad33aSDoug Rabson #include <sys/errno.h> 33*e97ad33aSDoug Rabson #include <sys/types.h> 34*e97ad33aSDoug Rabson #include <sys/_unrhdr.h> 35*e97ad33aSDoug Rabson #include <sys/lock.h> 36*e97ad33aSDoug Rabson #include <sys/mutex.h> 37*e97ad33aSDoug Rabson #include <sys/condvar.h> 38*e97ad33aSDoug Rabson #include <sys/systm.h> 39*e97ad33aSDoug Rabson #include <sys/mount.h> 40*e97ad33aSDoug Rabson #include <sys/malloc.h> 41*e97ad33aSDoug Rabson #include <sys/kernel.h> 42*e97ad33aSDoug Rabson #include <sys/proc.h> 43*e97ad33aSDoug Rabson #include <sys/dirent.h> 44*e97ad33aSDoug Rabson #include <machine/stdarg.h> 45*e97ad33aSDoug Rabson 46*e97ad33aSDoug Rabson #include <fs/p9fs/p9_protocol.h> 47*e97ad33aSDoug Rabson 48*e97ad33aSDoug Rabson /* 9P protocol versions */ 49*e97ad33aSDoug Rabson enum p9_proto_versions { 50*e97ad33aSDoug Rabson p9_proto_legacy, /* legacy version */ 51*e97ad33aSDoug Rabson p9_proto_2000u, /* Unix version */ 52*e97ad33aSDoug Rabson p9_proto_2000L, /* Linux version */ 53*e97ad33aSDoug Rabson }; 54*e97ad33aSDoug Rabson 55*e97ad33aSDoug Rabson /* P9 Request exchanged between Host and Guest */ 56*e97ad33aSDoug Rabson struct p9_req_t { 57*e97ad33aSDoug Rabson struct p9_buffer *tc; /* request buffer */ 58*e97ad33aSDoug Rabson struct p9_buffer *rc; /* response buffer */ 59*e97ad33aSDoug Rabson }; 60*e97ad33aSDoug Rabson 61*e97ad33aSDoug Rabson /* 9P transport status */ 62*e97ad33aSDoug Rabson enum transport_status { 63*e97ad33aSDoug Rabson P9FS_CONNECT, /* transport is connected */ 64*e97ad33aSDoug Rabson P9FS_BEGIN_DISCONNECT,/* transport has begun to disconnect */ 65*e97ad33aSDoug Rabson P9FS_DISCONNECT, /* transport has been dosconnected */ 66*e97ad33aSDoug Rabson }; 67*e97ad33aSDoug Rabson 68*e97ad33aSDoug Rabson /* This is set by QEMU so we will oblige */ 69*e97ad33aSDoug Rabson #define P9FS_MTU 8192 70*e97ad33aSDoug Rabson 71*e97ad33aSDoug Rabson /* 72*e97ad33aSDoug Rabson * Even though we have a 8k buffer, Qemu is typically doing 8168 73*e97ad33aSDoug Rabson * because of a HDR of 24. Use that amount for transfers so that we dont 74*e97ad33aSDoug Rabson * drop anything. 75*e97ad33aSDoug Rabson */ 76*e97ad33aSDoug Rabson #define P9FS_IOUNIT (P9FS_MTU - 24) 77*e97ad33aSDoug Rabson #define P9FS_DIRENT_LEN 256 78*e97ad33aSDoug Rabson #define P9_NOTAG 0 79*e97ad33aSDoug Rabson 80*e97ad33aSDoug Rabson /* Client state information */ 81*e97ad33aSDoug Rabson struct p9_client { 82*e97ad33aSDoug Rabson struct p9_trans_module *ops; /* module API instantiated with this client */ 83*e97ad33aSDoug Rabson void *handle; /* module-specific client handle */ 84*e97ad33aSDoug Rabson struct mtx clnt_mtx; /* mutex to lock the client */ 85*e97ad33aSDoug Rabson struct mtx req_mtx; /* mutex to lock the request buffer */ 86*e97ad33aSDoug Rabson struct cv req_cv; /* condition variable on which to wake up thread */ 87*e97ad33aSDoug Rabson unsigned int msize; /* maximum data size */ 88*e97ad33aSDoug Rabson unsigned char proto_version; /* 9P version to use */ 89*e97ad33aSDoug Rabson struct unrhdr fidpool; /* fid handle accounting for session */ 90*e97ad33aSDoug Rabson struct unrhdr tagpool; /* transaction id accounting for session */ 91*e97ad33aSDoug Rabson enum transport_status trans_status; /* tranport instance state */ 92*e97ad33aSDoug Rabson }; 93*e97ad33aSDoug Rabson 94*e97ad33aSDoug Rabson /* The main fid structure which keeps track of the file.*/ 95*e97ad33aSDoug Rabson struct p9_fid { 96*e97ad33aSDoug Rabson struct p9_client *clnt; /* the instatntiating 9P client */ 97*e97ad33aSDoug Rabson uint32_t fid; /* numeric identifier */ 98*e97ad33aSDoug Rabson int mode; /* current mode of this fid */ 99*e97ad33aSDoug Rabson struct p9_qid qid; /* server identifier */ 100*e97ad33aSDoug Rabson uint32_t mtu; /* max transferrable unit at a time */ 101*e97ad33aSDoug Rabson uid_t uid; /* numeric uid of the local user who owns this handle */ 102*e97ad33aSDoug Rabson int v_opens; /* keep count on the number of opens called with this fiel handle */ 103*e97ad33aSDoug Rabson STAILQ_ENTRY(p9_fid) fid_next; /* points to next fid in the list */ 104*e97ad33aSDoug Rabson }; 105*e97ad33aSDoug Rabson 106*e97ad33aSDoug Rabson /* Directory entry structure */ 107*e97ad33aSDoug Rabson struct p9_dirent { 108*e97ad33aSDoug Rabson struct p9_qid qid; /* 9P server qid for this dirent */ 109*e97ad33aSDoug Rabson uint64_t d_off; /* offset to the next dirent */ 110*e97ad33aSDoug Rabson unsigned char d_type; /* file type */ 111*e97ad33aSDoug Rabson char d_name[P9FS_DIRENT_LEN]; /* file name */ 112*e97ad33aSDoug Rabson int len; 113*e97ad33aSDoug Rabson }; 114*e97ad33aSDoug Rabson 115*e97ad33aSDoug Rabson void p9_init_zones(void); 116*e97ad33aSDoug Rabson void p9_destroy_zones(void); 117*e97ad33aSDoug Rabson 118*e97ad33aSDoug Rabson /* Session and client Init Ops */ 119*e97ad33aSDoug Rabson struct p9_client *p9_client_create(struct mount *mp, int *error, 120*e97ad33aSDoug Rabson const char *mount_tag); 121*e97ad33aSDoug Rabson void p9_client_destroy(struct p9_client *clnt); 122*e97ad33aSDoug Rabson struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *fid, 123*e97ad33aSDoug Rabson const char *uname, uid_t n_uname, const char *aname, int *error); 124*e97ad33aSDoug Rabson 125*e97ad33aSDoug Rabson /* FILE OPS - These are individually called from the specific vop function */ 126*e97ad33aSDoug Rabson 127*e97ad33aSDoug Rabson int p9_client_open(struct p9_fid *fid, int mode); 128*e97ad33aSDoug Rabson int p9_client_close(struct p9_fid *fid); 129*e97ad33aSDoug Rabson struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwnames, 130*e97ad33aSDoug Rabson char **wnames, int clone, int *error); 131*e97ad33aSDoug Rabson struct p9_fid *p9_fid_create(struct p9_client *clnt); 132*e97ad33aSDoug Rabson void p9_fid_destroy(struct p9_fid *fid); 133*e97ad33aSDoug Rabson uint16_t p9_tag_create(struct p9_client *clnt); 134*e97ad33aSDoug Rabson void p9_tag_destroy(struct p9_client *clnt, uint16_t tag); 135*e97ad33aSDoug Rabson int p9_client_clunk(struct p9_fid *fid); 136*e97ad33aSDoug Rabson int p9_client_version(struct p9_client *clnt); 137*e97ad33aSDoug Rabson int p9_client_readdir(struct p9_fid *fid, char *data, uint64_t offset, uint32_t count); 138*e97ad33aSDoug Rabson int p9_client_read(struct p9_fid *fid, uint64_t offset, uint32_t count, char *data); 139*e97ad33aSDoug Rabson int p9_client_write(struct p9_fid *fid, uint64_t offset, uint32_t count, char *data); 140*e97ad33aSDoug Rabson int p9_client_file_create(struct p9_fid *fid, char *name, uint32_t perm, int mode, 141*e97ad33aSDoug Rabson char *extension); 142*e97ad33aSDoug Rabson int p9_client_remove(struct p9_fid *fid); 143*e97ad33aSDoug Rabson int p9_dirent_read(struct p9_client *clnt, char *buf, int start, int len, 144*e97ad33aSDoug Rabson struct p9_dirent *dirent); 145*e97ad33aSDoug Rabson int p9_client_statfs(struct p9_fid *fid, struct p9_statfs *stat); 146*e97ad33aSDoug Rabson int p9_client_statread(struct p9_client *clnt, char *data, size_t len, struct p9_wstat *st); 147*e97ad33aSDoug Rabson int p9_is_proto_dotu(struct p9_client *clnt); 148*e97ad33aSDoug Rabson int p9_is_proto_dotl(struct p9_client *clnt); 149*e97ad33aSDoug Rabson void p9_client_cb(struct p9_client *c, struct p9_req_t *req); 150*e97ad33aSDoug Rabson int p9stat_read(struct p9_client *clnt, char *data, size_t len, struct p9_wstat *st); 151*e97ad33aSDoug Rabson void p9_client_disconnect(struct p9_client *clnt); 152*e97ad33aSDoug Rabson void p9_client_begin_disconnect(struct p9_client *clnt); 153*e97ad33aSDoug Rabson int p9_create_symlink(struct p9_fid *fid, char *name, char *symtgt, gid_t gid); 154*e97ad33aSDoug Rabson int p9_create_hardlink(struct p9_fid *dfid, struct p9_fid *oldfid, char *name); 155*e97ad33aSDoug Rabson int p9_readlink(struct p9_fid *fid, char **target); 156*e97ad33aSDoug Rabson int p9_client_renameat(struct p9_fid *oldfid, char *oldname, struct p9_fid *newfid, char *newname); 157*e97ad33aSDoug Rabson int p9_client_getattr(struct p9_fid *fid, struct p9_stat_dotl *stat_dotl, 158*e97ad33aSDoug Rabson uint64_t request_mask); 159*e97ad33aSDoug Rabson int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr); 160*e97ad33aSDoug Rabson 161*e97ad33aSDoug Rabson int p9_buf_vwritef(struct p9_buffer *buf, int proto_version, const char *fmt, 162*e97ad33aSDoug Rabson va_list ap); 163*e97ad33aSDoug Rabson int p9_buf_readf(struct p9_buffer *buf, int proto_version, const char *fmt, ...); 164*e97ad33aSDoug Rabson int p9_buf_prepare(struct p9_buffer *buf, int8_t type); 165*e97ad33aSDoug Rabson int p9_buf_finalize(struct p9_client *clnt, struct p9_buffer *buf); 166*e97ad33aSDoug Rabson void p9_buf_reset(struct p9_buffer *buf); 167*e97ad33aSDoug Rabson 168*e97ad33aSDoug Rabson #endif /* FS_P9FS_P9_CLIENT_H */ 169