Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4580 → Rev 4581

/branches/network/uspace/srv/fs/fat/fat_ops.c
48,22 → 48,26
#include <errno.h>
#include <string.h>
#include <byteorder.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <adt/hash_table.h>
#include <adt/list.h>
#include <assert.h>
#include <futex.h>
#include <fibril_sync.h>
#include <sys/mman.h>
#include <align.h>
 
/** Futex protecting the list of cached free FAT nodes. */
static futex_t ffn_futex = FUTEX_INITIALIZER;
#define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL)
#define FS_NODE(node) ((node) ? (node)->bp : NULL)
 
/** Mutex protecting the list of cached free FAT nodes. */
static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
 
/** List of cached free FAT nodes. */
static LIST_INITIALIZE(ffn_head);
 
static void fat_node_initialize(fat_node_t *node)
{
futex_initialize(&node->lock, 1);
fibril_mutex_initialize(&node->lock);
node->bp = NULL;
node->idx = NULL;
node->type = 0;
link_initialize(&node->ffn_link);
108,36 → 112,46
 
static fat_node_t *fat_node_get_new(void)
{
fs_node_t *fn;
fat_node_t *nodep;
 
futex_down(&ffn_futex);
fibril_mutex_lock(&ffn_mutex);
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)
if (!fibril_mutex_trylock(&nodep->lock))
goto skip_cache;
idxp_tmp = nodep->idx;
if (futex_trydown(&idxp_tmp->lock) == ESYNCH_WOULD_BLOCK) {
futex_up(&nodep->lock);
if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
fibril_mutex_unlock(&nodep->lock);
goto skip_cache;
}
list_remove(&nodep->ffn_link);
futex_up(&ffn_futex);
fibril_mutex_unlock(&ffn_mutex);
if (nodep->dirty)
fat_node_sync(nodep);
idxp_tmp->nodep = NULL;
futex_up(&nodep->lock);
futex_up(&idxp_tmp->lock);
fibril_mutex_unlock(&nodep->lock);
fibril_mutex_unlock(&idxp_tmp->lock);
fn = FS_NODE(nodep);
} else {
skip_cache:
/* Try to allocate a new node structure. */
futex_up(&ffn_futex);
fibril_mutex_unlock(&ffn_mutex);
fn = (fs_node_t *)malloc(sizeof(fs_node_t));
if (!fn)
return NULL;
nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!nodep)
if (!nodep) {
free(fn);
return NULL;
}
}
fat_node_initialize(nodep);
fs_node_initialize(fn);
fn->data = nodep;
nodep->bp = fn;
return nodep;
}
146,7 → 160,7
*
* @param idxp Locked index structure.
*/
static void *fat_node_get_core(fat_idx_t *idxp)
static fat_node_t *fat_node_get_core(fat_idx_t *idxp)
{
block_t *b;
fat_bs_t *bs;
161,10 → 175,10
* We are lucky.
* The node is already instantiated in memory.
*/
futex_down(&idxp->nodep->lock);
fibril_mutex_lock(&idxp->nodep->lock);
if (!idxp->nodep->refcnt++)
list_remove(&idxp->nodep->ffn_link);
futex_up(&idxp->nodep->lock);
fibril_mutex_unlock(&idxp->nodep->lock);
return idxp->nodep;
}
 
223,21 → 237,21
/*
* Forward declarations of FAT libfs operations.
*/
static void *fat_node_get(dev_handle_t, fs_index_t);
static void fat_node_put(void *);
static void *fat_create_node(dev_handle_t, int);
static int fat_destroy_node(void *);
static int fat_link(void *, void *, const char *);
static int fat_unlink(void *, void *);
static void *fat_match(void *, const char *);
static fs_index_t fat_index_get(void *);
static size_t fat_size_get(void *);
static unsigned fat_lnkcnt_get(void *);
static bool fat_has_children(void *);
static void *fat_root_get(dev_handle_t);
static fs_node_t *fat_node_get(dev_handle_t, fs_index_t);
static void fat_node_put(fs_node_t *);
static fs_node_t *fat_create_node(dev_handle_t, int);
static int fat_destroy_node(fs_node_t *);
static int fat_link(fs_node_t *, fs_node_t *, const char *);
static int fat_unlink(fs_node_t *, fs_node_t *, const char *);
static fs_node_t *fat_match(fs_node_t *, const char *);
static fs_index_t fat_index_get(fs_node_t *);
static size_t fat_size_get(fs_node_t *);
static unsigned fat_lnkcnt_get(fs_node_t *);
static bool fat_has_children(fs_node_t *);
static fs_node_t *fat_root_get(dev_handle_t);
static char fat_plb_get_char(unsigned);
static bool fat_is_directory(void *);
static bool fat_is_file(void *node);
static bool fat_is_directory(fs_node_t *);
static bool fat_is_file(fs_node_t *node);
 
/*
* FAT libfs operations.
244,9 → 258,9
*/
 
/** Instantiate a FAT in-core node. */
void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
{
void *node;
fat_node_t *nodep;
fat_idx_t *idxp;
 
idxp = fat_idx_get_by_index(dev_handle, index);
253,22 → 267,22
if (!idxp)
return NULL;
/* idxp->lock held */
node = fat_node_get_core(idxp);
futex_up(&idxp->lock);
return node;
nodep = fat_node_get_core(idxp);
fibril_mutex_unlock(&idxp->lock);
return FS_NODE(nodep);
}
 
void fat_node_put(void *node)
void fat_node_put(fs_node_t *fn)
{
fat_node_t *nodep = (fat_node_t *)node;
fat_node_t *nodep = FAT_NODE(fn);
bool destroy = false;
 
futex_down(&nodep->lock);
fibril_mutex_lock(&nodep->lock);
if (!--nodep->refcnt) {
if (nodep->idx) {
futex_down(&ffn_futex);
fibril_mutex_lock(&ffn_mutex);
list_append(&nodep->ffn_link, &ffn_head);
futex_up(&ffn_futex);
fibril_mutex_unlock(&ffn_mutex);
} else {
/*
* The node does not have any index structure associated
279,12 → 293,14
destroy = true;
}
}
futex_up(&nodep->lock);
if (destroy)
free(node);
fibril_mutex_unlock(&nodep->lock);
if (destroy) {
free(nodep->bp);
free(nodep);
}
}
 
void *fat_create_node(dev_handle_t dev_handle, int flags)
fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags)
{
fat_idx_t *idxp;
fat_node_t *nodep;
310,7 → 326,7
idxp = fat_idx_get_new(dev_handle);
if (!idxp) {
fat_free_clusters(bs, dev_handle, mcl);
fat_node_put(nodep);
fat_node_put(FS_NODE(nodep));
return NULL;
}
/* idxp->lock held */
344,13 → 360,13
nodep->idx = idxp;
idxp->nodep = nodep;
 
futex_up(&idxp->lock);
return nodep;
fibril_mutex_unlock(&idxp->lock);
return FS_NODE(nodep);
}
 
int fat_destroy_node(void *node)
int fat_destroy_node(fs_node_t *fn)
{
fat_node_t *nodep = (fat_node_t *)node;
fat_node_t *nodep = FAT_NODE(fn);
fat_bs_t *bs;
 
/*
364,7 → 380,7
/*
* The node may not have any children.
*/
assert(fat_has_children(node) == false);
assert(fat_has_children(fn) == false);
 
bs = block_bb_get(nodep->idx->dev_handle);
if (nodep->firstc != FAT_CLST_RES0) {
374,14 → 390,15
}
 
fat_idx_destroy(nodep->idx);
free(nodep->bp);
free(nodep);
return EOK;
}
 
int fat_link(void *prnt, void *chld, const char *name)
int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
{
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_node_t *parentp = FAT_NODE(pfn);
fat_node_t *childp = FAT_NODE(cfn);
fat_dentry_t *d;
fat_bs_t *bs;
block_t *b;
392,16 → 409,16
fat_cluster_t mcl, lcl;
int rc;
 
futex_down(&childp->lock);
fibril_mutex_lock(&childp->lock);
if (childp->lnkcnt == 1) {
/*
* On FAT, we don't support multiple hard links.
*/
futex_up(&childp->lock);
fibril_mutex_unlock(&childp->lock);
return EMLINK;
}
assert(childp->lnkcnt == 0);
futex_up(&childp->lock);
fibril_mutex_unlock(&childp->lock);
 
if (!fat_dentry_name_verify(name)) {
/*
415,7 → 432,7
* a new one.
*/
futex_down(&parentp->idx->lock);
fibril_mutex_lock(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
446,12 → 463,12
*/
if (parentp->idx->pfc == FAT_CLST_ROOT) {
/* Can't grow the root directory. */
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return ENOSPC;
}
rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
if (rc != EOK) {
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return rc;
}
fat_append_clusters(bs, parentp, mcl);
474,9 → 491,9
fat_dentry_name_set(d, name);
b->dirty = true; /* need to sync block */
block_put(b);
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
 
futex_down(&childp->idx->lock);
fibril_mutex_lock(&childp->idx->lock);
/*
* If possible, create the Sub-directory Identifier Entry and the
512,12 → 529,12
 
childp->idx->pfc = parentp->firstc;
childp->idx->pdi = i * dps + j;
futex_up(&childp->idx->lock);
fibril_mutex_unlock(&childp->idx->lock);
 
futex_down(&childp->lock);
fibril_mutex_lock(&childp->lock);
childp->lnkcnt = 1;
childp->dirty = true; /* need to sync node */
futex_up(&childp->lock);
fibril_mutex_unlock(&childp->lock);
 
/*
* Hash in the index structure into the position hash.
527,19 → 544,25
return EOK;
}
 
int fat_unlink(void *prnt, void *chld)
int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
{
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *childp = (fat_node_t *)chld;
fat_node_t *parentp = FAT_NODE(pfn);
fat_node_t *childp = FAT_NODE(cfn);
fat_bs_t *bs;
fat_dentry_t *d;
uint16_t bps;
block_t *b;
 
futex_down(&parentp->lock);
futex_down(&childp->lock);
if (!parentp)
return EBUSY;
if (fat_has_children(cfn))
return ENOTEMPTY;
 
fibril_mutex_lock(&parentp->lock);
fibril_mutex_lock(&childp->lock);
assert(childp->lnkcnt == 1);
futex_down(&childp->idx->lock);
fibril_mutex_lock(&childp->idx->lock);
bs = block_bb_get(childp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
 
558,19 → 581,19
/* clear position information */
childp->idx->pfc = FAT_CLST_RES0;
childp->idx->pdi = 0;
futex_up(&childp->idx->lock);
fibril_mutex_unlock(&childp->idx->lock);
childp->lnkcnt = 0;
childp->dirty = true;
futex_up(&childp->lock);
futex_up(&parentp->lock);
fibril_mutex_unlock(&childp->lock);
fibril_mutex_unlock(&parentp->lock);
 
return EOK;
}
 
void *fat_match(void *prnt, const char *component)
fs_node_t *fat_match(fs_node_t *pfn, const char *component)
{
fat_bs_t *bs;
fat_node_t *parentp = (fat_node_t *)prnt;
fat_node_t *parentp = FAT_NODE(pfn);
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
unsigned i, j;
unsigned bps; /* bytes per sector */
579,7 → 602,7
fat_dentry_t *d;
block_t *b;
 
futex_down(&parentp->idx->lock);
fibril_mutex_lock(&parentp->idx->lock);
bs = block_bb_get(parentp->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
594,7 → 617,7
continue;
case FAT_DENTRY_LAST:
block_put(b);
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return NULL;
default:
case FAT_DENTRY_VALID:
603,7 → 626,7
}
if (fat_dentry_namecmp(name, component) == 0) {
/* hit */
void *node;
fat_node_t *nodep;
/*
* Assume tree hierarchy for locking. We
* already have the parent and now we are going
613,7 → 636,7
fat_idx_t *idx = fat_idx_get_by_pos(
parentp->idx->dev_handle, parentp->firstc,
i * dps + j);
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
if (!idx) {
/*
* Can happen if memory is low or if we
622,41 → 645,38
block_put(b);
return NULL;
}
node = fat_node_get_core(idx);
futex_up(&idx->lock);
nodep = fat_node_get_core(idx);
fibril_mutex_unlock(&idx->lock);
block_put(b);
return node;
return FS_NODE(nodep);
}
}
block_put(b);
}
 
futex_up(&parentp->idx->lock);
fibril_mutex_unlock(&parentp->idx->lock);
return NULL;
}
 
fs_index_t fat_index_get(void *node)
fs_index_t fat_index_get(fs_node_t *fn)
{
fat_node_t *fnodep = (fat_node_t *)node;
if (!fnodep)
return 0;
return fnodep->idx->index;
return FAT_NODE(fn)->idx->index;
}
 
size_t fat_size_get(void *node)
size_t fat_size_get(fs_node_t *fn)
{
return ((fat_node_t *)node)->size;
return FAT_NODE(fn)->size;
}
 
unsigned fat_lnkcnt_get(void *node)
unsigned fat_lnkcnt_get(fs_node_t *fn)
{
return ((fat_node_t *)node)->lnkcnt;
return FAT_NODE(fn)->lnkcnt;
}
 
bool fat_has_children(void *node)
bool fat_has_children(fs_node_t *fn)
{
fat_bs_t *bs;
fat_node_t *nodep = (fat_node_t *)node;
fat_node_t *nodep = FAT_NODE(fn);
unsigned bps;
unsigned dps;
unsigned blocks;
666,7 → 686,7
if (nodep->type != FAT_DIRECTORY)
return false;
futex_down(&nodep->idx->lock);
fibril_mutex_lock(&nodep->idx->lock);
bs = block_bb_get(nodep->idx->dev_handle);
bps = uint16_t_le2host(bs->bps);
dps = bps / sizeof(fat_dentry_t);
685,26 → 705,26
continue;
case FAT_DENTRY_LAST:
block_put(b);
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return false;
default:
case FAT_DENTRY_VALID:
block_put(b);
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return true;
}
block_put(b);
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return true;
}
block_put(b);
}
 
futex_up(&nodep->idx->lock);
fibril_mutex_unlock(&nodep->idx->lock);
return false;
}
 
void *fat_root_get(dev_handle_t dev_handle)
fs_node_t *fat_root_get(dev_handle_t dev_handle)
{
return fat_node_get(dev_handle, 0);
}
714,14 → 734,14
return fat_reg.plb_ro[pos % PLB_SIZE];
}
 
bool fat_is_directory(void *node)
bool fat_is_directory(fs_node_t *fn)
{
return ((fat_node_t *)node)->type == FAT_DIRECTORY;
return FAT_NODE(fn)->type == FAT_DIRECTORY;
}
 
bool fat_is_file(void *node)
bool fat_is_file(fs_node_t *fn)
{
return ((fat_node_t *)node)->type == FAT_FILE;
return FAT_NODE(fn)->type == FAT_FILE;
}
 
/** libfs operations */
750,6 → 770,7
void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
enum cache_mode cmode;
fat_bs_t *bs;
uint16_t bps;
uint16_t rde;
777,6 → 798,12
}
opts[size] = '\0';
 
/* Check for option enabling write through. */
if (str_cmp(opts, "wtcache") == 0)
cmode = CACHE_MODE_WT;
else
cmode = CACHE_MODE_WB;
 
/* initialize libblock */
rc = block_init(dev_handle, BS_SIZE);
if (rc != EOK) {
806,7 → 833,7
}
 
/* Initialize the block cache */
rc = block_cache_init(dev_handle, bps, 0 /* XXX */);
rc = block_cache_init(dev_handle, bps, 0 /* XXX */, cmode);
if (rc != EOK) {
block_fini(dev_handle);
ipc_answer_0(rid, rc);
821,8 → 848,17
}
 
/* Initialize the root node. */
fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
if (!rfn) {
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
}
fs_node_initialize(rfn);
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
free(rfn);
block_fini(dev_handle);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
832,8 → 868,9
 
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
if (!ridxp) {
free(rfn);
free(rootp);
block_fini(dev_handle);
free(rootp);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
848,8 → 885,10
rootp->size = rde * sizeof(fat_dentry_t);
rootp->idx = ridxp;
ridxp->nodep = rootp;
rootp->bp = rfn;
rfn->data = rootp;
futex_up(&ridxp->lock);
fibril_mutex_unlock(&ridxp->lock);
 
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
}
856,7 → 895,7
 
void fat_mount(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
869,21 → 908,23
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
off_t pos = (off_t)IPC_GET_ARG3(*request);
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
fs_node_t *fn = fat_node_get(dev_handle, index);
fat_node_t *nodep;
fat_bs_t *bs;
uint16_t bps;
size_t bytes;
block_t *b;
 
if (!nodep) {
if (!fn) {
ipc_answer_0(rid, ENOENT);
return;
}
nodep = FAT_NODE(fn);
 
ipc_callid_t callid;
size_t len;
if (!ipc_data_read_receive(&callid, &len)) {
fat_node_put(nodep);
fat_node_put(fn);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
954,7 → 995,7
bnum++;
}
miss:
fat_node_put(nodep);
fat_node_put(fn);
ipc_answer_0(callid, ENOENT);
ipc_answer_1(rid, ENOENT, 0);
return;
963,7 → 1004,7
bytes = (pos - spos) + 1;
}
 
fat_node_put(nodep);
fat_node_put(fn);
ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
}
 
972,7 → 1013,8
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
off_t pos = (off_t)IPC_GET_ARG3(*request);
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
fs_node_t *fn = fat_node_get(dev_handle, index);
fat_node_t *nodep;
fat_bs_t *bs;
size_t bytes;
block_t *b;
982,15 → 1024,16
off_t boundary;
int flags = BLOCK_FLAGS_NONE;
if (!nodep) {
if (!fn) {
ipc_answer_0(rid, ENOENT);
return;
}
nodep = FAT_NODE(fn);
ipc_callid_t callid;
size_t len;
if (!ipc_data_write_receive(&callid, &len)) {
fat_node_put(nodep);
fat_node_put(fn);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
1031,7 → 1074,7
nodep->dirty = true; /* need to sync node */
}
ipc_answer_2(rid, EOK, bytes, nodep->size);
fat_node_put(nodep);
fat_node_put(fn);
return;
} else {
/*
1047,7 → 1090,7
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);
fat_node_put(fn);
ipc_answer_0(callid, status);
ipc_answer_0(rid, status);
return;
1068,7 → 1111,7
nodep->size = pos + bytes;
nodep->dirty = true; /* need to sync node */
ipc_answer_2(rid, EOK, bytes, nodep->size);
fat_node_put(nodep);
fat_node_put(fn);
return;
}
}
1078,7 → 1121,8
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);
fs_node_t *fn = fat_node_get(dev_handle, index);
fat_node_t *nodep;
fat_bs_t *bs;
uint16_t bps;
uint8_t spc;
1085,10 → 1129,11
unsigned bpc; /* bytes per cluster */
int rc;
 
if (!nodep) {
if (!fn) {
ipc_answer_0(rid, ENOENT);
return;
}
nodep = FAT_NODE(fn);
 
bs = block_bb_get(dev_handle);
bps = uint16_t_le2host(bs->bps);
1126,11 → 1171,16
nodep->dirty = true; /* need to sync node */
rc = EOK;
}
fat_node_put(nodep);
fat_node_put(fn);
ipc_answer_0(rid, rc);
return;
}
 
void fat_close(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, EOK);
}
 
void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
1137,16 → 1187,32
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
int rc;
 
fat_node_t *nodep = fat_node_get(dev_handle, index);
if (!nodep) {
fs_node_t *fn = fat_node_get(dev_handle, index);
if (!fn) {
ipc_answer_0(rid, ENOENT);
return;
}
 
rc = fat_destroy_node(nodep);
rc = fat_destroy_node(fn);
ipc_answer_0(rid, rc);
}
 
void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
{
libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_device(ipc_callid_t rid, ipc_call_t *request)
{
ipc_answer_0(rid, ENOTSUP);
}
 
void fat_sync(ipc_callid_t rid, ipc_call_t *request)
{
/* Dummy implementation */
ipc_answer_0(rid, EOK);
}
 
/**
* @}
*/
*/