|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
001 /* Copyright (C) 2005,2006 David Decotigny 002 003 This program is free software; you can redistribute it and/or 004 modify it under the terms of the GNU General Public License 005 as published by the Free Software Foundation; either version 2 006 of the License, or (at your option) any later version. 007 008 This program is distributed in the hope that it will be useful, 009 but WITHOUT ANY WARRANTY; without even the implied warranty of 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 011 GNU General Public License for more details. 012 013 You should have received a copy of the GNU General Public License 014 along with this program; if not, write to the Free Software 015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 016 USA. 017 */ 018 #ifndef _SOS_BLKDEV_H_ 019 #define _SOS_BLKDEV_H_ 020 021 /** 022 * @file blkdev.h 023 * 024 * Interface between the VFS and the "block" devices (real devices and 025 * their partitions). The following functions provide the mechanisms 026 * to bind the "block device" nodes (@see mknod) to their device 027 * driver. 028 * 029 * The "blkdev" layer is to be perceived as a FS-agnostic layer both 030 * below and on top of the FS that binds the special "block device" 031 * nodes to a set of system-wide block_read/block_write functions and 032 * which supports the cache of blocks for the device. 033 * 034 * The differences between the char device and the block device layers are: 035 * - A character device is byte-stream-oriented: one can easily fetch 036 * the data character by character. Theoretically, this stream has 037 * no limitation in size: it has a beginning but not necessarly an 038 * end. One can not necessarly rewind the stream, that is seek 039 * anywhere in it (as for a stream of audio data coming from a 040 * soundcard for example). But for some character devices, it is 041 * possible, though (it is possible to seek anywhere in /dev/zero 042 * for example). For some other devices, it is possible to seek only 043 * in some authorized regions (as for /dev/kmem for example: only 044 * the mapped kernel regions are available). 045 * - A block device is block-oriented: one can easily fetch fixed-size 046 * blocks of data anywhere inside the device, possibly in a random 047 * order. The capacity of the device is limited: there is a defined 048 * number of contiguous blocks reachable in the device, one cannot 049 * seek beyond its limits. 050 * - A block device is well suited to a cache layer: it is possible to 051 * cache the most used blocks inside memory to speed up the accesses 052 * to data. It doesn't make sense to do so on stream-oriented devices 053 * like character devices. 054 * - A character device is limited to the interaction between 055 * user-mode programs and the devices themselves. The kernel only acts 056 * as an intermediary and does not take care of the operations 057 * carried out. 058 * - A block device is used as the underlying data support for a 059 * filesystem. As a result, it must be managed by the kernel itself 060 * since the FS code resides inside the kernel. It must offer an API 061 * compatible with kernel-space interaction. 062 * 063 * A partition has the same properties as a disk: both are block 064 * devices. The main difference is that a disk really "owns" its 065 * operations (ie the read/write/ioctl operations are defined by him) 066 * and its block cache, whereas a partition shares them with its 067 * parent disk/partition. The partitions may be nested: a disk can 068 * have partitions, which can have sub-partitions, which can have 069 * sub-sub-partittions, etc. As a consequence, a parent disk/partition 070 * cannot be unregistered as long as it owns any child partitions. The 071 * only constraint being that the partitions must fit completely 072 * inside their parent partition/disk. However, no check is made 073 * regarding partitions overlapping one another... 074 * 075 * This implementation is based on two subsystems: 076 * - the block cache to accelerate accesses to the hardware by caching 077 * the most frequently used blocks in main memory 078 * - the page cache to guarantee consistency between read/write 079 * accesses and MMU access of mapped pages (mmap API). This is a 080 * simple dictionary of the device's mapped pages: offset -> mapped 081 * page. The read/write vs MMU consistency is achieved in a simple 082 * manner: before each read/write accesses, we first try to use the 083 * page cache, and eventually the block cache if the data is not 084 * mapped by anybody. 085 */ 086 087 /* Forward declaration */ 088 struct sos_blockdev_instance; 089 090 #include <sos/fs.h> 091 092 /** 093 * The fundamental callbacks for a real block device (ie not a 094 * partition). 095 */ 096 struct sos_blockdev_operations { 097 098 /** @note MANDATORY */ 099 sos_ret_t (*read_block)(void * blockdev_instance_custom_data, 100 sos_vaddr_t dest_buf /* Kernel address */, 101 sos_luoffset_t block_offset); 102 103 104 /** @note Optional (may be NULL) */ 105 sos_ret_t (*write_block)(void * blockdev_instance_custom_data, 106 sos_vaddr_t src_buf /* Kernel address */, 107 sos_luoffset_t block_offset); 108 109 110 /** 111 * @note Optional (may be NULL) 112 * @note Also called when an ioctl is made to a partition 113 */ 114 sos_ret_t (*ioctl)(void * blockdev_instance_custom_data, 115 int req_id, 116 sos_ui32_t req_arg /* Usually: sos_uaddr_t */); 117 }; 118 119 120 /* 121 * Functions restricted to block device driver code 122 */ 123 124 125 sos_ret_t sos_blockdev_subsystem_setup(void); 126 127 128 /** 129 * Contrary to Character devices, block devices are registered 130 * individually: any single registration corresponds to a driver for a 131 * single device instance 132 */ 133 sos_ret_t 134 sos_blockdev_register_disk (sos_ui32_t device_class, 135 sos_ui32_t device_instance, 136 sos_size_t block_size, 137 sos_lcount_t number_of_blocks, 138 sos_count_t cache_size_in_blocks, 139 struct sos_blockdev_operations * blockdev_ops, 140 void * blockdev_instance_custom_data); 141 142 143 /** 144 * @param index_of_first_block is the index of the first block 145 * relative to parent_bd, NOT relative to the top-most disk block 146 * device 147 */ 148 sos_ret_t 149 sos_blockdev_register_partition(sos_ui32_t device_class, 150 sos_ui32_t device_instance, 151 struct sos_blockdev_instance * parent_bd, 152 sos_luoffset_t index_of_first_block, 153 sos_lcount_t number_of_blocks, 154 void * blockdev_instance_custom_data); 155 156 157 sos_ret_t sos_blockdev_unregister_device (sos_ui32_t device_class, 158 sos_ui32_t device_instance); 159 160 161 /** 162 * Flush all caches of all devices to disk 163 */ 164 sos_ret_t sos_blockdev_sync_all_devices(void); 165 166 167 /** 168 * Increments the instance's reference counter: this will make any 169 * blockdev_unregister return BUSY. As a consequence, the following 170 * operations on blockdev instances should be as fast as possible and 171 * call release_instance as early as possible 172 */ 173 struct sos_blockdev_instance * 174 sos_blockdev_ref_instance(sos_ui32_t device_class, 175 sos_ui32_t device_instance); 176 177 178 sos_ret_t 179 sos_blockdev_release_instance(struct sos_blockdev_instance * blockdev); 180 181 182 /** Read data from disk and use it directly in the kernel. Mostly used 183 by the partition drivers to identify the partitions of a disk and 184 register them */ 185 sos_ret_t sos_blockdev_kernel_read(struct sos_blockdev_instance * blockdev, 186 sos_luoffset_t offset, 187 sos_vaddr_t dest_buf, 188 sos_size_t * /* in/out */len); 189 190 191 /** 192 * Write data to disk directly from the kernel. Mostly used by the 193 * partition drivers to modify the partitions of a disk and register 194 * them. 195 * 196 * @note The operation is normally NOT needed (fdisk is a userspace 197 * program) and is NOT synchronous 198 */ 199 sos_ret_t sos_blockdev_kernel_write(struct sos_blockdev_instance * blockdev, 200 sos_luoffset_t offset, 201 sos_vaddr_t src_buf, 202 sos_size_t * /* in/out */len); 203 204 205 /** 206 * Flush the modified blocks back to hardware (both block and page 207 * cache are flusehd) 208 */ 209 sos_ret_t sos_blockdev_sync(struct sos_blockdev_instance * blockdev); 210 211 212 /* 213 * Callbacks and functions restricted to fs.c internals 214 */ 215 216 /** 217 * Update the FS node ops_blockdev callbacks after an FS 218 * allocate_new_node or fetch_node_from_disk, in order to point to 219 * the block layer API functions 220 */ 221 sos_ret_t sos_blockdev_helper_ref_new_fsnode(struct sos_fs_node * this); 222 sos_ret_t sos_blockdev_helper_release_fsnode(struct sos_fs_node * this); 223 sos_ret_t sos_blockdev_helper_sync_fsnode(struct sos_fs_node * this); 224 225 #endif
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |