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