PKUOS - Pintos
Pintos source browser for PKU Operating System course
block.c
Go to the documentation of this file.
1#include "devices/block.h"
2#include <list.h>
3#include <string.h>
4#include <stdio.h>
5#include "devices/ide.h"
6#include "threads/malloc.h"
7
8/** A block device. */
9struct block
10 {
11 struct list_elem list_elem; /**< Element in all_blocks. */
12
13 char name[16]; /**< Block device name. */
14 enum block_type type; /**< Type of block device. */
15 block_sector_t size; /**< Size in sectors. */
16
17 const struct block_operations *ops; /**< Driver operations. */
18 void *aux; /**< Extra data owned by driver. */
19
20 unsigned long long read_cnt; /**< Number of sectors read. */
21 unsigned long long write_cnt; /**< Number of sectors written. */
22 };
23
24/** List of all block devices. */
26
27/** The block block assigned to each Pintos role. */
29
30static struct block *list_elem_to_block (struct list_elem *);
31
32/** Returns a human-readable name for the given block device
33 TYPE. */
34const char *
36{
37 static const char *block_type_names[BLOCK_CNT] =
38 {
39 "kernel",
40 "filesys",
41 "scratch",
42 "swap",
43 "raw",
44 "foreign",
45 };
46
48 return block_type_names[type];
49}
50
51/** Returns the block device fulfilling the given ROLE, or a null
52 pointer if no block device has been assigned that role. */
53struct block *
55{
56 ASSERT (role < BLOCK_ROLE_CNT);
57 return block_by_role[role];
58}
59
60/** Assigns BLOCK the given ROLE. */
61void
63{
64 ASSERT (role < BLOCK_ROLE_CNT);
65 block_by_role[role] = block;
66}
67
68/** Returns the first block device in kernel probe order, or a
69 null pointer if no block devices are registered. */
70struct block *
72{
74}
75
76/** Returns the block device following BLOCK in kernel probe
77 order, or a null pointer if BLOCK is the last block device. */
78struct block *
80{
82}
83
84/** Returns the block device with the given NAME, or a null
85 pointer if no block device has that name. */
86struct block *
88{
89 struct list_elem *e;
90
91 for (e = list_begin (&all_blocks); e != list_end (&all_blocks);
92 e = list_next (e))
93 {
94 struct block *block = list_entry (e, struct block, list_elem);
95 if (!strcmp (name, block->name))
96 return block;
97 }
98
99 return NULL;
100}
101
102/** Verifies that SECTOR is a valid offset within BLOCK.
103 Panics if not. */
104static void
106{
107 if (sector >= block->size)
108 {
109 /* We do not use ASSERT because we want to panic here
110 regardless of whether NDEBUG is defined. */
111 PANIC ("Access past end of device %s (sector=%"PRDSNu", "
112 "size=%"PRDSNu")\n", block_name (block), sector, block->size);
113 }
114}
115
116/** Reads sector SECTOR from BLOCK into BUFFER, which must
117 have room for BLOCK_SECTOR_SIZE bytes.
118 Internally synchronizes accesses to block devices, so external
119 per-block device locking is unneeded. */
120void
122{
123 check_sector (block, sector);
124 block->ops->read (block->aux, sector, buffer);
125 block->read_cnt++;
126}
127
128/** Write sector SECTOR to BLOCK from BUFFER, which must contain
129 BLOCK_SECTOR_SIZE bytes. Returns after the block device has
130 acknowledged receiving the data.
131 Internally synchronizes accesses to block devices, so external
132 per-block device locking is unneeded. */
133void
134block_write (struct block *block, block_sector_t sector, const void *buffer)
135{
136 check_sector (block, sector);
138 block->ops->write (block->aux, sector, buffer);
139 block->write_cnt++;
140}
141
142/** Returns the number of sectors in BLOCK. */
145{
146 return block->size;
147}
148
149/** Returns BLOCK's name (e.g. "hda"). */
150const char *
152{
153 return block->name;
154}
155
156/** Returns BLOCK's type. */
157enum block_type
159{
160 return block->type;
161}
162
163/** Prints statistics for each block device used for a Pintos role. */
164void
166{
167 int i;
168
169 for (i = 0; i < BLOCK_ROLE_CNT; i++)
170 {
171 struct block *block = block_by_role[i];
172 if (block != NULL)
173 {
174 printf ("%s (%s): %llu reads, %llu writes\n",
177 }
178 }
179}
180
181/** Registers a new block device with the given NAME. If
182 EXTRA_INFO is non-null, it is printed as part of a user
183 message. The block device's SIZE in sectors and its TYPE must
184 be provided, as well as the it operation functions OPS, which
185 will be passed AUX in each function call. */
186struct block *
188 const char *extra_info, block_sector_t size,
189 const struct block_operations *ops, void *aux)
190{
191 struct block *block = malloc (sizeof *block);
192 if (block == NULL)
193 PANIC ("Failed to allocate memory for block device descriptor");
194
196 strlcpy (block->name, name, sizeof block->name);
197 block->type = type;
198 block->size = size;
199 block->ops = ops;
200 block->aux = aux;
201 block->read_cnt = 0;
202 block->write_cnt = 0;
203
204 printf ("%s: %'"PRDSNu" sectors (", block->name, block->size);
206 printf (")");
207 if (extra_info != NULL)
208 printf (", %s", extra_info);
209 printf ("\n");
210
211 return block;
212}
213
214/** Returns the block device corresponding to LIST_ELEM, or a null
215 pointer if LIST_ELEM is the list end of all_blocks. */
216static struct block *
218{
219 return (list_elem != list_end (&all_blocks)
221 : NULL);
222}
223
static struct list all_blocks
List of all block devices.
Definition: block.c:25
struct block * block_first(void)
Returns the first block device in kernel probe order, or a null pointer if no block devices are regis...
Definition: block.c:71
struct block * block_get_by_name(const char *name)
Returns the block device with the given NAME, or a null pointer if no block device has that name.
Definition: block.c:87
struct block * block_register(const char *name, enum block_type type, const char *extra_info, block_sector_t size, const struct block_operations *ops, void *aux)
Registers a new block device with the given NAME.
Definition: block.c:187
struct block * block_get_role(enum block_type role)
Returns the block device fulfilling the given ROLE, or a null pointer if no block device has been ass...
Definition: block.c:54
block_sector_t block_size(struct block *block)
Returns the number of sectors in BLOCK.
Definition: block.c:144
const char * block_type_name(enum block_type type)
Returns a human-readable name for the given block device TYPE.
Definition: block.c:35
void block_read(struct block *block, block_sector_t sector, void *buffer)
Reads sector SECTOR from BLOCK into BUFFER, which must have room for BLOCK_SECTOR_SIZE bytes.
Definition: block.c:121
void block_set_role(enum block_type role, struct block *block)
Assigns BLOCK the given ROLE.
Definition: block.c:62
static void check_sector(struct block *block, block_sector_t sector)
Verifies that SECTOR is a valid offset within BLOCK.
Definition: block.c:105
static struct block * block_by_role[BLOCK_ROLE_CNT]
The block block assigned to each Pintos role.
Definition: block.c:28
static struct block * list_elem_to_block(struct list_elem *)
Returns the block device corresponding to LIST_ELEM, or a null pointer if LIST_ELEM is the list end o...
Definition: block.c:217
void block_write(struct block *block, block_sector_t sector, const void *buffer)
Write sector SECTOR to BLOCK from BUFFER, which must contain BLOCK_SECTOR_SIZE bytes.
Definition: block.c:134
const char * block_name(struct block *block)
Returns BLOCK's name (e.g.
Definition: block.c:151
enum block_type block_type(struct block *block)
Returns BLOCK's type.
Definition: block.c:158
struct block * block_next(struct block *block)
Returns the block device following BLOCK in kernel probe order, or a null pointer if BLOCK is the las...
Definition: block.c:79
void block_print_stats(void)
Prints statistics for each block device used for a Pintos role.
Definition: block.c:165
uint32_t block_sector_t
Index of a block device sector.
Definition: block.h:15
#define BLOCK_SECTOR_SIZE
Size of a block device sector in bytes.
Definition: block.h:11
#define PRDSNu
Format specifier for printf(), e.g.
Definition: block.h:19
block_type
Type of a block device.
Definition: block.h:27
@ BLOCK_ROLE_CNT
Definition: block.h:33
@ BLOCK_CNT
Number of Pintos block types.
Definition: block.h:39
@ BLOCK_FOREIGN
Owned by non-Pintos operating system.
Definition: block.h:38
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
#define PANIC(...)
Halts the OS, printing the source file name, line number, and function name, plus a user-specific mes...
Definition: debug.h:14
static struct intq buffer
Stores keys from the keyboard and serial port.
Definition: input.c:7
char * name[]
Definition: insult.c:47
struct list_elem * list_begin(struct list *list)
Returns the beginning of LIST.
Definition: list.c:72
struct list_elem * list_end(struct list *list)
Returns LIST's tail.
Definition: list.c:94
void list_push_back(struct list *list, struct list_elem *elem)
Inserts ELEM at the end of LIST, so that it becomes the back in LIST.
Definition: list.c:217
struct list_elem * list_next(struct list_elem *elem)
Returns the element after ELEM in its list.
Definition: list.c:82
void print_human_readable_size(uint64_t size)
Prints SIZE, which represents a number of bytes, in a human-readable format, e.g.
Definition: stdio.c:642
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
#define LIST_INITIALIZER(NAME)
List initialization.
Definition: list.h:122
#define list_entry(LIST_ELEM, STRUCT, MEMBER)
Converts pointer to list element LIST_ELEM into a pointer to the structure that LIST_ELEM is embedded...
Definition: list.h:108
void * malloc(size_t size)
Obtains and returns a new block of at least SIZE bytes.
Definition: malloc.c:90
#define NULL
Definition: stddef.h:4
unsigned long long int uint64_t
Definition: stdint.h:29
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
int strcmp(const char *a_, const char *b_)
Finds the first differing characters in strings A and B.
Definition: string.c:73
Lower-level interface to block device drivers.
Definition: block.h:65
void(* write)(void *aux, block_sector_t, const void *buffer)
Definition: block.h:67
void(* read)(void *aux, block_sector_t, void *buffer)
Definition: block.h:66
A block device.
Definition: block.c:10
unsigned long long write_cnt
Number of sectors written.
Definition: block.c:21
const struct block_operations * ops
Driver operations.
Definition: block.c:17
char name[16]
Block device name.
Definition: block.c:13
struct list_elem list_elem
Element in all_blocks.
Definition: block.c:11
enum block_type type
Type of block device.
Definition: block.c:14
void * aux
Extra data owned by driver.
Definition: block.c:18
block_sector_t size
Size in sectors.
Definition: block.c:15
unsigned long long read_cnt
Number of sectors read.
Definition: block.c:20
Doubly linked list.
Definition: list.h:91
List.
Definition: list.h:98