Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * 9P Client Definitions
0004  *
0005  *  Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
0006  *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
0007  */
0008 
0009 #ifndef NET_9P_CLIENT_H
0010 #define NET_9P_CLIENT_H
0011 
0012 #include <linux/utsname.h>
0013 #include <linux/idr.h>
0014 #include <linux/tracepoint-defs.h>
0015 
0016 /* Number of requests per row */
0017 #define P9_ROW_MAXTAG 255
0018 
0019 /** enum p9_proto_versions - 9P protocol versions
0020  * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
0021  * @p9_proto_2000u: 9P2000.u extension
0022  * @p9_proto_2000L: 9P2000.L extension
0023  */
0024 
0025 enum p9_proto_versions {
0026     p9_proto_legacy,
0027     p9_proto_2000u,
0028     p9_proto_2000L,
0029 };
0030 
0031 
0032 /**
0033  * enum p9_trans_status - different states of underlying transports
0034  * @Connected: transport is connected and healthy
0035  * @Disconnected: transport has been disconnected
0036  * @Hung: transport is connected by wedged
0037  *
0038  * This enumeration details the various states a transport
0039  * instatiation can be in.
0040  */
0041 
0042 enum p9_trans_status {
0043     Connected,
0044     BeginDisconnect,
0045     Disconnected,
0046     Hung,
0047 };
0048 
0049 /**
0050  * enum p9_req_status_t - status of a request
0051  * @REQ_STATUS_ALLOC: request has been allocated but not sent
0052  * @REQ_STATUS_UNSENT: request waiting to be sent
0053  * @REQ_STATUS_SENT: request sent to server
0054  * @REQ_STATUS_RCVD: response received from server
0055  * @REQ_STATUS_FLSHD: request has been flushed
0056  * @REQ_STATUS_ERROR: request encountered an error on the client side
0057  */
0058 
0059 enum p9_req_status_t {
0060     REQ_STATUS_ALLOC,
0061     REQ_STATUS_UNSENT,
0062     REQ_STATUS_SENT,
0063     REQ_STATUS_RCVD,
0064     REQ_STATUS_FLSHD,
0065     REQ_STATUS_ERROR,
0066 };
0067 
0068 /**
0069  * struct p9_req_t - request slots
0070  * @status: status of this request slot
0071  * @t_err: transport error
0072  * @wq: wait_queue for the client to block on for this request
0073  * @tc: the request fcall structure
0074  * @rc: the response fcall structure
0075  * @req_list: link for higher level objects to chain requests
0076  */
0077 struct p9_req_t {
0078     int status;
0079     int t_err;
0080     refcount_t refcount;
0081     wait_queue_head_t wq;
0082     struct p9_fcall tc;
0083     struct p9_fcall rc;
0084     struct list_head req_list;
0085 };
0086 
0087 /**
0088  * struct p9_client - per client instance state
0089  * @lock: protect @fids and @reqs
0090  * @msize: maximum data size negotiated by protocol
0091  * @proto_version: 9P protocol version to use
0092  * @trans_mod: module API instantiated with this client
0093  * @status: connection state
0094  * @trans: tranport instance state and API
0095  * @fids: All active FID handles
0096  * @reqs: All active requests.
0097  * @name: node name used as client id
0098  *
0099  * The client structure is used to keep track of various per-client
0100  * state that has been instantiated.
0101  */
0102 struct p9_client {
0103     spinlock_t lock;
0104     unsigned int msize;
0105     unsigned char proto_version;
0106     struct p9_trans_module *trans_mod;
0107     enum p9_trans_status status;
0108     void *trans;
0109     struct kmem_cache *fcall_cache;
0110 
0111     union {
0112         struct {
0113             int rfd;
0114             int wfd;
0115         } fd;
0116         struct {
0117             u16 port;
0118             bool privport;
0119 
0120         } tcp;
0121     } trans_opts;
0122 
0123     struct idr fids;
0124     struct idr reqs;
0125 
0126     char name[__NEW_UTS_LEN + 1];
0127 };
0128 
0129 /**
0130  * struct p9_fid - file system entity handle
0131  * @clnt: back pointer to instantiating &p9_client
0132  * @fid: numeric identifier for this handle
0133  * @mode: current mode of this fid (enum?)
0134  * @qid: the &p9_qid server identifier this handle points to
0135  * @iounit: the server reported maximum transaction size for this file
0136  * @uid: the numeric uid of the local user who owns this handle
0137  * @rdir: readdir accounting structure (allocated on demand)
0138  * @dlist: per-dentry fid tracking
0139  *
0140  * TODO: This needs lots of explanation.
0141  */
0142 enum fid_source {
0143     FID_FROM_OTHER,
0144     FID_FROM_INODE,
0145     FID_FROM_DENTRY,
0146 };
0147 
0148 struct p9_fid {
0149     struct p9_client *clnt;
0150     u32 fid;
0151     refcount_t count;
0152     int mode;
0153     struct p9_qid qid;
0154     u32 iounit;
0155     kuid_t uid;
0156 
0157     void *rdir;
0158 
0159     struct hlist_node dlist;    /* list of all fids attached to a dentry */
0160     struct hlist_node ilist;
0161 };
0162 
0163 /**
0164  * struct p9_dirent - directory entry structure
0165  * @qid: The p9 server qid for this dirent
0166  * @d_off: offset to the next dirent
0167  * @d_type: type of file
0168  * @d_name: file name
0169  */
0170 
0171 struct p9_dirent {
0172     struct p9_qid qid;
0173     u64 d_off;
0174     unsigned char d_type;
0175     char d_name[256];
0176 };
0177 
0178 struct iov_iter;
0179 
0180 int p9_show_client_options(struct seq_file *m, struct p9_client *clnt);
0181 int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
0182 int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
0183              const char *name);
0184 int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
0185                struct p9_fid *newdirfid, const char *new_name);
0186 struct p9_client *p9_client_create(const char *dev_name, char *options);
0187 void p9_client_destroy(struct p9_client *clnt);
0188 void p9_client_disconnect(struct p9_client *clnt);
0189 void p9_client_begin_disconnect(struct p9_client *clnt);
0190 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
0191                 const char *uname, kuid_t n_uname, const char *aname);
0192 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
0193         const unsigned char * const *wnames, int clone);
0194 int p9_client_open(struct p9_fid *fid, int mode);
0195 int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
0196                             char *extension);
0197 int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, const char *newname);
0198 int p9_client_symlink(struct p9_fid *fid, const char *name, const char *symname,
0199         kgid_t gid, struct p9_qid *qid);
0200 int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags, u32 mode,
0201         kgid_t gid, struct p9_qid *qid);
0202 int p9_client_clunk(struct p9_fid *fid);
0203 int p9_client_fsync(struct p9_fid *fid, int datasync);
0204 int p9_client_remove(struct p9_fid *fid);
0205 int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
0206 int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err);
0207 int p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
0208         int *err);
0209 int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err);
0210 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
0211 int p9dirent_read(struct p9_client *clnt, char *buf, int len,
0212           struct p9_dirent *dirent);
0213 struct p9_wstat *p9_client_stat(struct p9_fid *fid);
0214 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
0215 int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr);
0216 
0217 struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
0218                             u64 request_mask);
0219 
0220 int p9_client_mknod_dotl(struct p9_fid *oldfid, const char *name, int mode,
0221             dev_t rdev, kgid_t gid, struct p9_qid *qid);
0222 int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
0223                 kgid_t gid, struct p9_qid *qid);
0224 int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
0225 int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
0226 void p9_fcall_fini(struct p9_fcall *fc);
0227 struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag);
0228 
0229 static inline void p9_req_get(struct p9_req_t *r)
0230 {
0231     refcount_inc(&r->refcount);
0232 }
0233 
0234 static inline int p9_req_try_get(struct p9_req_t *r)
0235 {
0236     return refcount_inc_not_zero(&r->refcount);
0237 }
0238 
0239 int p9_req_put(struct p9_client *c, struct p9_req_t *r);
0240 
0241 /* We cannot have the real tracepoints in header files,
0242  * use a wrapper function */
0243 DECLARE_TRACEPOINT(9p_fid_ref);
0244 void do_trace_9p_fid_get(struct p9_fid *fid);
0245 void do_trace_9p_fid_put(struct p9_fid *fid);
0246 
0247 /* fid reference counting helpers:
0248  *  - fids used for any length of time should always be referenced through
0249  *    p9_fid_get(), and released with p9_fid_put()
0250  *  - v9fs_fid_lookup() or similar will automatically call get for you
0251  *    and also require a put
0252  *  - the *_fid_add() helpers will stash the fid in the inode,
0253  *    at which point it is the responsibility of evict_inode()
0254  *    to call the put
0255  *  - the last put will automatically send a clunk to the server
0256  */
0257 static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
0258 {
0259     if (tracepoint_enabled(9p_fid_ref))
0260         do_trace_9p_fid_get(fid);
0261 
0262     refcount_inc(&fid->count);
0263 
0264     return fid;
0265 }
0266 
0267 static inline int p9_fid_put(struct p9_fid *fid)
0268 {
0269     if (!fid || IS_ERR(fid))
0270         return 0;
0271 
0272     if (tracepoint_enabled(9p_fid_ref))
0273         do_trace_9p_fid_put(fid);
0274 
0275     if (!refcount_dec_and_test(&fid->count))
0276         return 0;
0277 
0278     return p9_client_clunk(fid);
0279 }
0280 
0281 void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
0282 
0283 int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
0284             int16_t *tag, int rewind);
0285 int p9stat_read(struct p9_client *clnt, char *buf, int len,
0286         struct p9_wstat *st);
0287 void p9stat_free(struct p9_wstat *stbuf);
0288 
0289 int p9_is_proto_dotu(struct p9_client *clnt);
0290 int p9_is_proto_dotl(struct p9_client *clnt);
0291 struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
0292                    const char *attr_name, u64 *attr_size);
0293 int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
0294               u64 attr_size, int flags);
0295 int p9_client_readlink(struct p9_fid *fid, char **target);
0296 
0297 int p9_client_init(void);
0298 void p9_client_exit(void);
0299 
0300 #endif /* NET_9P_CLIENT_H */