《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
11 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  1. #ifndef __KERN_FS_VFS_INODE_H__
  2. #define __KERN_FS_VFS_INODE_H__
  3. #include <defs.h>
  4. #include <dev.h>
  5. #include <sfs.h>
  6. #include <atomic.h>
  7. #include <assert.h>
  8. struct stat;
  9. struct iobuf;
  10. /*
  11. * A struct inode is an abstract representation of a file.
  12. *
  13. * It is an interface that allows the kernel's filesystem-independent
  14. * code to interact usefully with multiple sets of filesystem code.
  15. */
  16. /*
  17. * Abstract low-level file.
  18. *
  19. * Note: in_info is Filesystem-specific data, in_type is the inode type
  20. *
  21. * open_count is managed using VOP_INCOPEN and VOP_DECOPEN by
  22. * vfs_open() and vfs_close(). Code above the VFS layer should not
  23. * need to worry about it.
  24. */
  25. struct inode {
  26. union {
  27. struct device __device_info;
  28. struct sfs_inode __sfs_inode_info;
  29. } in_info;
  30. enum {
  31. inode_type_device_info = 0x1234,
  32. inode_type_sfs_inode_info,
  33. } in_type;
  34. int ref_count;
  35. int open_count;
  36. struct fs *in_fs;
  37. const struct inode_ops *in_ops;
  38. };
  39. #define __in_type(type) inode_type_##type##_info
  40. #define check_inode_type(node, type) ((node)->in_type == __in_type(type))
  41. #define __vop_info(node, type) \
  42. ({ \
  43. struct inode *__node = (node); \
  44. assert(__node != NULL && check_inode_type(__node, type)); \
  45. &(__node->in_info.__##type##_info); \
  46. })
  47. #define vop_info(node, type) __vop_info(node, type)
  48. #define info2node(info, type) \
  49. to_struct((info), struct inode, in_info.__##type##_info)
  50. struct inode *__alloc_inode(int type);
  51. #define alloc_inode(type) __alloc_inode(__in_type(type))
  52. #define MAX_INODE_COUNT 0x10000
  53. int inode_ref_inc(struct inode *node);
  54. int inode_ref_dec(struct inode *node);
  55. int inode_open_inc(struct inode *node);
  56. int inode_open_dec(struct inode *node);
  57. void inode_init(struct inode *node, const struct inode_ops *ops, struct fs *fs);
  58. void inode_kill(struct inode *node);
  59. #define VOP_MAGIC 0x8c4ba476
  60. /*
  61. * Abstract operations on a inode.
  62. *
  63. * These are used in the form VOP_FOO(inode, args), which are macros
  64. * that expands to inode->inode_ops->vop_foo(inode, args). The operations
  65. * "foo" are:
  66. *
  67. * vop_open - Called on open() of a file. Can be used to
  68. * reject illegal or undesired open modes. Note that
  69. * various operations can be performed without the
  70. * file actually being opened.
  71. * The inode need not look at O_CREAT, O_EXCL, or
  72. * O_TRUNC, as these are handled in the VFS layer.
  73. *
  74. * VOP_EACHOPEN should not be called directly from
  75. * above the VFS layer - use vfs_open() to open inodes.
  76. * This maintains the open count so VOP_LASTCLOSE can
  77. * be called at the right time.
  78. *
  79. * vop_close - To be called on *last* close() of a file.
  80. *
  81. * VOP_LASTCLOSE should not be called directly from
  82. * above the VFS layer - use vfs_close() to close
  83. * inodes opened with vfs_open().
  84. *
  85. * vop_reclaim - Called when inode is no longer in use. Note that
  86. * this may be substantially after vop_lastclose is
  87. * called.
  88. *
  89. *****************************************
  90. *
  91. * vop_read - Read data from file to uio, at offset specified
  92. * in the uio, updating uio_resid to reflect the
  93. * amount read, and updating uio_offset to match.
  94. * Not allowed on directories or symlinks.
  95. *
  96. * vop_getdirentry - Read a single filename from a directory into a
  97. * uio, choosing what name based on the offset
  98. * field in the uio, and updating that field.
  99. * Unlike with I/O on regular files, the value of
  100. * the offset field is not interpreted outside
  101. * the filesystem and thus need not be a byte
  102. * count. However, the uio_resid field should be
  103. * handled in the normal fashion.
  104. * On non-directory objects, return ENOTDIR.
  105. *
  106. * vop_write - Write data from uio to file at offset specified
  107. * in the uio, updating uio_resid to reflect the
  108. * amount written, and updating uio_offset to match.
  109. * Not allowed on directories or symlinks.
  110. *
  111. * vop_ioctl - Perform ioctl operation OP on file using data
  112. * DATA. The interpretation of the data is specific
  113. * to each ioctl.
  114. *
  115. * vop_fstat -Return info about a file. The pointer is a
  116. * pointer to struct stat; see stat.h.
  117. *
  118. * vop_gettype - Return type of file. The values for file types
  119. * are in sfs.h.
  120. *
  121. * vop_tryseek - Check if seeking to the specified position within
  122. * the file is legal. (For instance, all seeks
  123. * are illegal on serial port devices, and seeks
  124. * past EOF on files whose sizes are fixed may be
  125. * as well.)
  126. *
  127. * vop_fsync - Force any dirty buffers associated with this file
  128. * to stable storage.
  129. *
  130. * vop_truncate - Forcibly set size of file to the length passed
  131. * in, discarding any excess blocks.
  132. *
  133. * vop_namefile - Compute pathname relative to filesystem root
  134. * of the file and copy to the specified io buffer.
  135. * Need not work on objects that are not
  136. * directories.
  137. *
  138. *****************************************
  139. *
  140. * vop_creat - Create a regular file named NAME in the passed
  141. * directory DIR. If boolean EXCL is true, fail if
  142. * the file already exists; otherwise, use the
  143. * existing file if there is one. Hand back the
  144. * inode for the file as per vop_lookup.
  145. *
  146. *****************************************
  147. *
  148. * vop_lookup - Parse PATHNAME relative to the passed directory
  149. * DIR, and hand back the inode for the file it
  150. * refers to. May destroy PATHNAME. Should increment
  151. * refcount on inode handed back.
  152. */
  153. struct inode_ops {
  154. unsigned long vop_magic;
  155. int (*vop_open)(struct inode *node, uint32_t open_flags);
  156. int (*vop_close)(struct inode *node);
  157. int (*vop_read)(struct inode *node, struct iobuf *iob);
  158. int (*vop_write)(struct inode *node, struct iobuf *iob);
  159. int (*vop_fstat)(struct inode *node, struct stat *stat);
  160. int (*vop_fsync)(struct inode *node);
  161. int (*vop_namefile)(struct inode *node, struct iobuf *iob);
  162. int (*vop_getdirentry)(struct inode *node, struct iobuf *iob);
  163. int (*vop_reclaim)(struct inode *node);
  164. int (*vop_gettype)(struct inode *node, uint32_t *type_store);
  165. int (*vop_tryseek)(struct inode *node, off_t pos);
  166. int (*vop_truncate)(struct inode *node, off_t len);
  167. int (*vop_create)(struct inode *node, const char *name, bool excl, struct inode **node_store);
  168. int (*vop_lookup)(struct inode *node, char *path, struct inode **node_store);
  169. int (*vop_ioctl)(struct inode *node, int op, void *data);
  170. };
  171. /*
  172. * Consistency check
  173. */
  174. void inode_check(struct inode *node, const char *opstr);
  175. #define __vop_op(node, sym) \
  176. ({ \
  177. struct inode *__node = (node); \
  178. assert(__node != NULL && __node->in_ops != NULL && __node->in_ops->vop_##sym != NULL); \
  179. inode_check(__node, #sym); \
  180. __node->in_ops->vop_##sym; \
  181. })
  182. #define vop_open(node, open_flags) (__vop_op(node, open)(node, open_flags))
  183. #define vop_close(node) (__vop_op(node, close)(node))
  184. #define vop_read(node, iob) (__vop_op(node, read)(node, iob))
  185. #define vop_write(node, iob) (__vop_op(node, write)(node, iob))
  186. #define vop_fstat(node, stat) (__vop_op(node, fstat)(node, stat))
  187. #define vop_fsync(node) (__vop_op(node, fsync)(node))
  188. #define vop_namefile(node, iob) (__vop_op(node, namefile)(node, iob))
  189. #define vop_getdirentry(node, iob) (__vop_op(node, getdirentry)(node, iob))
  190. #define vop_reclaim(node) (__vop_op(node, reclaim)(node))
  191. #define vop_ioctl(node, op, data) (__vop_op(node, ioctl)(node, op, data))
  192. #define vop_gettype(node, type_store) (__vop_op(node, gettype)(node, type_store))
  193. #define vop_tryseek(node, pos) (__vop_op(node, tryseek)(node, pos))
  194. #define vop_truncate(node, len) (__vop_op(node, truncate)(node, len))
  195. #define vop_create(node, name, excl, node_store) (__vop_op(node, create)(node, name, excl, node_store))
  196. #define vop_lookup(node, path, node_store) (__vop_op(node, lookup)(node, path, node_store))
  197. #define vop_fs(node) ((node)->in_fs)
  198. #define vop_init(node, ops, fs) inode_init(node, ops, fs)
  199. #define vop_kill(node) inode_kill(node)
  200. /*
  201. * Reference count manipulation (handled above filesystem level)
  202. */
  203. #define vop_ref_inc(node) inode_ref_inc(node)
  204. #define vop_ref_dec(node) inode_ref_dec(node)
  205. /*
  206. * Open count manipulation (handled above filesystem level)
  207. *
  208. * VOP_INCOPEN is called by vfs_open. VOP_DECOPEN is called by vfs_close.
  209. * Neither of these should need to be called from above the vfs layer.
  210. */
  211. #define vop_open_inc(node) inode_open_inc(node)
  212. #define vop_open_dec(node) inode_open_dec(node)
  213. static inline int
  214. inode_ref_count(struct inode *node) {
  215. return node->ref_count;
  216. }
  217. static inline int
  218. inode_open_count(struct inode *node) {
  219. return node->open_count;
  220. }
  221. #endif /* !__KERN_FS_VFS_INODE_H__ */