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