3
* Fast Ramdisk implementation.
5
* (c) 2006 Andrew Warfield and Julian Chesterfield
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License version 2
9
* as published by the Free Software Foundation; or, when distributed
10
* separately from the Linux kernel or incorporated into other
11
* software packages, subject to the following license:
13
* Permission is hereby granted, free of charge, to any person obtaining a copy
14
* of this source file (the "Software"), to deal in the Software without
15
* restriction, including without limitation the rights to use, copy, modify,
16
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
17
* and to permit persons to whom the Software is furnished to do so, subject to
18
* the following conditions:
20
* The above copyright notice and this permission notice shall be included in
21
* all copies or substantial portions of the Software.
23
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
38
#include <sys/statvfs.h>
40
#include <sys/ioctl.h>
45
#define MAX_DISK_SIZE 1024000 /*500MB disk limit*/
47
/* *BSD has no O_LARGEFILE */
53
long int disksector_size;
56
static int connections = 0;
60
int poll_pipe[2]; /* dummy fd for polling on */
63
/*Get Image size, secsize*/
64
static int get_image_info(struct td_state *s, int fd)
68
unsigned long total_size;
69
struct statvfs statBuf;
72
ret = fstat(fd, &stat);
74
DPRINTF("ERROR: fstat failed, Couldn't stat image");
78
if (S_ISBLK(stat.st_mode)) {
79
/*Accessing block device directly*/
80
if (blk_getimagesize(fd, &s->size) != 0)
83
DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost "
84
"sector_shift [%llu]\n",
85
(long long unsigned)(s->size << SECTOR_SHIFT),
86
(long long unsigned)s->size);
88
/*Get the sector size*/
89
if (blk_getsectorsize(fd, &s->sector_size) != 0)
90
s->sector_size = DEFAULT_SECTOR_SIZE;
93
/*Local file? try fstat instead*/
94
s->size = (stat.st_size >> SECTOR_SHIFT);
95
s->sector_size = DEFAULT_SECTOR_SIZE;
96
DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost "
97
"sector_shift [%llu]\n",
98
(long long unsigned)(s->size << SECTOR_SHIFT),
99
(long long unsigned)s->size);
103
s->size =((uint64_t) MAX_DISK_SIZE);
104
s->sector_size = DEFAULT_SECTOR_SIZE;
108
/*Store variables locally*/
109
disksector_size = s->sector_size;
112
DPRINTF("Image sector_size: \n\t[%"PRIu64"]\n",
118
static inline void init_fds(struct disk_driver *dd)
121
struct tdram_state *prv = (struct tdram_state *)dd->private;
123
for(i =0 ; i < MAX_IOFD; i++)
126
dd->io_fd[0] = prv->poll_pipe[0];
129
/* Open the disk file and initialize ram state. */
130
static int tdram_open (struct disk_driver *dd, const char *name, td_flag_t flags)
134
int i, fd, ret = 0, count = 0, o_flags;
135
struct td_state *s = dd->td_state;
136
struct tdram_state *prv = (struct tdram_state *)dd->private;
140
/* set up a pipe so that we can hand back a poll fd that won't fire.*/
141
ret = pipe(prv->poll_pipe);
145
if (connections > 1) {
146
s->sector_size = disksector_size;
149
DPRINTF("Image already open, returning parameters:\n");
150
DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost "
151
"sector_shift [%llu]\n",
152
(long long unsigned)(s->size << SECTOR_SHIFT),
153
(long long unsigned)s->size);
154
DPRINTF("Image sector_size: \n\t[%"PRIu64"]\n",
162
o_flags = O_DIRECT | O_LARGEFILE |
163
((flags == TD_RDONLY) ? O_RDONLY : O_RDWR);
164
fd = open(name, o_flags);
166
if ((fd == -1) && (errno == EINVAL)) {
168
/* Maybe O_DIRECT isn't supported. */
169
o_flags &= ~O_DIRECT;
170
fd = open(name, o_flags);
171
if (fd != -1) DPRINTF("WARNING: Accessing image without"
172
"O_DIRECT! (%s)\n", name);
174
} else if (fd != -1) DPRINTF("open(%s) with O_DIRECT\n", name);
177
DPRINTF("Unable to open [%s]!\n",name);
184
ret = get_image_info(s, fd);
185
size = MAX_DISK_SIZE;
187
if (s->size > size) {
188
DPRINTF("Disk exceeds limit, must be less than [%d]MB",
189
(MAX_DISK_SIZE<<SECTOR_SHIFT)>>20);
193
/*Read the image into memory*/
194
p = img = malloc(s->size << SECTOR_SHIFT);
196
DPRINTF("Mem malloc failed\n");
199
DPRINTF("Reading %llu bytes.......",(long long unsigned)s->size << SECTOR_SHIFT);
201
for (i = 0; i < s->size; i++) {
202
ret = read(prv->fd, p, s->sector_size);
203
if (ret != s->sector_size) {
211
DPRINTF("[%d]\n",count);
212
if (count != s->size << SECTOR_SHIFT) {
223
static int tdram_queue_read(struct disk_driver *dd, uint64_t sector,
224
int nb_sectors, char *buf, td_callback_t cb,
225
int id, void *private)
227
struct td_state *s = dd->td_state;
228
struct tdram_state *prv = (struct tdram_state *)dd->private;
229
int size = nb_sectors * s->sector_size;
230
uint64_t offset = sector * (uint64_t)s->sector_size;
232
memcpy(buf, img + offset, size);
234
return cb(dd, 0, sector, nb_sectors, id, private);
237
static int tdram_queue_write(struct disk_driver *dd, uint64_t sector,
238
int nb_sectors, char *buf, td_callback_t cb,
239
int id, void *private)
241
struct td_state *s = dd->td_state;
242
struct tdram_state *prv = (struct tdram_state *)dd->private;
243
int size = nb_sectors * s->sector_size;
244
uint64_t offset = sector * (uint64_t)s->sector_size;
246
/* We assume that write access is controlled
247
* at a higher level for multiple disks */
248
memcpy(img + offset, buf, size);
250
return cb(dd, 0, sector, nb_sectors, id, private);
253
static int tdram_submit(struct disk_driver *dd)
258
static int tdram_close(struct disk_driver *dd)
260
struct tdram_state *prv = (struct tdram_state *)dd->private;
267
static int tdram_do_callbacks(struct disk_driver *dd, int sid)
269
/* always ask for a kick */
273
static int tdram_get_parent_id(struct disk_driver *dd, struct disk_id *id)
278
static int tdram_validate_parent(struct disk_driver *dd,
279
struct disk_driver *parent, td_flag_t flags)
284
struct tap_disk tapdisk_ram = {
285
.disk_type = "tapdisk_ram",
286
.private_data_size = sizeof(struct tdram_state),
287
.td_open = tdram_open,
288
.td_queue_read = tdram_queue_read,
289
.td_queue_write = tdram_queue_write,
290
.td_submit = tdram_submit,
291
.td_close = tdram_close,
292
.td_do_callbacks = tdram_do_callbacks,
293
.td_get_parent_id = tdram_get_parent_id,
294
.td_validate_parent = tdram_validate_parent