Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3596 → Rev 3597

/branches/tracing/uspace/app/debug/main.c
113,7 → 113,7
int rc;
 
/* Spawn a program loader */
ldr = loader_spawn();
ldr = loader_spawn(path);
if (ldr == NULL)
return 0;
 
/branches/tracing/uspace/app/tester/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/app/tetris/Makefile
1,3 → 1,5
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/app/klog/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/app/trace/trace.c
516,7 → 516,7
int rc;
 
/* Spawn a program loader */
ldr = loader_spawn();
ldr = loader_spawn(path);
if (ldr == NULL)
return 0;
 
/branches/tracing/uspace/app/trace/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/lib/libfs/libfs.c
191,7 → 191,7
}
void *nodep;
if (lflag & L_CREATE)
nodep = ops->create(lflag);
nodep = ops->create(dev_handle, lflag);
else
nodep = ops->node_get(dev_handle,
index);
262,7 → 262,7
void *nodep;
if (lflag & L_CREATE)
nodep = ops->create(lflag);
nodep = ops->create(dev_handle, lflag);
else
nodep = ops->node_get(dev_handle, index);
if (nodep) {
/branches/tracing/uspace/lib/libfs/libfs.h
45,7 → 45,7
void * (* match)(void *, const char *);
void * (* node_get)(dev_handle_t, fs_index_t);
void (* node_put)(void *);
void * (* create)(int);
void * (* create)(dev_handle_t, int);
int (* destroy)(void *);
bool (* link)(void *, void *, const char *);
int (* unlink)(void *, void *);
/branches/tracing/uspace/lib/libfs/Makefile
30,6 → 30,8
## Common compiler flags
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../libc
## Setup toolchain
#
/branches/tracing/uspace/lib/libblock/libblock.c
48,6 → 48,7
#include <assert.h>
#include <futex.h>
#include <libadt/list.h>
#include <libadt/hash_table.h>
 
/** Lock protecting the device connection list */
static futex_t dcl_lock = FUTEX_INITIALIZER;
54,7 → 55,18
/** Device connection list head. */
static LIST_INITIALIZE(dcl_head);
 
#define CACHE_BUCKETS_LOG2 10
#define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2)
 
typedef struct {
futex_t lock;
size_t block_size; /**< Block size. */
unsigned block_count; /**< Total number of blocks. */
hash_table_t block_hash;
link_t free_head;
} cache_t;
 
typedef struct {
link_t link;
int dev_handle;
int dev_phone;
63,6 → 75,7
void *bb_buf;
off_t bb_off;
size_t bb_size;
cache_t *cache;
} devcon_t;
 
static devcon_t *devcon_search(dev_handle_t dev_handle)
82,7 → 95,7
}
 
static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
size_t com_size, void *bb_buf, off_t bb_off, size_t bb_size)
size_t com_size)
{
link_t *cur;
devcon_t *devcon;
96,9 → 109,10
devcon->dev_phone = dev_phone;
devcon->com_area = com_area;
devcon->com_size = com_size;
devcon->bb_buf = bb_buf;
devcon->bb_off = bb_off;
devcon->bb_size = bb_size;
devcon->bb_buf = NULL;
devcon->bb_off = 0;
devcon->bb_size = 0;
devcon->cache = NULL;
 
futex_down(&dcl_lock);
for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
121,23 → 135,15
futex_up(&dcl_lock);
}
 
int
block_init(dev_handle_t dev_handle, size_t com_size, off_t bb_off,
size_t bb_size)
int block_init(dev_handle_t dev_handle, size_t com_size)
{
int rc;
int dev_phone;
void *com_area;
void *bb_buf;
bb_buf = malloc(bb_size);
if (!bb_buf)
return ENOMEM;
com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (!com_area) {
free(bb_buf);
return ENOMEM;
}
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
144,7 → 150,6
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
if (dev_phone < 0) {
free(bb_buf);
munmap(com_area, com_size);
return dev_phone;
}
152,29 → 157,18
rc = ipc_share_out_start(dev_phone, com_area,
AS_AREA_READ | AS_AREA_WRITE);
if (rc != EOK) {
free(bb_buf);
munmap(com_area, com_size);
ipc_hangup(dev_phone);
return rc;
}
rc = devcon_add(dev_handle, dev_phone, com_area, com_size, bb_buf,
bb_off, bb_size);
rc = devcon_add(dev_handle, dev_phone, com_area, com_size);
if (rc != EOK) {
free(bb_buf);
munmap(com_area, com_size);
ipc_hangup(dev_phone);
return rc;
}
 
off_t bufpos = 0;
size_t buflen = 0;
if (!block_read(dev_handle, &bufpos, &buflen, &bb_off,
bb_buf, bb_size, bb_size)) {
block_fini(dev_handle);
return EIO; /* XXX real error code */
}
return EOK;
}
 
185,7 → 179,14
devcon_remove(devcon);
 
free(devcon->bb_buf);
if (devcon->bb_buf)
free(devcon->bb_buf);
 
if (devcon->cache) {
hash_table_destroy(&devcon->cache->block_hash);
free(devcon->cache);
}
 
munmap(devcon->com_area, devcon->com_size);
ipc_hangup(devcon->dev_phone);
 
192,6 → 193,35
free(devcon);
}
 
int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size)
{
void *bb_buf;
int rc;
 
devcon_t *devcon = devcon_search(dev_handle);
if (!devcon)
return ENOENT;
if (devcon->bb_buf)
return EEXIST;
bb_buf = malloc(size);
if (!bb_buf)
return ENOMEM;
off_t bufpos = 0;
size_t buflen = 0;
rc = block_read(dev_handle, &bufpos, &buflen, &off,
bb_buf, size, size);
if (rc != EOK) {
free(bb_buf);
return rc;
}
devcon->bb_buf = bb_buf;
devcon->bb_off = off;
devcon->bb_size = size;
 
return EOK;
}
 
void *block_bb_get(dev_handle_t dev_handle)
{
devcon_t *devcon = devcon_search(dev_handle);
199,6 → 229,208
return devcon->bb_buf;
}
 
static hash_index_t cache_hash(unsigned long *key)
{
return *key & (CACHE_BUCKETS - 1);
}
 
static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item)
{
block_t *b = hash_table_get_instance(item, block_t, hash_link);
return b->boff == *key;
}
 
static void cache_remove_callback(link_t *item)
{
}
 
static hash_table_operations_t cache_ops = {
.hash = cache_hash,
.compare = cache_compare,
.remove_callback = cache_remove_callback
};
 
int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks)
{
devcon_t *devcon = devcon_search(dev_handle);
cache_t *cache;
if (!devcon)
return ENOENT;
if (devcon->cache)
return EEXIST;
cache = malloc(sizeof(cache_t));
if (!cache)
return ENOMEM;
futex_initialize(&cache->lock, 1);
list_initialize(&cache->free_head);
cache->block_size = size;
cache->block_count = blocks;
 
if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
&cache_ops)) {
free(cache);
return ENOMEM;
}
 
devcon->cache = cache;
return EOK;
}
 
static bool cache_can_grow(cache_t *cache)
{
return true;
}
 
static void block_initialize(block_t *b)
{
futex_initialize(&b->lock, 1);
b->refcnt = 1;
b->dirty = false;
rwlock_initialize(&b->contents_lock);
link_initialize(&b->free_link);
link_initialize(&b->hash_link);
}
 
/** Instantiate a block in memory and get a reference to it.
*
* @param dev_handle Device handle of the block device.
* @param boff Block offset.
* @param flags If BLOCK_FLAGS_NOREAD is specified, block_get()
* will not read the contents of the block from the
* device.
*
* @return Block structure.
*/
block_t *block_get(dev_handle_t dev_handle, bn_t boff, int flags)
{
devcon_t *devcon;
cache_t *cache;
block_t *b;
link_t *l;
unsigned long key = boff;
devcon = devcon_search(dev_handle);
 
assert(devcon);
assert(devcon->cache);
cache = devcon->cache;
futex_down(&cache->lock);
l = hash_table_find(&cache->block_hash, &key);
if (l) {
/*
* We found the block in the cache.
*/
b = hash_table_get_instance(l, block_t, hash_link);
futex_down(&b->lock);
if (b->refcnt++ == 0)
list_remove(&b->free_link);
futex_up(&b->lock);
futex_up(&cache->lock);
} else {
/*
* The block was not found in the cache.
*/
int rc;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = boff * cache->block_size;
bool sync = false;
 
if (cache_can_grow(cache)) {
/*
* We can grow the cache by allocating new blocks.
* Should the allocation fail, we fail over and try to
* recycle a block from the cache.
*/
b = malloc(sizeof(block_t));
if (!b)
goto recycle;
b->data = malloc(cache->block_size);
if (!b->data) {
free(b);
goto recycle;
}
} else {
/*
* Try to recycle a block from the free list.
*/
unsigned long temp_key;
recycle:
assert(!list_empty(&cache->free_head));
l = cache->free_head.next;
list_remove(l);
b = hash_table_get_instance(l, block_t, hash_link);
sync = b->dirty;
temp_key = b->boff;
hash_table_remove(&cache->block_hash, &temp_key, 1);
}
 
block_initialize(b);
b->dev_handle = dev_handle;
b->size = cache->block_size;
b->boff = boff;
hash_table_insert(&cache->block_hash, &key, &b->hash_link);
 
/*
* Lock the block before releasing the cache lock. Thus we don't
* kill concurent operations on the cache while doing I/O on the
* block.
*/
futex_down(&b->lock);
futex_up(&cache->lock);
 
if (sync) {
/*
* The block is dirty and needs to be written back to
* the device before we can read in the new contents.
*/
abort(); /* TODO: block_write() */
}
if (!(flags & BLOCK_FLAGS_NOREAD)) {
/*
* The block contains old or no data. We need to read
* the new contents from the device.
*/
rc = block_read(dev_handle, &bufpos, &buflen, &pos,
b->data, cache->block_size, cache->block_size);
assert(rc == EOK);
}
 
futex_up(&b->lock);
}
return b;
}
 
/** Release a reference to a block.
*
* If the last reference is dropped, the block is put on the free list.
*
* @param block Block of which a reference is to be released.
*/
void block_put(block_t *block)
{
devcon_t *devcon = devcon_search(block->dev_handle);
cache_t *cache;
 
assert(devcon);
assert(devcon->cache);
 
cache = devcon->cache;
futex_down(&cache->lock);
futex_down(&block->lock);
if (!--block->refcnt) {
/*
* Last reference to the block was dropped, put the block on the
* free list.
*/
list_append(&block->free_link, &cache->free_head);
}
futex_up(&block->lock);
futex_up(&cache->lock);
}
 
/** Read data from a block device.
*
* @param dev_handle Device handle of the block device.
211,9 → 443,9
* @param size Size of the destination buffer.
* @param block_size Block size to be used for the transfer.
*
* @return True on success, false on failure.
* @return EOK on success or a negative return code on failure.
*/
bool
int
block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst,
size_t size, size_t block_size)
{
248,7 → 480,7
int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
*pos / block_size, block_size, &retval);
if ((rc != EOK) || (retval != EOK))
return false;
return (rc != EOK ? rc : retval);
*bufpos = 0;
*buflen = block_size;
255,44 → 487,8
}
}
return true;
return EOK;
}
 
block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
{
/* FIXME */
block_t *b;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = offset * bs;
 
b = malloc(sizeof(block_t));
if (!b)
return NULL;
b->data = malloc(bs);
if (!b->data) {
free(b);
return NULL;
}
b->size = bs;
 
if (!block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
bs, bs)) {
free(b->data);
free(b);
return NULL;
}
 
return b;
}
 
void block_put(block_t *block)
{
/* FIXME */
free(block->data);
free(block);
}
 
/** @}
*/
/branches/tracing/uspace/lib/libblock/libblock.h
44,6 → 44,24
#include <libadt/hash_table.h>
#include <libadt/list.h>
 
/*
* Flags that can be used with block_get().
*/
 
/**
* This macro is a symbolic value for situations where no special flags are
* needed.
*/
#define BLOCK_FLAGS_NONE 0
 
/**
* When the client of block_get() intends to overwrite the current contents of
* the block, this flag is used to avoid the unnecessary read.
*/
#define BLOCK_FLAGS_NOREAD 1
 
typedef unsigned bn_t; /**< Block number type. */
 
typedef struct block {
/** Futex protecting the reference count. */
futex_t lock;
56,7 → 74,7
/** Handle of the device where the block resides. */
dev_handle_t dev_handle;
/** Block offset on the block device. Counted in 'size'-byte blocks. */
off_t boff;
bn_t boff;
/** Size of the block. */
size_t size;
/** Link for placing the block into the free block list. */
67,14 → 85,18
void *data;
} block_t;
 
extern int block_init(dev_handle_t, size_t, off_t, size_t);
extern int block_init(dev_handle_t, size_t);
extern void block_fini(dev_handle_t);
 
extern int block_bb_read(dev_handle_t, off_t, size_t);
extern void *block_bb_get(dev_handle_t);
 
extern block_t *block_get(dev_handle_t, off_t, size_t);
extern int block_cache_init(dev_handle_t, size_t, unsigned);
 
extern block_t *block_get(dev_handle_t, bn_t, int flags);
extern void block_put(block_t *);
 
extern bool block_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t);
extern int block_read(int, off_t *, size_t *, off_t *, void *, size_t, size_t);
 
#endif
 
/branches/tracing/uspace/lib/libblock/Makefile
30,6 → 30,8
## Common compiler flags
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../libc
## Setup toolchain
#
/branches/tracing/uspace/lib/softfloat/Makefile
29,6 → 29,8
## Common compiler flags
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../libc
## Setup toolchain
#
/branches/tracing/uspace/lib/softint/Makefile
29,6 → 29,8
## Common compiler flags
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../libc
## Setup toolchain
#
/branches/tracing/uspace/lib/libc/include/loader/loader.h
44,7 → 44,7
int phone_id;
} loader_t;
 
extern loader_t *loader_spawn(void);
extern loader_t *loader_spawn(char *name);
extern int loader_get_task_id(loader_t *, task_id_t *);
extern int loader_set_pathname(loader_t *, const char *);
extern int loader_set_args(loader_t *, char *const []);
/branches/tracing/uspace/lib/libc/generic/task.c
64,7 → 64,7
int rc;
 
/* Spawn a program loader. */
ldr = loader_spawn();
ldr = loader_spawn(path);
if (ldr == NULL)
return 0;
 
/branches/tracing/uspace/lib/libc/generic/loader.c
46,10 → 46,11
/** Connect to a new program loader.
*
* Spawns a new program loader task and returns the connection structure.
* @param name Symbolic name to set on the newly created task.
* @return Pointer to the loader connection structure (should be
* de-allocated using free() after use).
*/
loader_t *loader_spawn(void)
loader_t *loader_spawn(char *name)
{
int phone_id, rc;
loader_t *ldr;
57,7 → 58,8
/*
* Ask kernel to spawn a new loader task.
*/
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
rc = __SYSCALL3(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id,
(sysarg_t) name, strlen(name));
if (rc != 0)
return NULL;
 
/branches/tracing/uspace/lib/libc/generic/thread.c
108,8 → 108,8
uarg->uspace_thread_arg = arg;
uarg->uspace_uarg = uarg;
rc = __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name,
(sysarg_t) tid);
rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name,
(sysarg_t) strlen(name), (sysarg_t) tid);
if (rc) {
/*
/branches/tracing/uspace/lib/libc/Makefile
29,6 → 29,8
## Common compiler flags
#
 
include ../../Makefile.config
 
LIBC_PREFIX = $(shell pwd)
SOFTINT_PREFIX = ../softint
CONSOLE_PREFIX = ../../srv/console
/branches/tracing/uspace/lib/libc/arch/ppc32/src/entry.s
34,11 → 34,12
 
## User-space task entry point
#
# r3 contains the PCB pointer
# r6 contains the PCB pointer
#
__entry:
# Pass the PCB pointer to __main() as the first argument.
# Since the first argument is passed in r3, no operation is needed.
# The first argument is passed in r3.
mr %r3, %r6
bl __main
 
bl __exit
/branches/tracing/uspace/srv/kbd/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/srv/ns/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/srv/console/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/srv/rd/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/srv/loader/main.c
247,7 → 247,7
if (prog_info.interp == NULL) {
/* Statically linked program */
// printf("Run statically linked program\n");
// printf("entry point: 0x%llx\n", prog_info.entry);
// printf("entry point: 0x%lx\n", prog_info.entry);
is_dyn_linked = false;
ipc_answer_0(rid, EOK);
return 0;
285,7 → 285,7
if (is_dyn_linked == true) {
/* Dynamically linked program */
printf("run dynamic linker\n");
printf("entry point: 0x%llx\n", interp_info.entry);
printf("entry point: 0x%lx\n", interp_info.entry);
close_console();
 
ipc_answer_0(rid, EOK);
319,6 → 319,8
callid = async_get_call(&call);
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
exit(0);
case LOADER_GET_TASKID:
loader_get_taskid(callid, &call);
continue;
/branches/tracing/uspace/srv/loader/Makefile
27,7 → 27,6
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
include ../../Makefile.config
 
## Setup toolchain
/branches/tracing/uspace/srv/loader/arch/ppc32/ppc32.s
36,5 → 36,5
# Jump to a program entry point
program_run:
mtctr %r3
mr %r3, %r4 # Pass pcb to the entry point in %r3
mr %r6, %r4 # Pass pcb to the entry point in %r6
bctr
/branches/tracing/uspace/srv/fb/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_dump.c
65,8 → 65,8
tmpfs_dentry_t *node;
uint32_t size;
if (!block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
TMPFS_BLOCK_SIZE))
if (block_read(dev, bufpos, buflen, pos, &entry, sizeof(entry),
TMPFS_BLOCK_SIZE) != EOK)
return false;
entry.len = uint32_t_le2host(entry.len);
79,14 → 79,14
if (fname == NULL)
return false;
node = (tmpfs_dentry_t *) ops->create(L_FILE);
node = (tmpfs_dentry_t *) ops->create(dev, L_FILE);
if (node == NULL) {
free(fname);
return false;
}
if (!block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE)) {
if (block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
100,8 → 100,8
}
free(fname);
if (!block_read(dev, bufpos, buflen, pos, &size,
sizeof(size), TMPFS_BLOCK_SIZE))
if (block_read(dev, bufpos, buflen, pos, &size,
sizeof(size), TMPFS_BLOCK_SIZE) != EOK)
return false;
size = uint32_t_le2host(size);
111,8 → 111,8
return false;
node->size = size;
if (!block_read(dev, bufpos, buflen, pos, node->data,
size, TMPFS_BLOCK_SIZE))
if (block_read(dev, bufpos, buflen, pos, node->data,
size, TMPFS_BLOCK_SIZE) != EOK)
return false;
break;
121,14 → 121,14
if (fname == NULL)
return false;
node = (tmpfs_dentry_t *) ops->create(L_DIRECTORY);
node = (tmpfs_dentry_t *) ops->create(dev, L_DIRECTORY);
if (node == NULL) {
free(fname);
return false;
}
if (!block_read(dev, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
if (block_read(dev, bufpos, buflen, pos, fname,
entry.len, TMPFS_BLOCK_SIZE) != EOK) {
ops->destroy((void *) node);
free(fname);
return false;
160,7 → 160,7
libfs_ops_t *ops = &tmpfs_libfs_ops;
int rc;
 
rc = block_init(dev, TMPFS_BLOCK_SIZE, 0, 0);
rc = block_init(dev, TMPFS_BLOCK_SIZE);
if (rc != EOK)
return false;
169,8 → 169,8
off_t pos = 0;
char tag[6];
if (!block_read(dev, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE))
if (block_read(dev, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE) != EOK)
goto error;
tag[5] = 0;
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_ops.c
64,6 → 64,8
*/
static tmpfs_dentry_t *root;
 
#define TMPFS_DEV 0 /**< Dummy device handle for TMPFS */
 
/*
* Implementation of the libfs interface.
*/
72,7 → 74,7
static void *tmpfs_match(void *, const char *);
static void *tmpfs_node_get(dev_handle_t, fs_index_t);
static void tmpfs_node_put(void *);
static void *tmpfs_create_node(int);
static void *tmpfs_create_node(dev_handle_t, int);
static bool tmpfs_link_node(void *, void *, const char *);
static int tmpfs_unlink_node(void *, void *);
static int tmpfs_destroy_node(void *);
228,7 → 230,7
{
if (!hash_table_create(&dentries, DENTRIES_BUCKETS, 1, &dentries_ops))
return false;
root = (tmpfs_dentry_t *) tmpfs_create_node(L_DIRECTORY);
root = (tmpfs_dentry_t *) tmpfs_create_node(TMPFS_DEV, L_DIRECTORY);
if (!root) {
hash_table_destroy(&dentries);
return false;
282,7 → 284,7
/* nothing to do */
}
 
void *tmpfs_create_node(int lflag)
void *tmpfs_create_node(dev_handle_t dev_handle, int lflag)
{
assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
 
/branches/tracing/uspace/srv/fs/tmpfs/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../../Makefile.config
 
LIBC_PREFIX = ../../../lib/libc
LIBFS_PREFIX = ../../../lib/libfs
LIBBLOCK_PREFIX = ../../../lib/libblock
/branches/tracing/uspace/srv/fs/fat/fat_idx.c
338,6 → 338,52
futex_up(&unused_futex);
}
 
static fat_idx_t *fat_idx_get_new_core(dev_handle_t dev_handle)
{
fat_idx_t *fidx;
 
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
if (!fidx)
return NULL;
if (!fat_idx_alloc(dev_handle, &fidx->index)) {
free(fidx);
return NULL;
}
link_initialize(&fidx->uph_link);
link_initialize(&fidx->uih_link);
futex_initialize(&fidx->lock, 1);
fidx->dev_handle = dev_handle;
fidx->pfc = FAT_CLST_RES0; /* no parent yet */
fidx->pdi = 0;
fidx->nodep = NULL;
 
return fidx;
}
 
fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle)
{
fat_idx_t *fidx;
 
futex_down(&used_futex);
fidx = fat_idx_get_new_core(dev_handle);
if (!fidx) {
futex_up(&used_futex);
return NULL;
}
unsigned long ikey[] = {
[UIH_DH_KEY] = dev_handle,
[UIH_INDEX_KEY] = fidx->index,
};
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
futex_down(&fidx->lock);
futex_up(&used_futex);
 
return fidx;
}
 
fat_idx_t *
fat_idx_get_by_pos(dev_handle_t dev_handle, fat_cluster_t pfc, unsigned pdi)
{
354,16 → 400,11
if (l) {
fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
} else {
fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
fidx = fat_idx_get_new_core(dev_handle);
if (!fidx) {
futex_up(&used_futex);
return NULL;
}
if (!fat_idx_alloc(dev_handle, &fidx->index)) {
free(fidx);
futex_up(&used_futex);
return NULL;
}
unsigned long ikey[] = {
[UIH_DH_KEY] = dev_handle,
370,13 → 411,8
[UIH_INDEX_KEY] = fidx->index,
};
link_initialize(&fidx->uph_link);
link_initialize(&fidx->uih_link);
futex_initialize(&fidx->lock, 1);
fidx->dev_handle = dev_handle;
fidx->pfc = pfc;
fidx->pdi = pdi;
fidx->nodep = NULL;
 
hash_table_insert(&up_hash, pkey, &fidx->uph_link);
hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
/branches/tracing/uspace/srv/fs/fat/fat.h
202,6 → 202,7
extern void fat_lookup(ipc_callid_t, ipc_call_t *);
extern void fat_read(ipc_callid_t, ipc_call_t *);
extern void fat_write(ipc_callid_t, ipc_call_t *);
extern void fat_truncate(ipc_callid_t, ipc_call_t *);
 
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
/branches/tracing/uspace/srv/fs/fat/fat_fat.c
54,125 → 54,109
*/
static futex_t fat_alloc_lock = FUTEX_INITIALIZER;
 
/** Read block from file located on a FAT file system.
/** Walk the cluster chain.
*
* @param bs Buffer holding the boot sector of the file system.
* @param dev_handle Device handle of the file system.
* @param firstc First cluster used by the file. Can be zero if the file
* is empty.
* @param offset Offset in blocks.
* @param bs Buffer holding the boot sector for the file.
* @param dev_handle Device handle of the device with the file.
* @param firstc First cluster to start the walk with.
* @param lastc If non-NULL, output argument hodling the last cluster number visited.
* @param max_clusters Maximum number of clusters to visit.
*
* @return Block structure holding the requested block.
* @return Number of clusters seen during the walk.
*/
block_t *
_fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
off_t offset)
uint16_t
fat_cluster_walk(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
fat_cluster_t *lastc, uint16_t max_clusters)
{
block_t *b;
unsigned bps;
unsigned spc;
unsigned rscnt; /* block address of the first FAT */
unsigned fatcnt;
unsigned rde;
unsigned rds; /* root directory size */
unsigned sf;
unsigned ssa; /* size of the system area */
unsigned clusters;
uint16_t clusters = 0;
fat_cluster_t clst = firstc;
unsigned i;
 
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
rscnt = uint16_t_le2host(bs->rscnt);
fatcnt = bs->fatcnt;
rde = uint16_t_le2host(bs->root_ent_max);
sf = uint16_t_le2host(bs->sec_per_fat);
 
rds = (sizeof(fat_dentry_t) * rde) / bps;
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
ssa = rscnt + fatcnt * sf + rds;
 
if (firstc == FAT_CLST_ROOT) {
/* root directory special case */
assert(offset < rds);
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps);
return b;
if (firstc == FAT_CLST_RES0) {
/* No space allocated to the file. */
if (lastc)
*lastc = firstc;
return 0;
}
 
clusters = offset / spc;
for (i = 0; i < clusters; i++) {
unsigned fsec; /* sector offset relative to FAT1 */
while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
bn_t fsec; /* sector offset relative to FAT1 */
unsigned fidx; /* FAT1 entry index */
 
assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD);
assert(clst >= FAT_CLST_FIRST);
if (lastc)
*lastc = clst; /* remember the last cluster number */
fsec = (clst * sizeof(fat_cluster_t)) / bps;
fidx = clst % (bps / sizeof(fat_cluster_t));
/* read FAT1 */
b = block_get(dev_handle, rscnt + fsec, bps);
b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
assert(clst != FAT_CLST_BAD);
assert(clst < FAT_CLST_LAST1);
block_put(b);
clusters++;
}
 
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc +
offset % spc, bps);
if (lastc && clst < FAT_CLST_LAST1)
*lastc = clst;
 
return b;
return clusters;
}
 
/** Return number of blocks allocated to a file.
/** Read block from file located on a FAT file system.
*
* @param bs Buffer holding the boot sector for the file.
* @param dev_handle Device handle of the device with the file.
* @param firstc First cluster of the file.
* @param lastc If non-NULL, output argument holding the
* last cluster.
* @param bs Buffer holding the boot sector of the file system.
* @param dev_handle Device handle of the file system.
* @param firstc First cluster used by the file. Can be zero if the file
* is empty.
* @param bn Block number.
* @param flags Flags passed to libblock.
*
* @return Number of blocks allocated to the file.
* @return Block structure holding the requested block.
*/
uint16_t
_fat_blcks_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
fat_cluster_t *lastc)
block_t *
_fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
bn_t bn, int flags)
{
block_t *b;
unsigned bps;
unsigned spc;
unsigned rscnt; /* block address of the first FAT */
unsigned clusters = 0;
fat_cluster_t clst = firstc;
unsigned rde;
unsigned rds; /* root directory size */
unsigned sf;
unsigned ssa; /* size of the system area */
unsigned clusters, max_clusters;
fat_cluster_t lastc;
 
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
rscnt = uint16_t_le2host(bs->rscnt);
rde = uint16_t_le2host(bs->root_ent_max);
sf = uint16_t_le2host(bs->sec_per_fat);
 
if (firstc == FAT_CLST_RES0) {
/* No space allocated to the file. */
if (lastc)
*lastc = firstc;
return 0;
rds = (sizeof(fat_dentry_t) * rde) / bps;
rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
ssa = rscnt + bs->fatcnt * sf + rds;
 
if (firstc == FAT_CLST_ROOT) {
/* root directory special case */
assert(bn < rds);
b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags);
return b;
}
 
while (clst < FAT_CLST_LAST1) {
unsigned fsec; /* sector offset relative to FAT1 */
unsigned fidx; /* FAT1 entry index */
max_clusters = bn / bs->spc;
clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc,
max_clusters);
assert(clusters == max_clusters);
 
assert(clst >= FAT_CLST_FIRST);
if (lastc)
*lastc = clst; /* remember the last cluster */
fsec = (clst * sizeof(fat_cluster_t)) / bps;
fidx = clst % (bps / sizeof(fat_cluster_t));
/* read FAT1 */
b = block_get(dev_handle, rscnt + fsec, bps);
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
assert(clst != FAT_CLST_BAD);
block_put(b);
clusters++;
}
b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc +
bn % bs->spc, flags);
 
if (lastc)
*lastc = clst;
return clusters * spc;
return b;
}
 
/** Fill the gap between EOF and a new file position.
200,7 → 184,9
/* zero out already allocated space */
for (o = nodep->size - 1; o < pos && o < boundary;
o = ALIGN_DOWN(o + bps, bps)) {
b = fat_block_get(bs, nodep, o / bps);
int flags = (o % bps == 0) ?
BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE;
b = fat_block_get(bs, nodep, o / bps, flags);
memset(b->data + o % bps, 0, bps - o % bps);
b->dirty = true; /* need to sync node */
block_put(b);
212,7 → 198,7
/* zero out the initial part of the new cluster chain */
for (o = boundary; o < pos; o += bps) {
b = _fat_block_get(bs, nodep->idx->dev_handle, mcl,
(o - boundary) / bps);
(o - boundary) / bps, BLOCK_FLAGS_NOREAD);
memset(b->data, 0, min(bps, pos - o));
b->dirty = true; /* need to sync node */
block_put(b);
219,16 → 205,44
}
}
 
/** Mark cluster in one instance of FAT.
/** Get cluster from the first FAT.
*
* @param bs Buffer holding the boot sector for the file system.
* @param dev_handle Device handle for the file system.
* @param clst Cluster which to get.
*
* @return Value found in the cluster.
*/
fat_cluster_t
fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst)
{
block_t *b;
uint16_t bps;
uint16_t rscnt;
fat_cluster_t *cp, value;
 
bps = uint16_t_le2host(bs->bps);
rscnt = uint16_t_le2host(bs->rscnt);
 
b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps,
BLOCK_FLAGS_NONE);
cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
value = uint16_t_le2host(*cp);
block_put(b);
return value;
}
 
/** Set cluster in one instance of FAT.
*
* @param bs Buffer holding the boot sector for the file system.
* @param dev_handle Device handle for the file system.
* @param fatno Number of the FAT instance where to make the change.
* @param clst Cluster which is to be marked.
* @param value Value mark the cluster with.
* @param clst Cluster which is to be set.
* @param value Value to set the cluster with.
*/
void
fat_mark_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno,
fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno,
fat_cluster_t clst, fat_cluster_t value)
{
block_t *b;
243,7 → 257,7
 
assert(fatno < bs->fatcnt);
b = block_get(dev_handle, rscnt + sf * fatno +
(clst * sizeof(fat_cluster_t)) / bps, bps);
(clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
*cp = host2uint16_t_le(value);
b->dirty = true; /* need to sync block */
265,7 → 279,7
 
for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
for (c = 0; c < nclsts; c++) {
fat_mark_cluster(bs, dev_handle, fatno, lifo[c],
fat_set_cluster(bs, dev_handle, fatno, lifo[c],
c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
}
}
313,7 → 327,7
*/
futex_down(&fat_alloc_lock);
for (b = 0, cl = 0; b < sf; blk++) {
blk = block_get(dev_handle, rscnt + b, bps);
blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NOREAD);
for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
349,7 → 363,7
* we have allocated so far.
*/
while (found--) {
fat_mark_cluster(bs, dev_handle, FAT1, lifo[found],
fat_set_cluster(bs, dev_handle, FAT1, lifo[found],
FAT_CLST_RES0);
}
357,9 → 371,32
return ENOSPC;
}
 
/** Free clusters forming a cluster chain in all copies of FAT.
*
* @param bs Buffer hodling the boot sector of the file system.
* @param dev_handle Device handle of the file system.
* @param firstc First cluster in the chain which is to be freed.
*/
void
fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc)
{
unsigned fatno;
fat_cluster_t nextc;
 
/* Mark all clusters in the chain as free in all copies of FAT. */
while (firstc < FAT_CLST_LAST1) {
nextc = fat_get_cluster(bs, dev_handle, firstc);
assert(nextc >= FAT_CLST_FIRST && nextc < FAT_CLST_BAD);
for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
fat_set_cluster(bs, dev_handle, fatno, firstc,
FAT_CLST_RES0);
firstc = nextc;
}
}
 
/** Append a cluster chain to the last file cluster in all FATs.
*
* @param bs Buffer holding boot sector of the file system.
* @param bs Buffer holding the boot sector of the file system.
* @param nodep Node representing the file.
* @param mcl First cluster of the cluster chain to append.
*/
369,7 → 406,9
fat_cluster_t lcl;
uint8_t fatno;
 
if (_fat_blcks_get(bs, dev_handle, nodep->firstc, &lcl) == 0) {
if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl,
(uint16_t) -1) == 0) {
/* No clusters allocated to the node yet. */
nodep->firstc = host2uint16_t_le(mcl);
nodep->dirty = true; /* need to sync node */
return;
376,9 → 415,40
}
 
for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
fat_mark_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl);
fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl);
}
 
/** Chop off node clusters in all copies of FAT.
*
* @param bs Buffer holding the boot sector of the file system.
* @param nodep FAT node where the chopping will take place.
* @param lastc Last cluster which will remain in the node. If this
* argument is FAT_CLST_RES0, then all clusters will
* be chopped off.
*/
void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc)
{
dev_handle_t dev_handle = nodep->idx->dev_handle;
if (lastc == FAT_CLST_RES0) {
/* The node will have zero size and no clusters allocated. */
fat_free_clusters(bs, dev_handle, nodep->firstc);
nodep->firstc = FAT_CLST_RES0;
nodep->dirty = true; /* need to sync node */
} else {
fat_cluster_t nextc;
unsigned fatno;
 
nextc = fat_get_cluster(bs, dev_handle, lastc);
 
/* Terminate the cluster chain in all copies of FAT. */
for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1);
 
/* Free all following clusters. */
fat_free_clusters(bs, dev_handle, nextc);
}
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/fat_fat.h
35,6 → 35,7
 
#include "../../vfs/vfs.h"
#include <stdint.h>
#include <libblock.h>
 
#define FAT1 0
 
57,21 → 58,28
 
typedef uint16_t fat_cluster_t;
 
#define fat_block_get(bs, np, off) \
_fat_block_get((bs), (np)->idx->dev_handle, (np)->firstc, (off))
#define fat_clusters_get(bs, dh, fc) \
fat_cluster_walk((bs), (dh), (fc), NULL, (uint16_t) -1)
extern uint16_t fat_cluster_walk(struct fat_bs *, dev_handle_t, fat_cluster_t,
fat_cluster_t *, uint16_t);
 
#define fat_block_get(bs, np, bn, flags) \
_fat_block_get((bs), (np)->idx->dev_handle, (np)->firstc, (bn), (flags))
 
extern struct block *_fat_block_get(struct fat_bs *, dev_handle_t,
fat_cluster_t, off_t);
extern uint16_t _fat_blcks_get(struct fat_bs *, dev_handle_t, fat_cluster_t,
fat_cluster_t *);
fat_cluster_t, bn_t, int);
extern void fat_append_clusters(struct fat_bs *, struct fat_node *,
fat_cluster_t);
extern void fat_chop_clusters(struct fat_bs *, struct fat_node *,
fat_cluster_t);
extern int fat_alloc_clusters(struct fat_bs *, dev_handle_t, unsigned,
fat_cluster_t *, fat_cluster_t *);
extern void fat_free_clusters(struct fat_bs *, dev_handle_t, fat_cluster_t);
extern void fat_alloc_shadow_clusters(struct fat_bs *, dev_handle_t,
fat_cluster_t *, unsigned);
extern void fat_mark_cluster(struct fat_bs *, dev_handle_t, unsigned,
extern fat_cluster_t fat_get_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t);
extern void fat_set_cluster(struct fat_bs *, dev_handle_t, unsigned,
fat_cluster_t, fat_cluster_t);
extern void fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
off_t);
/branches/tracing/uspace/srv/fs/fat/fat.c
113,6 → 113,9
case VFS_WRITE:
fat_write(callid, &call);
break;
case VFS_TRUNCATE:
fat_truncate(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/tracing/uspace/srv/fs/fat/fat_ops.c
89,7 → 89,7
/* Read the block that contains the dentry of interest. */
b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc,
(node->idx->pdi * sizeof(fat_dentry_t)) / bps);
(node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
 
d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
 
102,6 → 102,42
block_put(b);
}
 
static fat_node_t *fat_node_get_new(void)
{
fat_node_t *nodep;
 
futex_down(&ffn_futex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached free node structure. */
fat_idx_t *idxp_tmp;
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
goto skip_cache;
idxp_tmp = nodep->idx;
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
futex_up(&ffn_futex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
} else {
skip_cache:
/* Try to allocate a new node structure. */
futex_up(&ffn_futex);
nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!nodep)
return NULL;
}
fat_node_initialize(nodep);
return nodep;
}
 
/** Internal version of fat_node_get().
*
* @param idxp Locked index structure.
113,6 → 149,7
fat_dentry_t *d;
fat_node_t *nodep = NULL;
unsigned bps;
unsigned spc;
unsigned dps;
 
if (idxp->nodep) {
133,42 → 170,18
assert(idxp->pfc);
 
futex_down(&ffn_futex);
if (!list_empty(&ffn_head)) {
/* Try to use a cached free node structure. */
fat_idx_t *idxp_tmp;
nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
if (futex_trydown(&nodep->lock) == ESYNCH_WOULD_BLOCK)
goto skip_cache;
idxp_tmp = nodep->idx;
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
futex_up(&ffn_futex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
} else {
skip_cache:
/* Try to allocate a new node structure. */
futex_up(&ffn_futex);
nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!nodep)
return NULL;
}
fat_node_initialize(nodep);
nodep = fat_node_get_new();
if (!nodep)
return NULL;
 
bs = block_bb_get(idxp->dev_handle);
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
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,
(idxp->pdi * sizeof(fat_dentry_t)) / bps);
(idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
assert(b);
 
d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
184,8 → 197,8
* 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,
uint16_t_le2host(d->firstc), NULL);
nodep->size = bps * spc * fat_clusters_get(bs, idxp->dev_handle,
uint16_t_le2host(d->firstc));
} else {
nodep->type = FAT_FILE;
nodep->size = uint32_t_le2host(d->size);
231,7 → 244,7
futex_up(&nodep->lock);
}
 
static void *fat_create(int flags)
static void *fat_create(dev_handle_t dev_handle, int flags)
{
return NULL; /* not supported at the moment */
}
269,7 → 282,7
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(bs, parentp, i, BLOCK_FLAGS_NONE);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
359,7 → 372,7
for (i = 0; i < blocks; i++) {
fat_dentry_t *d;
b = fat_block_get(bs, nodep, i);
b = fat_block_get(bs, nodep, i, BLOCK_FLAGS_NONE);
for (j = 0; j < dps; j++) {
d = ((fat_dentry_t *)b->data) + j;
switch (fat_classify_dentry(d)) {
434,12 → 447,20
int rc;
 
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE, BS_BLOCK * BS_SIZE, BS_SIZE);
rc = block_init(dev_handle, BS_SIZE);
if (rc != EOK) {
ipc_answer_0(rid, 0);
ipc_answer_0(rid, rc);
return;
}
 
/* prepare the boot block */
rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE);
if (rc != EOK) {
block_fini(dev_handle);
ipc_answer_0(rid, rc);
return;
}
 
/* get the buffer with the boot sector */
bs = block_bb_get(dev_handle);
453,6 → 474,14
return;
}
 
/* Initialize the block cache */
rc = block_cache_init(dev_handle, bps, 0 /* XXX */);
if (rc != EOK) {
block_fini(dev_handle);
ipc_answer_0(rid, rc);
return;
}
 
rc = fat_idx_init_by_dev_handle(dev_handle);
if (rc != EOK) {
block_fini(dev_handle);
545,7 → 574,8
} else {
bytes = min(len, bps - pos % bps);
bytes = min(bytes, nodep->size - pos);
b = fat_block_get(bs, nodep, pos / bps);
b = fat_block_get(bs, nodep, pos / bps,
BLOCK_FLAGS_NONE);
(void) ipc_data_read_finalize(callid, b->data + pos % bps,
bytes);
block_put(b);
570,7 → 600,7
while (bnum < nodep->size / bps) {
off_t o;
 
b = fat_block_get(bs, nodep, bnum);
b = fat_block_get(bs, nodep, bnum, BLOCK_FLAGS_NONE);
for (o = pos % (bps / sizeof(fat_dentry_t));
o < bps / sizeof(fat_dentry_t);
o++, pos++) {
616,7 → 646,9
block_t *b;
uint16_t bps;
unsigned spc;
unsigned bpc; /* bytes per cluster */
off_t boundary;
int flags = BLOCK_FLAGS_NONE;
if (!nodep) {
ipc_answer_0(rid, ENOENT);
623,13 → 655,6
return;
}
/* XXX remove me when you are ready */
{
ipc_answer_0(rid, ENOTSUP);
fat_node_put(nodep);
return;
}
 
ipc_callid_t callid;
size_t len;
if (!ipc_data_write_receive(&callid, &len)) {
639,6 → 664,11
return;
}
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
bpc = bps * spc;
 
/*
* In all scenarios, we will attempt to write out only one block worth
* of data at maximum. There might be some more efficient approaches,
647,12 → 677,10
* value signalizing a smaller number of bytes written.
*/
bytes = min(len, bps - pos % bps);
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
if (bytes == bps)
flags |= BLOCK_FLAGS_NOREAD;
boundary = ROUND_UP(nodep->size, bps * spc);
boundary = ROUND_UP(nodep->size, bpc);
if (pos < boundary) {
/*
* This is the easier case - we are either overwriting already
661,7 → 689,7
* next block size boundary.
*/
fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos);
b = fat_block_get(bs, nodep, pos / bps);
b = fat_block_get(bs, nodep, pos / bps, flags);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
b->dirty = true; /* need to sync block */
670,8 → 698,8
nodep->size = pos + bytes;
nodep->dirty = true; /* need to sync node */
}
ipc_answer_2(rid, EOK, bytes, nodep->size);
fat_node_put(nodep);
ipc_answer_1(rid, EOK, bytes);
return;
} else {
/*
680,13 → 708,11
*/
int status;
unsigned nclsts;
fat_cluster_t mcl, lcl;
nclsts = (ROUND_UP(pos + bytes, bps * spc) - boundary) /
bps * spc;
fat_cluster_t mcl, lcl;
nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc;
/* create an independent chain of nclsts clusters in all FATs */
status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl,
&lcl);
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);
696,8 → 722,8
}
/* zero fill any gaps */
fat_fill_gap(bs, nodep, mcl, pos);
b = _fat_block_get(bs, dev_handle, lcl,
(pos / bps) % spc);
b = _fat_block_get(bs, dev_handle, lcl, (pos / bps) % spc,
flags);
(void) ipc_data_write_finalize(callid, b->data + pos % bps,
bytes);
b->dirty = true; /* need to sync block */
709,12 → 735,70
fat_append_clusters(bs, nodep, mcl);
nodep->size = pos + bytes;
nodep->dirty = true; /* need to sync node */
ipc_answer_2(rid, EOK, bytes, nodep->size);
fat_node_put(nodep);
ipc_answer_1(rid, EOK, bytes);
return;
}
}
 
void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
size_t size = (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;
uint8_t spc;
unsigned bpc; /* bytes per cluster */
int rc;
 
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
spc = bs->spc;
bpc = bps * spc;
 
if (nodep->size == size) {
rc = EOK;
} else if (nodep->size < size) {
/*
* The standard says we have the freedom to grow the node.
* For now, we simply return an error.
*/
rc = EINVAL;
} else if (ROUND_UP(nodep->size, bpc) == ROUND_UP(size, bpc)) {
/*
* The node will be shrunk, but no clusters will be deallocated.
*/
nodep->size = size;
nodep->dirty = true; /* need to sync node */
rc = EOK;
} else {
/*
* The node will be shrunk, clusters will be deallocated.
*/
if (size == 0) {
fat_chop_clusters(bs, nodep, FAT_CLST_RES0);
} else {
fat_cluster_t lastc;
(void) fat_cluster_walk(bs, dev_handle, nodep->firstc,
&lastc, (size - 1) / bpc);
fat_chop_clusters(bs, nodep, lastc);
}
nodep->size = size;
nodep->dirty = true; /* need to sync node */
rc = EOK;
}
fat_node_put(nodep);
ipc_answer_0(rid, rc);
return;
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../../Makefile.config
 
LIBC_PREFIX = ../../../lib/libc
LIBFS_PREFIX = ../../../lib/libfs
LIBBLOCK_PREFIX = ../../../lib/libblock
/branches/tracing/uspace/srv/pci/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/srv/devmap/Makefile
29,6 → 29,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/srv/vfs/Makefile
30,6 → 30,8
## Setup toolchain
#
 
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
/branches/tracing/uspace/Makefile
93,7 → 93,7
-rm Makefile.config
 
$(CLEANS):
-$(MAKE) -C $(basename $@) clean ARCH=$(ARCH)
-$(MAKE) -C $(basename $@) clean
 
$(BUILDS):
$(MAKE) -C $(basename $@) all ARCH=$(ARCH) COMPILER=$(COMPILER)
$(MAKE) -C $(basename $@) all