xref: /openbmc/linux/include/net/9p/client.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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