sfs_fs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*
  2. * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
  3. * The President and Fellows of Harvard College.
  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. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * SFS filesystem
  31. *
  32. * Filesystem-level interface routines.
  33. */
  34. #include <types.h>
  35. #include <kern/errno.h>
  36. #include <lib.h>
  37. #include <array.h>
  38. #include <bitmap.h>
  39. #include <uio.h>
  40. #include <vfs.h>
  41. #include <device.h>
  42. #include <sfs.h>
  43. /* Shortcuts for the size macros in kern/sfs.h */
  44. #define SFS_FS_BITMAPSIZE(sfs) SFS_BITMAPSIZE((sfs)->sfs_super.sp_nblocks)
  45. #define SFS_FS_BITBLOCKS(sfs) SFS_BITBLOCKS((sfs)->sfs_super.sp_nblocks)
  46. /*
  47. * Routine for doing I/O (reads or writes) on the free block bitmap.
  48. * We always do the whole bitmap at once; writing individual sectors
  49. * might or might not be a worthwhile optimization.
  50. *
  51. * The free block bitmap consists of SFS_BITBLOCKS 512-byte sectors of
  52. * bits, one bit for each sector on the filesystem. The number of
  53. * blocks in the bitmap is thus rounded up to the nearest multiple of
  54. * 512*8 = 4096. (This rounded number is SFS_BITMAPSIZE.) This means
  55. * that the bitmap will (in general) contain space for some number of
  56. * invalid sectors that are actually beyond the end of the disk
  57. * device. This is ok. These sectors are supposed to be marked "in
  58. * use" by mksfs and never get marked "free".
  59. *
  60. * The sectors used by the superblock and the bitmap itself are
  61. * likewise marked in use by mksfs.
  62. */
  63. static
  64. int
  65. sfs_mapio(struct sfs_fs *sfs, enum uio_rw rw)
  66. {
  67. uint32_t j, mapsize;
  68. char *bitdata;
  69. int result;
  70. /* Number of blocks in the bitmap. */
  71. mapsize = SFS_FS_BITBLOCKS(sfs);
  72. /* Pointer to our bitmap data in memory. */
  73. bitdata = bitmap_getdata(sfs->sfs_freemap);
  74. /* For each sector in the bitmap... */
  75. for (j=0; j<mapsize; j++) {
  76. /* Get a pointer to its data */
  77. void *ptr = bitdata + j*SFS_BLOCKSIZE;
  78. /* and read or write it. The bitmap starts at sector 2. */
  79. if (rw == UIO_READ) {
  80. result = sfs_rblock(sfs, ptr, SFS_MAP_LOCATION+j);
  81. }
  82. else {
  83. result = sfs_wblock(sfs, ptr, SFS_MAP_LOCATION+j);
  84. }
  85. /* If we failed, stop. */
  86. if (result) {
  87. return result;
  88. }
  89. }
  90. return 0;
  91. }
  92. /*
  93. * Sync routine. This is what gets invoked if you do FS_SYNC on the
  94. * sfs filesystem structure.
  95. */
  96. static
  97. int
  98. sfs_sync(struct fs *fs)
  99. {
  100. struct sfs_fs *sfs;
  101. unsigned i, num;
  102. int result;
  103. vfs_biglock_acquire();
  104. /*
  105. * Get the sfs_fs from the generic abstract fs.
  106. *
  107. * Note that the abstract struct fs, which is all the VFS
  108. * layer knows about, is actually a member of struct sfs_fs.
  109. * The pointer in the struct fs points back to the top of the
  110. * struct sfs_fs - essentially the same object. This can be a
  111. * little confusing at first.
  112. *
  113. * The following diagram may help:
  114. *
  115. * struct sfs_fs <-------------\
  116. * : |
  117. * : sfs_absfs (struct fs) | <------\
  118. * : : | |
  119. * : : various members | |
  120. * : : | |
  121. * : : fs_data ----------/ |
  122. * : : ...|...
  123. * : . VFS .
  124. * : . layer .
  125. * : other members .......
  126. * :
  127. * :
  128. *
  129. * This construct is repeated with vnodes and devices and other
  130. * similar things all over the place in OS/161, so taking the
  131. * time to straighten it out in your mind is worthwhile.
  132. */
  133. sfs = fs->fs_data;
  134. /* Go over the array of loaded vnodes, syncing as we go. */
  135. num = vnodearray_num(sfs->sfs_vnodes);
  136. for (i=0; i<num; i++) {
  137. struct vnode *v = vnodearray_get(sfs->sfs_vnodes, i);
  138. VOP_FSYNC(v);
  139. }
  140. /* If the free block map needs to be written, write it. */
  141. if (sfs->sfs_freemapdirty) {
  142. result = sfs_mapio(sfs, UIO_WRITE);
  143. if (result) {
  144. vfs_biglock_release();
  145. return result;
  146. }
  147. sfs->sfs_freemapdirty = false;
  148. }
  149. /* If the superblock needs to be written, write it. */
  150. if (sfs->sfs_superdirty) {
  151. result = sfs_wblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION);
  152. if (result) {
  153. vfs_biglock_release();
  154. return result;
  155. }
  156. sfs->sfs_superdirty = false;
  157. }
  158. vfs_biglock_release();
  159. return 0;
  160. }
  161. /*
  162. * Routine to retrieve the volume name. Filesystems can be referred
  163. * to by their volume name followed by a colon as well as the name
  164. * of the device they're mounted on.
  165. */
  166. static
  167. const char *
  168. sfs_getvolname(struct fs *fs)
  169. {
  170. struct sfs_fs *sfs = fs->fs_data;
  171. const char *ret;
  172. vfs_biglock_acquire();
  173. ret = sfs->sfs_super.sp_volname;
  174. vfs_biglock_release();
  175. return ret;
  176. }
  177. /*
  178. * Unmount code.
  179. *
  180. * VFS calls FS_SYNC on the filesystem prior to unmounting it.
  181. */
  182. static
  183. int
  184. sfs_unmount(struct fs *fs)
  185. {
  186. struct sfs_fs *sfs = fs->fs_data;
  187. vfs_biglock_acquire();
  188. /* Do we have any files open? If so, can't unmount. */
  189. if (vnodearray_num(sfs->sfs_vnodes) > 0) {
  190. vfs_biglock_release();
  191. return EBUSY;
  192. }
  193. /* We should have just had sfs_sync called. */
  194. KASSERT(sfs->sfs_superdirty == false);
  195. KASSERT(sfs->sfs_freemapdirty == false);
  196. /* Once we start nuking stuff we can't fail. */
  197. vnodearray_destroy(sfs->sfs_vnodes);
  198. bitmap_destroy(sfs->sfs_freemap);
  199. /* The vfs layer takes care of the device for us */
  200. (void)sfs->sfs_device;
  201. /* Destroy the fs object */
  202. kfree(sfs);
  203. /* nothing else to do */
  204. vfs_biglock_release();
  205. return 0;
  206. }
  207. /*
  208. * Mount routine.
  209. *
  210. * The way mount works is that you call vfs_mount and pass it a
  211. * filesystem-specific mount routine. Said routine takes a device and
  212. * hands back a pointer to an abstract filesystem. You can also pass
  213. * a void pointer through.
  214. *
  215. * This organization makes cleanup on error easier. Hint: it may also
  216. * be easier to synchronize correctly; it is important not to get two
  217. * filesystem with the same name mounted at once, or two filesystems
  218. * mounted on the same device at once.
  219. */
  220. static
  221. int
  222. sfs_domount(void *options, struct device *dev, struct fs **ret)
  223. {
  224. int result;
  225. struct sfs_fs *sfs;
  226. vfs_biglock_acquire();
  227. /* We don't pass any options through mount */
  228. (void)options;
  229. /*
  230. * Make sure our on-disk structures aren't messed up
  231. */
  232. KASSERT(sizeof(struct sfs_super)==SFS_BLOCKSIZE);
  233. KASSERT(sizeof(struct sfs_inode)==SFS_BLOCKSIZE);
  234. KASSERT(SFS_BLOCKSIZE % sizeof(struct sfs_dir) == 0);
  235. /*
  236. * We can't mount on devices with the wrong sector size.
  237. *
  238. * (Note: for all intents and purposes here, "sector" and
  239. * "block" are interchangeable terms. Technically a filesystem
  240. * block may be composed of several hardware sectors, but we
  241. * don't do that in sfs.)
  242. */
  243. if (dev->d_blocksize != SFS_BLOCKSIZE) {
  244. vfs_biglock_release();
  245. return ENXIO;
  246. }
  247. /* Allocate object */
  248. sfs = kmalloc(sizeof(struct sfs_fs));
  249. if (sfs==NULL) {
  250. vfs_biglock_release();
  251. return ENOMEM;
  252. }
  253. /* Allocate array */
  254. sfs->sfs_vnodes = vnodearray_create();
  255. if (sfs->sfs_vnodes == NULL) {
  256. kfree(sfs);
  257. vfs_biglock_release();
  258. return ENOMEM;
  259. }
  260. /* Set the device so we can use sfs_rblock() */
  261. sfs->sfs_device = dev;
  262. /* Load superblock */
  263. result = sfs_rblock(sfs, &sfs->sfs_super, SFS_SB_LOCATION);
  264. if (result) {
  265. vnodearray_destroy(sfs->sfs_vnodes);
  266. kfree(sfs);
  267. vfs_biglock_release();
  268. return result;
  269. }
  270. /* Make some simple sanity checks */
  271. if (sfs->sfs_super.sp_magic != SFS_MAGIC) {
  272. kprintf("sfs: Wrong magic number in superblock "
  273. "(0x%x, should be 0x%x)\n",
  274. sfs->sfs_super.sp_magic,
  275. SFS_MAGIC);
  276. vnodearray_destroy(sfs->sfs_vnodes);
  277. kfree(sfs);
  278. vfs_biglock_release();
  279. return EINVAL;
  280. }
  281. if (sfs->sfs_super.sp_nblocks > dev->d_blocks) {
  282. kprintf("sfs: warning - fs has %u blocks, device has %u\n",
  283. sfs->sfs_super.sp_nblocks, dev->d_blocks);
  284. }
  285. /* Ensure null termination of the volume name */
  286. sfs->sfs_super.sp_volname[sizeof(sfs->sfs_super.sp_volname)-1] = 0;
  287. /* Load free space bitmap */
  288. sfs->sfs_freemap = bitmap_create(SFS_FS_BITMAPSIZE(sfs));
  289. if (sfs->sfs_freemap == NULL) {
  290. vnodearray_destroy(sfs->sfs_vnodes);
  291. kfree(sfs);
  292. vfs_biglock_release();
  293. return ENOMEM;
  294. }
  295. result = sfs_mapio(sfs, UIO_READ);
  296. if (result) {
  297. bitmap_destroy(sfs->sfs_freemap);
  298. vnodearray_destroy(sfs->sfs_vnodes);
  299. kfree(sfs);
  300. vfs_biglock_release();
  301. return result;
  302. }
  303. /* Set up abstract fs calls */
  304. sfs->sfs_absfs.fs_sync = sfs_sync;
  305. sfs->sfs_absfs.fs_getvolname = sfs_getvolname;
  306. sfs->sfs_absfs.fs_getroot = sfs_getroot;
  307. sfs->sfs_absfs.fs_unmount = sfs_unmount;
  308. sfs->sfs_absfs.fs_data = sfs;
  309. /* the other fields */
  310. sfs->sfs_superdirty = false;
  311. sfs->sfs_freemapdirty = false;
  312. /* Hand back the abstract fs */
  313. *ret = &sfs->sfs_absfs;
  314. vfs_biglock_release();
  315. return 0;
  316. }
  317. /*
  318. * Actual function called from high-level code to mount an sfs.
  319. */
  320. int
  321. sfs_mount(const char *device)
  322. {
  323. return vfs_mount(device, NULL, sfs_domount);
  324. }