1*e97ad33aSDoug Rabson /*- 2*e97ad33aSDoug Rabson * Copyright (c) 2017-2020 Juniper Networks, Inc. 3*e97ad33aSDoug Rabson * All rights reserved. 4*e97ad33aSDoug Rabson * 5*e97ad33aSDoug Rabson * Redistribution and use in source and binary forms, with or without 6*e97ad33aSDoug Rabson * modification, are permitted provided that the following conditions 7*e97ad33aSDoug Rabson * are met: 8*e97ad33aSDoug Rabson * 1. Redistributions of source code must retain the above copyright 9*e97ad33aSDoug Rabson * notice, this list of conditions and the following disclaimer. 10*e97ad33aSDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 11*e97ad33aSDoug Rabson * notice, this list of conditions and the following disclaimer in the 12*e97ad33aSDoug Rabson * documentation and/or other materials provided with the distribution. 13*e97ad33aSDoug Rabson * 14*e97ad33aSDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*e97ad33aSDoug Rabson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*e97ad33aSDoug Rabson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*e97ad33aSDoug Rabson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18*e97ad33aSDoug Rabson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19*e97ad33aSDoug Rabson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*e97ad33aSDoug Rabson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*e97ad33aSDoug Rabson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*e97ad33aSDoug Rabson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23*e97ad33aSDoug Rabson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*e97ad33aSDoug Rabson * 25*e97ad33aSDoug Rabson */ 26*e97ad33aSDoug Rabson 27*e97ad33aSDoug Rabson /* This file has prototypes specific to the p9fs file system */ 28*e97ad33aSDoug Rabson 29*e97ad33aSDoug Rabson #ifndef FS_P9FS_P9FS_H 30*e97ad33aSDoug Rabson #define FS_P9FS_P9FS_H 31*e97ad33aSDoug Rabson 32*e97ad33aSDoug Rabson struct p9fs_session; 33*e97ad33aSDoug Rabson 34*e97ad33aSDoug Rabson /* QID: Unique identification for the file being accessed */ 35*e97ad33aSDoug Rabson struct p9fs_qid { 36*e97ad33aSDoug Rabson uint8_t qid_mode; /* file mode specifiying file type */ 37*e97ad33aSDoug Rabson uint32_t qid_version; /* version of the file */ 38*e97ad33aSDoug Rabson uint64_t qid_path; /* unique integer among all files in hierarchy */ 39*e97ad33aSDoug Rabson }; 40*e97ad33aSDoug Rabson 41*e97ad33aSDoug Rabson /* 42*e97ad33aSDoug Rabson * The in memory representation of the on disk inode. Save the current 43*e97ad33aSDoug Rabson * fields to write it back later. 44*e97ad33aSDoug Rabson */ 45*e97ad33aSDoug Rabson struct p9fs_inode { 46*e97ad33aSDoug Rabson /* Make it simple first, Add more fields later */ 47*e97ad33aSDoug Rabson uint64_t i_size; /* size of the inode */ 48*e97ad33aSDoug Rabson uint16_t i_type; /* type of inode */ 49*e97ad33aSDoug Rabson uint32_t i_dev; /* type of device */ 50*e97ad33aSDoug Rabson uint32_t i_mode; /* mode of the inode */ 51*e97ad33aSDoug Rabson uint32_t i_atime; /* time of last access */ 52*e97ad33aSDoug Rabson uint32_t i_mtime; /* time of last modification */ 53*e97ad33aSDoug Rabson uint32_t i_ctime; /* time of last status change */ 54*e97ad33aSDoug Rabson uint32_t i_atime_nsec; /* times of last access in nanoseconds resolution */ 55*e97ad33aSDoug Rabson uint32_t i_mtime_nsec; /* time of last modification in nanoseconds resolution */ 56*e97ad33aSDoug Rabson uint32_t i_ctime_nsec; /* time of last status change in nanoseconds resolution */ 57*e97ad33aSDoug Rabson uint64_t i_length; 58*e97ad33aSDoug Rabson char *i_name; /* inode name */ 59*e97ad33aSDoug Rabson char *i_uid; /* inode user id */ 60*e97ad33aSDoug Rabson char *i_gid; /* inode group id */ 61*e97ad33aSDoug Rabson char *i_muid; 62*e97ad33aSDoug Rabson char *i_extension; /* 9p2000.u extensions */ 63*e97ad33aSDoug Rabson uid_t n_uid; /* 9p2000.u extensions */ 64*e97ad33aSDoug Rabson gid_t n_gid; /* 9p2000.u extensions */ 65*e97ad33aSDoug Rabson uid_t n_muid; /* 9p2000.u extensions */ 66*e97ad33aSDoug Rabson /* bookkeeping info on the client. */ 67*e97ad33aSDoug Rabson uint16_t i_links_count; /*number of references to the inode*/ 68*e97ad33aSDoug Rabson uint64_t i_qid_path; /* using inode number for reference. */ 69*e97ad33aSDoug Rabson uint64_t i_flags; 70*e97ad33aSDoug Rabson uint64_t blksize; /* block size for file system */ 71*e97ad33aSDoug Rabson uint64_t blocks; /* number of 512B blocks allocated */ 72*e97ad33aSDoug Rabson uint64_t gen; /* reserved for future use */ 73*e97ad33aSDoug Rabson uint64_t data_version; /* reserved for future use */ 74*e97ad33aSDoug Rabson 75*e97ad33aSDoug Rabson }; 76*e97ad33aSDoug Rabson 77*e97ad33aSDoug Rabson #define P9FS_VFID_MTX(_sc) (&(_sc)->vfid_mtx) 78*e97ad33aSDoug Rabson #define P9FS_VFID_LOCK(_sc) mtx_lock(P9FS_VFID_MTX(_sc)) 79*e97ad33aSDoug Rabson #define P9FS_VFID_UNLOCK(_sc) mtx_unlock(P9FS_VFID_MTX(_sc)) 80*e97ad33aSDoug Rabson #define P9FS_VFID_LOCK_INIT(_sc) mtx_init(P9FS_VFID_MTX(_sc), \ 81*e97ad33aSDoug Rabson "VFID List lock", NULL, MTX_DEF) 82*e97ad33aSDoug Rabson #define P9FS_VFID_LOCK_DESTROY(_sc) mtx_destroy(P9FS_VFID_MTX(_sc)) 83*e97ad33aSDoug Rabson 84*e97ad33aSDoug Rabson #define P9FS_VOFID_MTX(_sc) (&(_sc)->vofid_mtx) 85*e97ad33aSDoug Rabson #define P9FS_VOFID_LOCK(_sc) mtx_lock(P9FS_VOFID_MTX(_sc)) 86*e97ad33aSDoug Rabson #define P9FS_VOFID_UNLOCK(_sc) mtx_unlock(P9FS_VOFID_MTX(_sc)) 87*e97ad33aSDoug Rabson #define P9FS_VOFID_LOCK_INIT(_sc) mtx_init(P9FS_VOFID_MTX(_sc), \ 88*e97ad33aSDoug Rabson "VOFID List lock", NULL, MTX_DEF) 89*e97ad33aSDoug Rabson #define P9FS_VOFID_LOCK_DESTROY(_sc) mtx_destroy(P9FS_VOFID_MTX(_sc)) 90*e97ad33aSDoug Rabson 91*e97ad33aSDoug Rabson #define VFID 0x01 92*e97ad33aSDoug Rabson #define VOFID 0x02 93*e97ad33aSDoug Rabson 94*e97ad33aSDoug Rabson /* A Plan9 node. */ 95*e97ad33aSDoug Rabson struct p9fs_node { 96*e97ad33aSDoug Rabson STAILQ_HEAD( ,p9_fid) vfid_list; /* vfid related to uid */ 97*e97ad33aSDoug Rabson struct mtx vfid_mtx; /* mutex for vfid list */ 98*e97ad33aSDoug Rabson STAILQ_HEAD( ,p9_fid) vofid_list; /* vofid related to uid */ 99*e97ad33aSDoug Rabson struct mtx vofid_mtx; /* mutex for vofid list */ 100*e97ad33aSDoug Rabson struct p9fs_node *parent; /* pointer to parent p9fs node */ 101*e97ad33aSDoug Rabson struct p9fs_qid vqid; /* the server qid, will be from the host */ 102*e97ad33aSDoug Rabson struct vnode *v_node; /* vnode for this fs_node. */ 103*e97ad33aSDoug Rabson struct p9fs_inode inode; /* in memory representation of ondisk information*/ 104*e97ad33aSDoug Rabson struct p9fs_session *p9fs_ses; /* Session_ptr for this node */ 105*e97ad33aSDoug Rabson STAILQ_ENTRY(p9fs_node) p9fs_node_next; 106*e97ad33aSDoug Rabson uint64_t flags; 107*e97ad33aSDoug Rabson }; 108*e97ad33aSDoug Rabson 109*e97ad33aSDoug Rabson #define P9FS_VTON(vp) ((struct p9fs_node *)(vp)->v_data) 110*e97ad33aSDoug Rabson #define P9FS_NTOV(node) ((node)->v_node) 111*e97ad33aSDoug Rabson #define VFSTOP9(mp) ((struct p9fs_mount *)(mp)->mnt_data) 112*e97ad33aSDoug Rabson #define QEMU_DIRENTRY_SZ 25 113*e97ad33aSDoug Rabson #define P9FS_NODE_MODIFIED 0x1 /* indicating file change */ 114*e97ad33aSDoug Rabson #define P9FS_ROOT 0x2 /* indicating root p9fs node */ 115*e97ad33aSDoug Rabson #define P9FS_NODE_DELETED 0x4 /* indicating file or directory delete */ 116*e97ad33aSDoug Rabson #define P9FS_NODE_IN_SESSION 0x8 /* p9fs_node is in the session - virt_node_list */ 117*e97ad33aSDoug Rabson #define IS_ROOT(node) (node->flags & P9FS_ROOT) 118*e97ad33aSDoug Rabson 119*e97ad33aSDoug Rabson #define P9FS_SET_LINKS(inode) do { \ 120*e97ad33aSDoug Rabson (inode)->i_links_count = 1; \ 121*e97ad33aSDoug Rabson } while (0) \ 122*e97ad33aSDoug Rabson 123*e97ad33aSDoug Rabson #define P9FS_INCR_LINKS(inode) do { \ 124*e97ad33aSDoug Rabson (inode)->i_links_count++; \ 125*e97ad33aSDoug Rabson } while (0) \ 126*e97ad33aSDoug Rabson 127*e97ad33aSDoug Rabson #define P9FS_DECR_LINKS(inode) do { \ 128*e97ad33aSDoug Rabson (inode)->i_links_count--; \ 129*e97ad33aSDoug Rabson } while (0) \ 130*e97ad33aSDoug Rabson 131*e97ad33aSDoug Rabson #define P9FS_CLR_LINKS(inode) do { \ 132*e97ad33aSDoug Rabson (inode)->i_links_count = 0; \ 133*e97ad33aSDoug Rabson } while (0) \ 134*e97ad33aSDoug Rabson 135*e97ad33aSDoug Rabson #define P9FS_MTX(_sc) (&(_sc)->p9fs_mtx) 136*e97ad33aSDoug Rabson #define P9FS_LOCK(_sc) mtx_lock(P9FS_MTX(_sc)) 137*e97ad33aSDoug Rabson #define P9FS_UNLOCK(_sc) mtx_unlock(P9FS_MTX(_sc)) 138*e97ad33aSDoug Rabson #define P9FS_LOCK_INIT(_sc) mtx_init(P9FS_MTX(_sc), \ 139*e97ad33aSDoug Rabson "P9FS session chain lock", NULL, MTX_DEF) 140*e97ad33aSDoug Rabson #define P9FS_LOCK_DESTROY(_sc) mtx_destroy(P9FS_MTX(_sc)) 141*e97ad33aSDoug Rabson 142*e97ad33aSDoug Rabson /* Session structure for the FS */ 143*e97ad33aSDoug Rabson struct p9fs_session { 144*e97ad33aSDoug Rabson unsigned char flags; /* these flags for the session */ 145*e97ad33aSDoug Rabson struct mount *p9fs_mount; /* mount point */ 146*e97ad33aSDoug Rabson struct p9fs_node rnp; /* root p9fs node for this session */ 147*e97ad33aSDoug Rabson uid_t uid; /* the uid that has access */ 148*e97ad33aSDoug Rabson const char *uname; /* user name to mount as */ 149*e97ad33aSDoug Rabson const char *aname; /* name of remote file tree being mounted */ 150*e97ad33aSDoug Rabson struct p9_client *clnt; /* 9p client */ 151*e97ad33aSDoug Rabson struct mtx p9fs_mtx; /* mutex used for guarding the chain.*/ 152*e97ad33aSDoug Rabson STAILQ_HEAD( ,p9fs_node) virt_node_list; /* list of p9fs nodes in this session*/ 153*e97ad33aSDoug Rabson struct p9_fid *mnt_fid; /* to save nobody 's fid for unmounting as root user */ 154*e97ad33aSDoug Rabson }; 155*e97ad33aSDoug Rabson 156*e97ad33aSDoug Rabson struct p9fs_mount { 157*e97ad33aSDoug Rabson struct p9fs_session p9fs_session; /* per instance session information */ 158*e97ad33aSDoug Rabson struct mount *p9fs_mountp; /* mount point */ 159*e97ad33aSDoug Rabson int mount_tag_len; /* length of the mount tag */ 160*e97ad33aSDoug Rabson char *mount_tag; /* mount tag used */ 161*e97ad33aSDoug Rabson }; 162*e97ad33aSDoug Rabson 163*e97ad33aSDoug Rabson /* All session flags based on 9p versions */ 164*e97ad33aSDoug Rabson enum virt_session_flags { 165*e97ad33aSDoug Rabson P9FS_PROTO_2000U = 0x01, 166*e97ad33aSDoug Rabson P9FS_PROTO_2000L = 0x02, 167*e97ad33aSDoug Rabson }; 168*e97ad33aSDoug Rabson 169*e97ad33aSDoug Rabson /* Session access flags */ 170*e97ad33aSDoug Rabson #define P9_ACCESS_ANY 0x04 /* single attach for all users */ 171*e97ad33aSDoug Rabson #define P9_ACCESS_SINGLE 0x08 /* access to only the user who mounts */ 172*e97ad33aSDoug Rabson #define P9_ACCESS_USER 0x10 /* new attach established for every user */ 173*e97ad33aSDoug Rabson #define P9_ACCESS_MASK (P9_ACCESS_ANY|P9_ACCESS_SINGLE|P9_ACCESS_USER) 174*e97ad33aSDoug Rabson 175*e97ad33aSDoug Rabson u_quad_t p9fs_round_filesize_to_bytes(uint64_t filesize, uint64_t bsize); 176*e97ad33aSDoug Rabson u_quad_t p9fs_pow2_filesize_to_bytes(uint64_t filesize, uint64_t bsize); 177*e97ad33aSDoug Rabson 178*e97ad33aSDoug Rabson /* These are all the P9FS specific vops */ 179*e97ad33aSDoug Rabson int p9fs_stat_vnode_l(void); 180*e97ad33aSDoug Rabson int p9fs_stat_vnode_dotl(struct p9_stat_dotl *st, struct vnode *vp); 181*e97ad33aSDoug Rabson int p9fs_reload_stats_dotl(struct vnode *vp, struct ucred *cred); 182*e97ad33aSDoug Rabson int p9fs_proto_dotl(struct p9fs_session *vses); 183*e97ad33aSDoug Rabson struct p9_fid *p9fs_init_session(struct mount *mp, int *error); 184*e97ad33aSDoug Rabson void p9fs_close_session(struct mount *mp); 185*e97ad33aSDoug Rabson void p9fs_prepare_to_close(struct mount *mp); 186*e97ad33aSDoug Rabson void p9fs_complete_close(struct mount *mp); 187*e97ad33aSDoug Rabson int p9fs_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp); 188*e97ad33aSDoug Rabson int p9fs_vget_common(struct mount *mp, struct p9fs_node *np, int flags, 189*e97ad33aSDoug Rabson struct p9fs_node *parent, struct p9_fid *fid, struct vnode **vpp, 190*e97ad33aSDoug Rabson char *name); 191*e97ad33aSDoug Rabson int p9fs_node_cmp(struct vnode *vp, void *arg); 192*e97ad33aSDoug Rabson void p9fs_destroy_node(struct p9fs_node **npp); 193*e97ad33aSDoug Rabson void p9fs_dispose_node(struct p9fs_node **npp); 194*e97ad33aSDoug Rabson void p9fs_cleanup(struct p9fs_node *vp); 195*e97ad33aSDoug Rabson void p9fs_fid_remove_all(struct p9fs_node *np, int leave_ofids); 196*e97ad33aSDoug Rabson void p9fs_fid_remove(struct p9fs_node *np, struct p9_fid *vfid, 197*e97ad33aSDoug Rabson int fid_type); 198*e97ad33aSDoug Rabson void p9fs_fid_add(struct p9fs_node *np, struct p9_fid *fid, 199*e97ad33aSDoug Rabson int fid_type); 200*e97ad33aSDoug Rabson struct p9_fid *p9fs_get_fid(struct p9_client *clnt, 201*e97ad33aSDoug Rabson struct p9fs_node *np, struct ucred *cred, int fid_type, int mode, int *error); 202*e97ad33aSDoug Rabson 203*e97ad33aSDoug Rabson #endif /* FS_P9FS_P9FS_H */ 204