Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3530 → Rev 3526

/trunk/uspace/srv/fs/fat/fat_ops.c
75,8 → 75,7
 
static void fat_node_sync(fat_node_t *node)
{
block_t *b;
fat_bs_t *bs;
block_t *bb, *b;
fat_dentry_t *d;
uint16_t bps;
unsigned dps;
83,12 → 82,12
assert(node->dirty);
 
bs = block_bb_get(node->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
bb = block_get(node->idx->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
dps = bps / sizeof(fat_dentry_t);
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc,
b = _fat_block_get(bb->data, 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);
100,6 → 99,7
b->dirty = true; /* need to sync block */
block_put(b);
block_put(bb);
}
 
/** Internal version of fat_node_get().
108,8 → 108,7
*/
static void *fat_node_get_core(fat_idx_t *idxp)
{
block_t *b;
fat_bs_t *bs;
block_t *bb, *b;
fat_dentry_t *d;
fat_node_t *nodep = NULL;
unsigned bps;
162,12 → 161,12
}
fat_node_initialize(nodep);
 
bs = block_bb_get(idxp->dev_handle);
bps = uint16_t_le2host(bs->bps);
bb = block_get(idxp->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
dps = bps / sizeof(fat_dentry_t);
 
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc,
b = _fat_block_get(bb->data, idxp->dev_handle, idxp->pfc,
(idxp->pdi * sizeof(fat_dentry_t)) / bps);
assert(b);
 
184,7 → 183,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(bs, idxp->dev_handle,
nodep->size = bps * _fat_blcks_get(bb->data, idxp->dev_handle,
uint16_t_le2host(d->firstc), NULL);
} else {
nodep->type = FAT_FILE;
195,6 → 194,7
nodep->refcnt = 1;
 
block_put(b);
block_put(bb);
 
/* Link the idx structure with the node structure. */
nodep->idx = idxp;
253,7 → 253,6
 
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;
261,15 → 260,15
unsigned dps; /* dentries per sector */
unsigned blocks;
fat_dentry_t *d;
block_t *b;
block_t *bb, *b;
 
futex_down(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
bb = block_get(parentp->idx->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
dps = bps / sizeof(fat_dentry_t);
blocks = parentp->size / bps;
for (i = 0; i < blocks; i++) {
b = fat_block_get(bs, parentp, i);
b = fat_block_get(bb->data, parentp, i);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
277,6 → 276,7
continue;
case FAT_DENTRY_LAST:
block_put(b);
block_put(bb);
futex_up(&parentp->idx->lock);
return NULL;
default:
303,16 → 303,19
* 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;
338,12 → 341,11
 
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 *b;
block_t *bb, *b;
unsigned i, j;
 
if (nodep->type != FAT_DIRECTORY)
350,8 → 352,8
return false;
futex_down(&nodep->idx->lock);
bs = block_bb_get(nodep->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
dps = bps / sizeof(fat_dentry_t);
 
blocks = nodep->size / bps;
359,7 → 361,7
for (i = 0; i < blocks; i++) {
fat_dentry_t *d;
b = fat_block_get(bs, nodep, i);
b = fat_block_get(bb->data, nodep, i);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
367,20 → 369,24
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;
428,27 → 434,50
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fat_bs_t *bs;
block_t *bb;
uint16_t bps;
uint16_t rde;
int rc;
 
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE, BS_BLOCK * BS_SIZE, BS_SIZE);
/*
* 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);
if (rc != EOK) {
ipc_answer_0(rid, 0);
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, rc);
return;
}
 
/* get the buffer with the boot sector */
bs = block_bb_get(dev_handle);
/* Read the number of root directory entries. */
bps = uint16_t_le2host(bs->bps);
rde = uint16_t_le2host(bs->root_ent_max);
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);
 
if (bps != BS_SIZE) {
block_fini(dev_handle);
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, ENOTSUP);
return;
}
455,7 → 484,7
 
rc = fat_idx_init_by_dev_handle(dev_handle);
if (rc != EOK) {
block_fini(dev_handle);
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, rc);
return;
}
463,7 → 492,7
/* Initialize the root node. */
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
block_fini(dev_handle);
munmap(dev_buffer, BS_SIZE);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
472,7 → 501,7
 
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
if (!ridxp) {
block_fini(dev_handle);
munmap(dev_buffer, BS_SIZE);
free(rootp);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
510,10 → 539,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;
uint16_t bps;
size_t bytes;
block_t *b;
block_t *bb, *b;
 
if (!nodep) {
ipc_answer_0(rid, ENOENT);
529,8 → 557,8
return;
}
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
 
if (nodep->type == FAT_FILE) {
/*
539,7 → 567,7
* requested. This keeps the code very simple.
*/
bytes = min(len, bps - pos % bps);
b = fat_block_get(bs, nodep, pos / bps);
b = fat_block_get(bb->data, nodep, pos / bps);
(void) ipc_data_read_finalize(callid, b->data + pos % bps,
bytes);
block_put(b);
563,7 → 591,7
while (bnum < nodep->size / bps) {
off_t o;
 
b = fat_block_get(bs, nodep, bnum);
b = fat_block_get(bb->data, nodep, bnum);
for (o = pos % (bps / sizeof(fat_dentry_t));
o < bps / sizeof(fat_dentry_t);
o++, pos++) {
586,6 → 614,7
}
miss:
fat_node_put(nodep);
block_put(bb);
ipc_answer_0(callid, ENOENT);
ipc_answer_1(rid, ENOENT, 0);
return;
595,6 → 624,7
}
 
fat_node_put(nodep);
block_put(bb);
ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
}
 
604,9 → 634,8
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;
block_t *b, *bb;
uint16_t bps;
unsigned spc;
off_t boundary;
641,9 → 670,9
*/
bytes = min(len, bps - pos % bps);
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
spc = FAT_BS(bb)->spc;
boundary = ROUND_UP(nodep->size, bps * spc);
if (pos < boundary) {
653,8 → 682,8
* the limits of the last cluster. The node size may grow to the
* next block size boundary.
*/
fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos);
b = fat_block_get(bs, nodep, pos / bps);
fat_fill_gap(bb->data, nodep, FAT_CLST_RES0, pos);
b = fat_block_get(bb->data, nodep, pos / bps);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
b->dirty = true; /* need to sync block */
664,6 → 693,7
nodep->dirty = true; /* need to sync node */
}
fat_node_put(nodep);
block_put(bb);
ipc_answer_1(rid, EOK, bytes);
return;
} else {
678,18 → 708,19
nclsts = (ROUND_UP(pos + bytes, bps * spc) - boundary) /
bps * spc;
/* create an independent chain of nclsts clusters in all FATs */
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl,
status = fat_alloc_clusters(bb->data, 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(bs, nodep, mcl, pos);
b = _fat_block_get(bs, dev_handle, lcl,
fat_fill_gap(bb->data, nodep, mcl, pos);
b = _fat_block_get(bb->data, dev_handle, lcl,
(pos / bps) % spc);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
699,10 → 730,11
* Append the cluster chain starting in mcl to the end of the
* node's cluster chain.
*/
fat_append_clusters(bs, nodep, mcl);
fat_append_clusters(bb->data, 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/fat.h
121,6 → 121,8
};
} __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/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 \
$(LIBC_PREFIX)/libc.a
$(LIBBLOCK_PREFIX)/libblock.a
 
## Sources
#