11f327613SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2bd238fb4SLatchesar Ionkov /*
3bd238fb4SLatchesar Ionkov * 9P Client Definitions
4bd238fb4SLatchesar Ionkov *
58a0dc95fSEric Van Hensbergen * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
6bd238fb4SLatchesar Ionkov * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
7bd238fb4SLatchesar Ionkov */
8bd238fb4SLatchesar Ionkov
9bd238fb4SLatchesar Ionkov #ifndef NET_9P_CLIENT_H
10bd238fb4SLatchesar Ionkov #define NET_9P_CLIENT_H
11bd238fb4SLatchesar Ionkov
1250192abeSWill Deacon #include <linux/utsname.h>
13f28cdf04SMatthew Wilcox #include <linux/idr.h>
14286c171bSDominique Martinet #include <linux/tracepoint-defs.h>
1550192abeSWill Deacon
16fea511a6SEric Van Hensbergen /* Number of requests per row */
17fea511a6SEric Van Hensbergen #define P9_ROW_MAXTAG 255
18fea511a6SEric Van Hensbergen
190fb80abdSSripathi Kodi /** enum p9_proto_versions - 9P protocol versions
200fb80abdSSripathi Kodi * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
210fb80abdSSripathi Kodi * @p9_proto_2000u: 9P2000.u extension
2245bc21edSSripathi Kodi * @p9_proto_2000L: 9P2000.L extension
230fb80abdSSripathi Kodi */
240fb80abdSSripathi Kodi
250fb80abdSSripathi Kodi enum p9_proto_versions {
264d63055fSPrem Karat p9_proto_legacy,
274d63055fSPrem Karat p9_proto_2000u,
284d63055fSPrem Karat p9_proto_2000L,
290fb80abdSSripathi Kodi };
300fb80abdSSripathi Kodi
310fb80abdSSripathi Kodi
32ee443996SEric Van Hensbergen /**
338b81ef58SEric Van Hensbergen * enum p9_trans_status - different states of underlying transports
348b81ef58SEric Van Hensbergen * @Connected: transport is connected and healthy
358b81ef58SEric Van Hensbergen * @Disconnected: transport has been disconnected
368b81ef58SEric Van Hensbergen * @Hung: transport is connected by wedged
378b81ef58SEric Van Hensbergen *
388b81ef58SEric Van Hensbergen * This enumeration details the various states a transport
398b81ef58SEric Van Hensbergen * instatiation can be in.
408b81ef58SEric Van Hensbergen */
418b81ef58SEric Van Hensbergen
428b81ef58SEric Van Hensbergen enum p9_trans_status {
438b81ef58SEric Van Hensbergen Connected,
446d96d3abSAneesh Kumar K.V BeginDisconnect,
458b81ef58SEric Van Hensbergen Disconnected,
468b81ef58SEric Van Hensbergen Hung,
478b81ef58SEric Van Hensbergen };
488b81ef58SEric Van Hensbergen
498b81ef58SEric Van Hensbergen /**
50aca00763SRob Landley * enum p9_req_status_t - status of a request
51fea511a6SEric Van Hensbergen * @REQ_STATUS_ALLOC: request has been allocated but not sent
52673d62cdSEric Van Hensbergen * @REQ_STATUS_UNSENT: request waiting to be sent
53fea511a6SEric Van Hensbergen * @REQ_STATUS_SENT: request sent to server
54fea511a6SEric Van Hensbergen * @REQ_STATUS_RCVD: response received from server
55fea511a6SEric Van Hensbergen * @REQ_STATUS_FLSHD: request has been flushed
56673d62cdSEric Van Hensbergen * @REQ_STATUS_ERROR: request encountered an error on the client side
57fea511a6SEric Van Hensbergen */
58fea511a6SEric Van Hensbergen
59fea511a6SEric Van Hensbergen enum p9_req_status_t {
60fea511a6SEric Van Hensbergen REQ_STATUS_ALLOC,
61673d62cdSEric Van Hensbergen REQ_STATUS_UNSENT,
62fea511a6SEric Van Hensbergen REQ_STATUS_SENT,
63fea511a6SEric Van Hensbergen REQ_STATUS_RCVD,
64fea511a6SEric Van Hensbergen REQ_STATUS_FLSHD,
65fea511a6SEric Van Hensbergen REQ_STATUS_ERROR,
66fea511a6SEric Van Hensbergen };
67fea511a6SEric Van Hensbergen
68fea511a6SEric Van Hensbergen /**
69fea511a6SEric Van Hensbergen * struct p9_req_t - request slots
70fea511a6SEric Van Hensbergen * @status: status of this request slot
71fea511a6SEric Van Hensbergen * @t_err: transport error
72fea511a6SEric Van Hensbergen * @wq: wait_queue for the client to block on for this request
73fea511a6SEric Van Hensbergen * @tc: the request fcall structure
74fea511a6SEric Van Hensbergen * @rc: the response fcall structure
75673d62cdSEric Van Hensbergen * @req_list: link for higher level objects to chain requests
76fea511a6SEric Van Hensbergen */
77fea511a6SEric Van Hensbergen struct p9_req_t {
78fea511a6SEric Van Hensbergen int status;
79fea511a6SEric Van Hensbergen int t_err;
806cda1286SKent Overstreet refcount_t refcount;
812557d0c5SMatthew Wilcox wait_queue_head_t wq;
82523adb6cSDominique Martinet struct p9_fcall tc;
83523adb6cSDominique Martinet struct p9_fcall rc;
84673d62cdSEric Van Hensbergen struct list_head req_list;
85fea511a6SEric Van Hensbergen };
86fea511a6SEric Van Hensbergen
87fea511a6SEric Van Hensbergen /**
88ee443996SEric Van Hensbergen * struct p9_client - per client instance state
89996d5b4dSMatthew Wilcox * @lock: protect @fids and @reqs
90ee443996SEric Van Hensbergen * @msize: maximum data size negotiated by protocol
910fb80abdSSripathi Kodi * @proto_version: 9P protocol version to use
92ee443996SEric Van Hensbergen * @trans_mod: module API instantiated with this client
93996d5b4dSMatthew Wilcox * @status: connection state
94ee443996SEric Van Hensbergen * @trans: tranport instance state and API
95f28cdf04SMatthew Wilcox * @fids: All active FID handles
96996d5b4dSMatthew Wilcox * @reqs: All active requests.
97996d5b4dSMatthew Wilcox * @name: node name used as client id
98ee443996SEric Van Hensbergen *
99ee443996SEric Van Hensbergen * The client structure is used to keep track of various per-client
100ee443996SEric Van Hensbergen * state that has been instantiated.
101ee443996SEric Van Hensbergen */
102bd238fb4SLatchesar Ionkov struct p9_client {
103996d5b4dSMatthew Wilcox spinlock_t lock;
104ef6b0807SDan Carpenter unsigned int msize;
1050fb80abdSSripathi Kodi unsigned char proto_version;
1068a0dc95fSEric Van Hensbergen struct p9_trans_module *trans_mod;
1078b81ef58SEric Van Hensbergen enum p9_trans_status status;
1088b81ef58SEric Van Hensbergen void *trans;
10991a76be3SDominique Martinet struct kmem_cache *fcall_cache;
110bd238fb4SLatchesar Ionkov
111c4fac910SDavid Howells union {
112c4fac910SDavid Howells struct {
113c4fac910SDavid Howells int rfd;
114c4fac910SDavid Howells int wfd;
115c4fac910SDavid Howells } fd;
116c4fac910SDavid Howells struct {
117c4fac910SDavid Howells u16 port;
118c4fac910SDavid Howells bool privport;
119c4fac910SDavid Howells
120c4fac910SDavid Howells } tcp;
121c4fac910SDavid Howells } trans_opts;
122c4fac910SDavid Howells
123f28cdf04SMatthew Wilcox struct idr fids;
124996d5b4dSMatthew Wilcox struct idr reqs;
12550192abeSWill Deacon
12650192abeSWill Deacon char name[__NEW_UTS_LEN + 1];
127bd238fb4SLatchesar Ionkov };
128bd238fb4SLatchesar Ionkov
129ee443996SEric Van Hensbergen /**
130ee443996SEric Van Hensbergen * struct p9_fid - file system entity handle
131ee443996SEric Van Hensbergen * @clnt: back pointer to instantiating &p9_client
132ee443996SEric Van Hensbergen * @fid: numeric identifier for this handle
133ee443996SEric Van Hensbergen * @mode: current mode of this fid (enum?)
134ee443996SEric Van Hensbergen * @qid: the &p9_qid server identifier this handle points to
135ee443996SEric Van Hensbergen * @iounit: the server reported maximum transaction size for this file
136ee443996SEric Van Hensbergen * @uid: the numeric uid of the local user who owns this handle
1373e2796a9SEric Van Hensbergen * @rdir: readdir accounting structure (allocated on demand)
138ee443996SEric Van Hensbergen * @dlist: per-dentry fid tracking
139ee443996SEric Van Hensbergen *
140ee443996SEric Van Hensbergen * TODO: This needs lots of explanation.
141ee443996SEric Van Hensbergen */
1426636b6dcSJianyong Wu enum fid_source {
1436636b6dcSJianyong Wu FID_FROM_OTHER,
1446636b6dcSJianyong Wu FID_FROM_INODE,
1456636b6dcSJianyong Wu FID_FROM_DENTRY,
1466636b6dcSJianyong Wu };
147ee443996SEric Van Hensbergen
148bd238fb4SLatchesar Ionkov struct p9_fid {
149bd238fb4SLatchesar Ionkov struct p9_client *clnt;
150bd238fb4SLatchesar Ionkov u32 fid;
151ff5e72ebSDominique Martinet refcount_t count;
152bd238fb4SLatchesar Ionkov int mode;
153bd238fb4SLatchesar Ionkov struct p9_qid qid;
154bd238fb4SLatchesar Ionkov u32 iounit;
155b4642556SEric W. Biederman kuid_t uid;
156bd238fb4SLatchesar Ionkov
1573e2796a9SEric Van Hensbergen void *rdir;
1583e2796a9SEric Van Hensbergen
159c4d30967SAl Viro struct hlist_node dlist; /* list of all fids attached to a dentry */
160987a6485SGreg Kurz struct hlist_node ilist;
161bd238fb4SLatchesar Ionkov };
162bd238fb4SLatchesar Ionkov
1637751bdb3SSripathi Kodi /**
1647751bdb3SSripathi Kodi * struct p9_dirent - directory entry structure
1657751bdb3SSripathi Kodi * @qid: The p9 server qid for this dirent
1667751bdb3SSripathi Kodi * @d_off: offset to the next dirent
1677751bdb3SSripathi Kodi * @d_type: type of file
1687751bdb3SSripathi Kodi * @d_name: file name
1697751bdb3SSripathi Kodi */
1707751bdb3SSripathi Kodi
1717751bdb3SSripathi Kodi struct p9_dirent {
1727751bdb3SSripathi Kodi struct p9_qid qid;
1737751bdb3SSripathi Kodi u64 d_off;
1747751bdb3SSripathi Kodi unsigned char d_type;
1757751bdb3SSripathi Kodi char d_name[256];
1767751bdb3SSripathi Kodi };
1777751bdb3SSripathi Kodi
178070b3656SAl Viro struct iov_iter;
179070b3656SAl Viro
180c4fac910SDavid Howells int p9_show_client_options(struct seq_file *m, struct p9_client *clnt);
181bda8e775SSripathi Kodi int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
1829e8fb38eSAneesh Kumar K.V int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
1839e8fb38eSAneesh Kumar K.V const char *name);
1849e8fb38eSAneesh Kumar K.V int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
1859e8fb38eSAneesh Kumar K.V struct p9_fid *newdirfid, const char *new_name);
1868a0dc95fSEric Van Hensbergen struct p9_client *p9_client_create(const char *dev_name, char *options);
187bd238fb4SLatchesar Ionkov void p9_client_destroy(struct p9_client *clnt);
188bd238fb4SLatchesar Ionkov void p9_client_disconnect(struct p9_client *clnt);
1896d96d3abSAneesh Kumar K.V void p9_client_begin_disconnect(struct p9_client *clnt);
190bd238fb4SLatchesar Ionkov struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
1917880b43bSAl Viro const char *uname, kuid_t n_uname, const char *aname);
192b76225e2SHarsh Prateek Bora struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
1937880b43bSAl Viro const unsigned char * const *wnames, int clone);
194bd238fb4SLatchesar Ionkov int p9_client_open(struct p9_fid *fid, int mode);
1957880b43bSAl Viro int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
196bd238fb4SLatchesar Ionkov char *extension);
1977880b43bSAl Viro int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, const char *newname);
1987880b43bSAl Viro int p9_client_symlink(struct p9_fid *fid, const char *name, const char *symname,
1997880b43bSAl Viro kgid_t gid, struct p9_qid *qid);
2007880b43bSAl Viro int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 mode,
201f791f7c5SEric W. Biederman kgid_t gid, struct p9_qid *qid);
202bd238fb4SLatchesar Ionkov int p9_client_clunk(struct p9_fid *fid);
203b165d601SVenkateswararao Jujjuri (JV) int p9_client_fsync(struct p9_fid *fid, int datasync);
204bd238fb4SLatchesar Ionkov int p9_client_remove(struct p9_fid *fid);
20548e370ffSAneesh Kumar K.V int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
206e1200fe6SAl Viro int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err);
207388f6966SSergey Alirzaev int p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
208388f6966SSergey Alirzaev int *err);
209070b3656SAl Viro int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err);
2107751bdb3SSripathi Kodi int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
211348b5901SAneesh Kumar K.V int p9dirent_read(struct p9_client *clnt, char *buf, int len,
212348b5901SAneesh Kumar K.V struct p9_dirent *dirent);
21351a87c55SEric Van Hensbergen struct p9_wstat *p9_client_stat(struct p9_fid *fid);
214bd238fb4SLatchesar Ionkov int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
21587d7845aSSripathi Kodi int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr);
216bd238fb4SLatchesar Ionkov
217f0853122SSripathi Kodi struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
218f0853122SSripathi Kodi u64 request_mask);
219f0853122SSripathi Kodi
2207880b43bSAl Viro int p9_client_mknod_dotl(struct p9_fid *oldfid, const char *name, int mode,
2216e195b0fSDominique Martinet dev_t rdev, kgid_t gid, struct p9_qid *qid);
2227880b43bSAl Viro int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
2236e195b0fSDominique Martinet kgid_t gid, struct p9_qid *qid);
224a099027cSM. Mohan Kumar int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
2251d769cd1SM. Mohan Kumar int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
226523adb6cSDominique Martinet void p9_fcall_fini(struct p9_fcall *fc);
2276e195b0fSDominique Martinet struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag);
228728356deSTomas Bortoli
p9_req_get(struct p9_req_t * r)229728356deSTomas Bortoli static inline void p9_req_get(struct p9_req_t *r)
230728356deSTomas Bortoli {
2316cda1286SKent Overstreet refcount_inc(&r->refcount);
232728356deSTomas Bortoli }
233728356deSTomas Bortoli
p9_req_try_get(struct p9_req_t * r)234728356deSTomas Bortoli static inline int p9_req_try_get(struct p9_req_t *r)
235728356deSTomas Bortoli {
2366cda1286SKent Overstreet return refcount_inc_not_zero(&r->refcount);
237728356deSTomas Bortoli }
238728356deSTomas Bortoli
239*8b11ff09SKent Overstreet int p9_req_put(struct p9_client *c, struct p9_req_t *r);
240728356deSTomas Bortoli
241286c171bSDominique Martinet /* We cannot have the real tracepoints in header files,
242286c171bSDominique Martinet * use a wrapper function */
243286c171bSDominique Martinet DECLARE_TRACEPOINT(9p_fid_ref);
244286c171bSDominique Martinet void do_trace_9p_fid_get(struct p9_fid *fid);
245286c171bSDominique Martinet void do_trace_9p_fid_put(struct p9_fid *fid);
246286c171bSDominique Martinet
247b48dbb99SDominique Martinet /* fid reference counting helpers:
248b48dbb99SDominique Martinet * - fids used for any length of time should always be referenced through
249b48dbb99SDominique Martinet * p9_fid_get(), and released with p9_fid_put()
250b48dbb99SDominique Martinet * - v9fs_fid_lookup() or similar will automatically call get for you
251b48dbb99SDominique Martinet * and also require a put
252b48dbb99SDominique Martinet * - the *_fid_add() helpers will stash the fid in the inode,
253b48dbb99SDominique Martinet * at which point it is the responsibility of evict_inode()
254b48dbb99SDominique Martinet * to call the put
255b48dbb99SDominique Martinet * - the last put will automatically send a clunk to the server
256b48dbb99SDominique Martinet */
p9_fid_get(struct p9_fid * fid)257b48dbb99SDominique Martinet static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
258b48dbb99SDominique Martinet {
259286c171bSDominique Martinet if (tracepoint_enabled(9p_fid_ref))
260286c171bSDominique Martinet do_trace_9p_fid_get(fid);
261286c171bSDominique Martinet
262b48dbb99SDominique Martinet refcount_inc(&fid->count);
263b48dbb99SDominique Martinet
264b48dbb99SDominique Martinet return fid;
265b48dbb99SDominique Martinet }
266b48dbb99SDominique Martinet
p9_fid_put(struct p9_fid * fid)267b48dbb99SDominique Martinet static inline int p9_fid_put(struct p9_fid *fid)
268b48dbb99SDominique Martinet {
269b48dbb99SDominique Martinet if (!fid || IS_ERR(fid))
270b48dbb99SDominique Martinet return 0;
271b48dbb99SDominique Martinet
272286c171bSDominique Martinet if (tracepoint_enabled(9p_fid_ref))
273286c171bSDominique Martinet do_trace_9p_fid_put(fid);
274286c171bSDominique Martinet
275b48dbb99SDominique Martinet if (!refcount_dec_and_test(&fid->count))
276b48dbb99SDominique Martinet return 0;
277b48dbb99SDominique Martinet
278b48dbb99SDominique Martinet return p9_client_clunk(fid);
279b48dbb99SDominique Martinet }
280b48dbb99SDominique Martinet
2812b6e72edSDominique Martinet void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
282fea511a6SEric Van Hensbergen
2836e195b0fSDominique Martinet int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
2846e195b0fSDominique Martinet int16_t *tag, int rewind);
2856e195b0fSDominique Martinet int p9stat_read(struct p9_client *clnt, char *buf, int len,
2866e195b0fSDominique Martinet struct p9_wstat *st);
2876e195b0fSDominique Martinet void p9stat_free(struct p9_wstat *stbuf);
28851a87c55SEric Van Hensbergen
289342fee1dSSripathi Kodi int p9_is_proto_dotu(struct p9_client *clnt);
290342fee1dSSripathi Kodi int p9_is_proto_dotl(struct p9_client *clnt);
2916e195b0fSDominique Martinet struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
2926e195b0fSDominique Martinet const char *attr_name, u64 *attr_size);
2936e195b0fSDominique Martinet int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
2946e195b0fSDominique Martinet u64 attr_size, int flags);
295329176ccSM. Mohan Kumar int p9_client_readlink(struct p9_fid *fid, char **target);
29602da398bSEric Van Hensbergen
297996d5b4dSMatthew Wilcox int p9_client_init(void);
298996d5b4dSMatthew Wilcox void p9_client_exit(void);
299996d5b4dSMatthew Wilcox
300bd238fb4SLatchesar Ionkov #endif /* NET_9P_CLIENT_H */
301