1 /* 2 * include/net/9p/client.h 3 * 4 * 9P Client Definitions 5 * 6 * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com> 7 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 11 * as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to: 20 * Free Software Foundation 21 * 51 Franklin Street, Fifth Floor 22 * Boston, MA 02111-1301 USA 23 * 24 */ 25 26 #ifndef NET_9P_CLIENT_H 27 #define NET_9P_CLIENT_H 28 29 #include <linux/utsname.h> 30 #include <linux/idr.h> 31 32 /* Number of requests per row */ 33 #define P9_ROW_MAXTAG 255 34 35 /** enum p9_proto_versions - 9P protocol versions 36 * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u 37 * @p9_proto_2000u: 9P2000.u extension 38 * @p9_proto_2000L: 9P2000.L extension 39 */ 40 41 enum p9_proto_versions{ 42 p9_proto_legacy, 43 p9_proto_2000u, 44 p9_proto_2000L, 45 }; 46 47 48 /** 49 * enum p9_trans_status - different states of underlying transports 50 * @Connected: transport is connected and healthy 51 * @Disconnected: transport has been disconnected 52 * @Hung: transport is connected by wedged 53 * 54 * This enumeration details the various states a transport 55 * instatiation can be in. 56 */ 57 58 enum p9_trans_status { 59 Connected, 60 BeginDisconnect, 61 Disconnected, 62 Hung, 63 }; 64 65 /** 66 * enum p9_req_status_t - status of a request 67 * @REQ_STATUS_IDLE: request slot unused 68 * @REQ_STATUS_ALLOC: request has been allocated but not sent 69 * @REQ_STATUS_UNSENT: request waiting to be sent 70 * @REQ_STATUS_SENT: request sent to server 71 * @REQ_STATUS_RCVD: response received from server 72 * @REQ_STATUS_FLSHD: request has been flushed 73 * @REQ_STATUS_ERROR: request encountered an error on the client side 74 * 75 * The @REQ_STATUS_IDLE state is used to mark a request slot as unused 76 * but use is actually tracked by the idpool structure which handles tag 77 * id allocation. 78 * 79 */ 80 81 enum p9_req_status_t { 82 REQ_STATUS_IDLE, 83 REQ_STATUS_ALLOC, 84 REQ_STATUS_UNSENT, 85 REQ_STATUS_SENT, 86 REQ_STATUS_RCVD, 87 REQ_STATUS_FLSHD, 88 REQ_STATUS_ERROR, 89 }; 90 91 /** 92 * struct p9_req_t - request slots 93 * @status: status of this request slot 94 * @t_err: transport error 95 * @flush_tag: tag of request being flushed (for flush requests) 96 * @wq: wait_queue for the client to block on for this request 97 * @tc: the request fcall structure 98 * @rc: the response fcall structure 99 * @aux: transport specific data (provided for trans_fd migration) 100 * @req_list: link for higher level objects to chain requests 101 * 102 * Transport use an array to track outstanding requests 103 * instead of a list. While this may incurr overhead during initial 104 * allocation or expansion, it makes request lookup much easier as the 105 * tag id is a index into an array. (We use tag+1 so that we can accommodate 106 * the -1 tag for the T_VERSION request). 107 * This also has the nice effect of only having to allocate wait_queues 108 * once, instead of constantly allocating and freeing them. Its possible 109 * other resources could benefit from this scheme as well. 110 * 111 */ 112 113 struct p9_req_t { 114 int status; 115 int t_err; 116 wait_queue_head_t wq; 117 struct p9_fcall *tc; 118 struct p9_fcall *rc; 119 void *aux; 120 121 struct list_head req_list; 122 }; 123 124 /** 125 * struct p9_client - per client instance state 126 * @lock: protect @fidlist 127 * @msize: maximum data size negotiated by protocol 128 * @dotu: extension flags negotiated by protocol 129 * @proto_version: 9P protocol version to use 130 * @trans_mod: module API instantiated with this client 131 * @trans: tranport instance state and API 132 * @fids: All active FID handles 133 * @tagpool - transaction id accounting for session 134 * @reqs - 2D array of requests 135 * @max_tag - current maximum tag id allocated 136 * @name - node name used as client id 137 * 138 * The client structure is used to keep track of various per-client 139 * state that has been instantiated. 140 * In order to minimize per-transaction overhead we use a 141 * simple array to lookup requests instead of a hash table 142 * or linked list. In order to support larger number of 143 * transactions, we make this a 2D array, allocating new rows 144 * when we need to grow the total number of the transactions. 145 * 146 * Each row is 256 requests and we'll support up to 256 rows for 147 * a total of 64k concurrent requests per session. 148 * 149 * Bugs: duplicated data and potentially unnecessary elements. 150 */ 151 152 struct p9_client { 153 spinlock_t lock; /* protect client structure */ 154 unsigned int msize; 155 unsigned char proto_version; 156 struct p9_trans_module *trans_mod; 157 enum p9_trans_status status; 158 void *trans; 159 160 union { 161 struct { 162 int rfd; 163 int wfd; 164 } fd; 165 struct { 166 u16 port; 167 bool privport; 168 169 } tcp; 170 } trans_opts; 171 172 struct idr fids; 173 174 struct p9_idpool *tagpool; 175 struct p9_req_t *reqs[P9_ROW_MAXTAG]; 176 int max_tag; 177 178 char name[__NEW_UTS_LEN + 1]; 179 }; 180 181 /** 182 * struct p9_fid - file system entity handle 183 * @clnt: back pointer to instantiating &p9_client 184 * @fid: numeric identifier for this handle 185 * @mode: current mode of this fid (enum?) 186 * @qid: the &p9_qid server identifier this handle points to 187 * @iounit: the server reported maximum transaction size for this file 188 * @uid: the numeric uid of the local user who owns this handle 189 * @rdir: readdir accounting structure (allocated on demand) 190 * @dlist: per-dentry fid tracking 191 * 192 * TODO: This needs lots of explanation. 193 */ 194 195 struct p9_fid { 196 struct p9_client *clnt; 197 u32 fid; 198 int mode; 199 struct p9_qid qid; 200 u32 iounit; 201 kuid_t uid; 202 203 void *rdir; 204 205 struct hlist_node dlist; /* list of all fids attached to a dentry */ 206 }; 207 208 /** 209 * struct p9_dirent - directory entry structure 210 * @qid: The p9 server qid for this dirent 211 * @d_off: offset to the next dirent 212 * @d_type: type of file 213 * @d_name: file name 214 */ 215 216 struct p9_dirent { 217 struct p9_qid qid; 218 u64 d_off; 219 unsigned char d_type; 220 char d_name[256]; 221 }; 222 223 struct iov_iter; 224 225 int p9_show_client_options(struct seq_file *m, struct p9_client *clnt); 226 int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb); 227 int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, 228 const char *name); 229 int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, 230 struct p9_fid *newdirfid, const char *new_name); 231 struct p9_client *p9_client_create(const char *dev_name, char *options); 232 void p9_client_destroy(struct p9_client *clnt); 233 void p9_client_disconnect(struct p9_client *clnt); 234 void p9_client_begin_disconnect(struct p9_client *clnt); 235 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 236 const char *uname, kuid_t n_uname, const char *aname); 237 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, 238 const unsigned char * const *wnames, int clone); 239 int p9_client_open(struct p9_fid *fid, int mode); 240 int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode, 241 char *extension); 242 int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, const char *newname); 243 int p9_client_symlink(struct p9_fid *fid, const char *name, const char *symname, 244 kgid_t gid, struct p9_qid *qid); 245 int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 mode, 246 kgid_t gid, struct p9_qid *qid); 247 int p9_client_clunk(struct p9_fid *fid); 248 int p9_client_fsync(struct p9_fid *fid, int datasync); 249 int p9_client_remove(struct p9_fid *fid); 250 int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags); 251 int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err); 252 int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err); 253 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset); 254 int p9dirent_read(struct p9_client *clnt, char *buf, int len, 255 struct p9_dirent *dirent); 256 struct p9_wstat *p9_client_stat(struct p9_fid *fid); 257 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); 258 int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr); 259 260 struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, 261 u64 request_mask); 262 263 int p9_client_mknod_dotl(struct p9_fid *oldfid, const char *name, int mode, 264 dev_t rdev, kgid_t gid, struct p9_qid *); 265 int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode, 266 kgid_t gid, struct p9_qid *); 267 int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); 268 int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl); 269 struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); 270 void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status); 271 272 int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int); 273 int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *); 274 void p9stat_free(struct p9_wstat *); 275 276 int p9_is_proto_dotu(struct p9_client *clnt); 277 int p9_is_proto_dotl(struct p9_client *clnt); 278 struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); 279 int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); 280 int p9_client_readlink(struct p9_fid *fid, char **target); 281 282 #endif /* NET_9P_CLIENT_H */ 283