/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); |
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)); |
nodep = fat_node_get_new(); |
if (!nodep) |
return NULL; |
} |
fat_node_initialize(nodep); |
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); |
if (bytes == bps) |
flags |= BLOCK_FLAGS_NOREAD; |
bs = block_bb_get(dev_handle); |
bps = uint16_t_le2host(bs->bps); |
spc = bs->spc; |
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 { |
/* |
682,11 → 710,9 |
unsigned nclsts; |
fat_cluster_t mcl, lcl; |
nclsts = (ROUND_UP(pos + bytes, bps * spc) - boundary) / |
bps * spc; |
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 |