Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3527 → Rev 3530

/trunk/uspace/lib/libblock/libblock.c
38,16 → 38,82
#include "libblock.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <ipc/devmap.h>
#include <ipc/services.h>
#include <errno.h>
#include <sys/mman.h>
#include <async.h>
#include <ipc/ipc.h>
#include <as.h>
#include <assert.h>
 
static int dev_phone = -1; /* FIXME */
static void *dev_buffer = NULL; /* FIXME */
static size_t dev_buffer_len = 0; /* FIXME */
static void *bblock = NULL; /* FIXME */
 
int
block_init(dev_handle_t dev_handle, size_t com_size, off_t bb_off,
size_t bb_size)
{
int rc;
 
bblock = malloc(bb_size);
if (!bblock)
return ENOMEM;
dev_buffer_len = com_size;
dev_buffer = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (!dev_buffer) {
free(bblock);
return ENOMEM;
}
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
if (dev_phone < 0) {
free(bblock);
munmap(dev_buffer, com_size);
return dev_phone;
}
 
rc = ipc_share_out_start(dev_phone, dev_buffer,
AS_AREA_READ | AS_AREA_WRITE);
if (rc != EOK) {
ipc_hangup(dev_phone);
free(bblock);
munmap(dev_buffer, com_size);
return rc;
}
off_t bufpos = 0;
size_t buflen = 0;
if (!block_read(dev_handle, &bufpos, &buflen, &bb_off,
bblock, bb_size, bb_size)) {
ipc_hangup(dev_phone);
free(bblock);
munmap(dev_buffer, com_size);
return EIO; /* XXX real error code */
}
return EOK;
}
 
void block_fini(dev_handle_t dev_handle)
{
/* XXX */
free(bblock);
munmap(dev_buffer, dev_buffer_len);
ipc_hangup(dev_phone);
}
 
void *block_bb_get(dev_handle_t dev_handle)
{
/* XXX */
return bblock;
}
 
/** Read data from a block device.
*
* @param phone Phone to be used to communicate with the device.
* @param buffer Communication buffer shared with the device.
* @param dev_handle Device handle of the block device.
* @param bufpos Pointer to the first unread valid offset within the
* communication buffer.
* @param buflen Pointer to the number of unread bytes that are ready in
59,8 → 125,9
*
* @return True on success, false on failure.
*/
bool blockread(int phone, void *buffer, off_t *bufpos, size_t *buflen,
off_t *pos, void *dst, size_t size, size_t block_size)
bool
block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst,
size_t size, size_t block_size)
{
off_t offset = 0;
size_t left = size;
78,7 → 145,7
* Copy the contents of the communication buffer to the
* destination buffer.
*/
memcpy(dst + offset, buffer + *bufpos, rd);
memcpy(dst + offset, dev_buffer + *bufpos, rd);
offset += rd;
*bufpos += rd;
*pos += rd;
88,7 → 155,7
if (*bufpos == *buflen) {
/* Refill the communication buffer with a new block. */
ipcarg_t retval;
int rc = async_req_2_1(phone, RD_READ_BLOCK,
int rc = async_req_2_1(dev_phone, RD_READ_BLOCK,
*pos / block_size, block_size, &retval);
if ((rc != EOK) || (retval != EOK))
return false;
101,9 → 168,6
return true;
}
 
int dev_phone = -1; /* FIXME */
void *dev_buffer = NULL; /* FIXME */
 
block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
{
/* FIXME */
126,7 → 190,7
}
b->size = bs;
 
if (!blockread(dev_phone, dev_buffer, &bufpos, &buflen, &pos, b->data,
if (!block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
bs, bs)) {
free(b->data);
free(b);
/trunk/uspace/lib/libblock/libblock.h
67,14 → 67,14
void *data;
} block_t;
 
extern int dev_phone; /* FIXME */
extern void *dev_buffer; /* FIXME */
extern int block_init(dev_handle_t, size_t, off_t, size_t);
extern void block_fini(dev_handle_t);
extern void *block_bb_get(dev_handle_t);
 
extern block_t *block_get(dev_handle_t, off_t, size_t);
extern void block_put(block_t *);
 
extern bool blockread(int, void *, off_t *, size_t *, off_t *, void *, size_t,
size_t);
extern bool block_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t);
 
#endif
 
/trunk/uspace/lib/libc/include/errno.h
46,6 → 46,7
#define EBADF (-262)
#define ERANGE (-263)
#define EXDEV (-264)
#define EIO (-265)
 
#endif
 
/trunk/uspace/srv/fs/tmpfs/tmpfs_dump.c
38,8 → 38,6
 
#include "tmpfs.h"
#include "../../vfs/vfs.h"
#include <ipc/ipc.h>
#include <async.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
46,9 → 44,6
#include <sys/types.h>
#include <as.h>
#include <libblock.h>
#include <ipc/services.h>
#include <ipc/devmap.h>
#include <sys/mman.h>
#include <byteorder.h>
 
#define TMPFS_BLOCK_SIZE 1024
59,8 → 54,8
} __attribute__((packed));
 
static bool
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen,
off_t *pos, tmpfs_dentry_t *parent)
tmpfs_restore_recursion(int dev, off_t *bufpos, size_t *buflen, off_t *pos,
tmpfs_dentry_t *parent)
{
struct rdentry entry;
libfs_ops_t *ops = &tmpfs_libfs_ops;
70,8 → 65,8
tmpfs_dentry_t *node;
uint32_t size;
if (!blockread(phone, block, bufpos, buflen, pos, &entry,
sizeof(entry), TMPFS_BLOCK_SIZE))
if (!block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
TMPFS_BLOCK_SIZE))
return false;
entry.len = uint32_t_le2host(entry.len);
90,7 → 85,7
return false;
}
if (!blockread(phone, block, bufpos, buflen, pos, fname,
if (!block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE)) {
ops->destroy((void *) node);
free(fname);
105,7 → 100,7
}
free(fname);
if (!blockread(phone, block, bufpos, buflen, pos, &size,
if (!block_read(dev, bufpos, buflen, pos, &size,
sizeof(size), TMPFS_BLOCK_SIZE))
return false;
116,8 → 111,8
return false;
node->size = size;
if (!blockread(phone, block, bufpos, buflen, pos,
node->data, size, TMPFS_BLOCK_SIZE))
if (!block_read(dev, bufpos, buflen, pos, node->data,
size, TMPFS_BLOCK_SIZE))
return false;
break;
132,8 → 127,8
return false;
}
if (!blockread(phone, block, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE)) {
if (!block_read(dev, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
ops->destroy((void *) node);
free(fname);
return false;
147,8 → 142,8
}
free(fname);
if (!tmpfs_restore_recursion(phone, block, bufpos,
buflen, pos, node))
if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
node))
return false;
break;
163,31 → 158,18
bool tmpfs_restore(dev_handle_t dev)
{
libfs_ops_t *ops = &tmpfs_libfs_ops;
int rc;
 
void *block = mmap(NULL, TMPFS_BLOCK_SIZE,
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
rc = block_init(dev, TMPFS_BLOCK_SIZE, 0, 0);
if (rc != EOK)
return false;
if (block == NULL)
return false;
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev);
 
if (phone < 0) {
munmap(block, TMPFS_BLOCK_SIZE);
return false;
}
if (ipc_share_out_start(phone, block, AS_AREA_READ | AS_AREA_WRITE) !=
EOK)
goto error;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = 0;
char tag[6];
if (!blockread(phone, block, &bufpos, &buflen, &pos, tag, 5,
if (!block_read(dev, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE))
goto error;
195,17 → 177,15
if (strcmp(tag, "TMPFS") != 0)
goto error;
if (!tmpfs_restore_recursion(phone, block, &bufpos, &buflen, &pos,
if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos,
ops->root_get(dev)))
goto error;
ipc_hangup(phone);
munmap(block, TMPFS_BLOCK_SIZE);
block_fini(dev);
return true;
error:
ipc_hangup(phone);
munmap(block, TMPFS_BLOCK_SIZE);
block_fini(dev);
return false;
}
 
/trunk/uspace/srv/fs/tmpfs/Makefile
38,9 → 38,9
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX)
 
LIBS = \
$(LIBC_PREFIX)/libc.a \
$(LIBFS_PREFIX)/libfs.a \
$(LIBBLOCK_PREFIX)/libblock.a
$(LIBBLOCK_PREFIX)/libblock.a \
$(LIBC_PREFIX)/libc.a
 
## Sources
#
/trunk/uspace/srv/fs/fat/fat.h
121,8 → 121,6
};
} __attribute__ ((packed)) fat_bs_t;
 
#define FAT_BS(b) ((fat_bs_t *)((b)->data))
 
typedef enum {
FAT_INVALID,
FAT_DIRECTORY,
/trunk/uspace/srv/fs/fat/fat_ops.c
75,7 → 75,8
 
static void fat_node_sync(fat_node_t *node)
{
block_t *bb, *b;
block_t *b;
fat_bs_t *bs;
fat_dentry_t *d;
uint16_t bps;
unsigned dps;
82,12 → 83,12
assert(node->dirty);
 
bb = block_get(node->idx->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
bs = block_bb_get(node->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(bb->data, node->idx->dev_handle, node->idx->pfc,
b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc,
(node->idx->pdi * sizeof(fat_dentry_t)) / bps);
 
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
99,7 → 100,6
b->dirty = true; /* need to sync block */
block_put(b);
block_put(bb);
}
 
/** Internal version of fat_node_get().
108,7 → 108,8
*/
static void *fat_node_get_core(fat_idx_t *idxp)
{
block_t *bb, *b;
block_t *b;
fat_bs_t *bs;
fat_dentry_t *d;
fat_node_t *nodep = NULL;
unsigned bps;
161,12 → 162,12
}
fat_node_initialize(nodep);
 
bb = block_get(idxp->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
bs = block_bb_get(idxp->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
 
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(bb->data, idxp->dev_handle, idxp->pfc,
b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc,
(idxp->pdi * sizeof(fat_dentry_t)) / bps);
assert(b);
 
183,7 → 184,7
* defined for the directory entry type. We must determine the
* size of the directory by walking the FAT.
*/
nodep->size = bps * _fat_blcks_get(bb->data, idxp->dev_handle,
nodep->size = bps * _fat_blcks_get(bs, idxp->dev_handle,
uint16_t_le2host(d->firstc), NULL);
} else {
nodep->type = FAT_FILE;
194,7 → 195,6
nodep->refcnt = 1;
 
block_put(b);
block_put(bb);
 
/* Link the idx structure with the node structure. */
nodep->idx = idxp;
253,6 → 253,7
 
static void *fat_match(void *prnt, const char *component)
{
fat_bs_t *bs;
fat_node_t *parentp = (fat_node_t *)prnt;
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
unsigned i, j;
260,15 → 261,15
unsigned dps; /* dentries per sector */
unsigned blocks;
fat_dentry_t *d;
block_t *bb, *b;
block_t *b;
 
futex_down(&parentp->idx->lock);
bb = block_get(parentp->idx->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
blocks = parentp->size / bps;
for (i = 0; i < blocks; i++) {
b = fat_block_get(bb->data, parentp, i);
b = fat_block_get(bs, parentp, i);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
276,7 → 277,6
continue;
case FAT_DENTRY_LAST:
block_put(b);
block_put(bb);
futex_up(&parentp->idx->lock);
return NULL;
default:
303,19 → 303,16
* run out of 32-bit indices.
*/
block_put(b);
block_put(bb);
return NULL;
}
node = fat_node_get_core(idx);
futex_up(&idx->lock);
block_put(b);
block_put(bb);
return node;
}
}
block_put(b);
}
block_put(bb);
 
futex_up(&parentp->idx->lock);
return NULL;
341,11 → 338,12
 
static bool fat_has_children(void *node)
{
fat_bs_t *bs;
fat_node_t *nodep = (fat_node_t *)node;
unsigned bps;
unsigned dps;
unsigned blocks;
block_t *bb, *b;
block_t *b;
unsigned i, j;
 
if (nodep->type != FAT_DIRECTORY)
352,8 → 350,8
return false;
futex_down(&nodep->idx->lock);
bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
bs = block_bb_get(nodep->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
 
blocks = nodep->size / bps;
361,7 → 359,7
for (i = 0; i < blocks; i++) {
fat_dentry_t *d;
b = fat_block_get(bb->data, nodep, i);
b = fat_block_get(bs, nodep, i);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
369,24 → 367,20
continue;
case FAT_DENTRY_LAST:
block_put(b);
block_put(bb);
futex_up(&nodep->idx->lock);
return false;
default:
case FAT_DENTRY_VALID:
block_put(b);
block_put(bb);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
block_put(bb);
futex_up(&nodep->idx->lock);
return true;
}
block_put(b);
}
block_put(bb);
 
futex_up(&nodep->idx->lock);
return false;
434,50 → 428,27
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
block_t *bb;
fat_bs_t *bs;
uint16_t bps;
uint16_t rde;
int rc;
 
/*
* For now, we don't bother to remember dev_handle, dev_phone or
* dev_buffer in some data structure. We use global variables because we
* know there will be at most one mount on this file system.
* Of course, this is a huge TODO item.
*/
dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (!dev_buffer) {
ipc_answer_0(rid, ENOMEM);
return;
}
 
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
if (dev_phone < 0) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, dev_phone);
return;
}
 
rc = ipc_share_out_start(dev_phone, dev_buffer,
AS_AREA_READ | AS_AREA_WRITE);
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE, BS_BLOCK * BS_SIZE, BS_SIZE);
if (rc != EOK) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, rc);
ipc_answer_0(rid, 0);
return;
}
 
/* get the buffer with the boot sector */
bs = block_bb_get(dev_handle);
/* Read the number of root directory entries. */
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);
block_put(bb);
bps = uint16_t_le2host(bs->bps);
rde = uint16_t_le2host(bs->root_ent_max);
 
if (bps != BS_SIZE) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
ipc_answer_0(rid, ENOTSUP);
return;
}
484,7 → 455,7
 
rc = fat_idx_init_by_dev_handle(dev_handle);
if (rc != EOK) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
ipc_answer_0(rid, rc);
return;
}
492,7 → 463,7
/* Initialize the root node. */
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
501,7 → 472,7
 
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
if (!ridxp) {
munmap(dev_buffer, BS_SIZE);
block_fini(dev_handle);
free(rootp);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
539,9 → 510,10
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
off_t pos = (off_t)IPC_GET_ARG3(*request);
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
fat_bs_t *bs;
uint16_t bps;
size_t bytes;
block_t *bb, *b;
block_t *b;
 
if (!nodep) {
ipc_answer_0(rid, ENOENT);
557,8 → 529,8
return;
}
 
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
 
if (nodep->type == FAT_FILE) {
/*
567,7 → 539,7
* requested. This keeps the code very simple.
*/
bytes = min(len, bps - pos % bps);
b = fat_block_get(bb->data, nodep, pos / bps);
b = fat_block_get(bs, nodep, pos / bps);
(void) ipc_data_read_finalize(callid, b->data + pos % bps,
bytes);
block_put(b);
591,7 → 563,7
while (bnum < nodep->size / bps) {
off_t o;
 
b = fat_block_get(bb->data, nodep, bnum);
b = fat_block_get(bs, nodep, bnum);
for (o = pos % (bps / sizeof(fat_dentry_t));
o < bps / sizeof(fat_dentry_t);
o++, pos++) {
614,7 → 586,6
}
miss:
fat_node_put(nodep);
block_put(bb);
ipc_answer_0(callid, ENOENT);
ipc_answer_1(rid, ENOENT, 0);
return;
624,7 → 595,6
}
 
fat_node_put(nodep);
block_put(bb);
ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
}
 
634,8 → 604,9
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
off_t pos = (off_t)IPC_GET_ARG3(*request);
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
fat_bs_t *bs;
size_t bytes;
block_t *b, *bb;
block_t *b;
uint16_t bps;
unsigned spc;
off_t boundary;
670,9 → 641,9
*/
bytes = min(len, bps - pos % bps);
 
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
spc = FAT_BS(bb)->spc;
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
boundary = ROUND_UP(nodep->size, bps * spc);
if (pos < boundary) {
682,8 → 653,8
* the limits of the last cluster. The node size may grow to the
* next block size boundary.
*/
fat_fill_gap(bb->data, nodep, FAT_CLST_RES0, pos);
b = fat_block_get(bb->data, nodep, pos / bps);
fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos);
b = fat_block_get(bs, nodep, pos / bps);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
b->dirty = true; /* need to sync block */
693,7 → 664,6
nodep->dirty = true; /* need to sync node */
}
fat_node_put(nodep);
block_put(bb);
ipc_answer_1(rid, EOK, bytes);
return;
} else {
708,19 → 678,18
nclsts = (ROUND_UP(pos + bytes, bps * spc) - boundary) /
bps * spc;
/* create an independent chain of nclsts clusters in all FATs */
status = fat_alloc_clusters(bb->data, dev_handle, nclsts, &mcl,
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl,
&lcl);
if (status != EOK) {
/* could not allocate a chain of nclsts clusters */
fat_node_put(nodep);
block_put(bb);
ipc_answer_0(callid, status);
ipc_answer_0(rid, status);
return;
}
/* zero fill any gaps */
fat_fill_gap(bb->data, nodep, mcl, pos);
b = _fat_block_get(bb->data, dev_handle, lcl,
fat_fill_gap(bs, nodep, mcl, pos);
b = _fat_block_get(bs, dev_handle, lcl,
(pos / bps) % spc);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
730,11 → 699,10
* Append the cluster chain starting in mcl to the end of the
* node's cluster chain.
*/
fat_append_clusters(bb->data, nodep, mcl);
fat_append_clusters(bs, nodep, mcl);
nodep->size = pos + bytes;
nodep->dirty = true; /* need to sync node */
fat_node_put(nodep);
block_put(bb);
ipc_answer_1(rid, EOK, bytes);
return;
}
/trunk/uspace/srv/fs/fat/Makefile
38,9 → 38,9
CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX)
 
LIBS = \
$(LIBC_PREFIX)/libc.a \
$(LIBFS_PREFIX)/libfs.a \
$(LIBBLOCK_PREFIX)/libblock.a
$(LIBBLOCK_PREFIX)/libblock.a \
$(LIBC_PREFIX)/libc.a
 
## Sources
#