Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -100,4 +100,6 @@
if (s.is_file)
printf("%-40s\t%llu\n", name, (long long) s.size);
+ else if (s.is_directory)
+ printf("%-40s\t
\n", name);
else
printf("%-40s\n", name);
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/app/init/init.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -58,5 +58,5 @@
{
char *opts = "";
- const char *root_dev = "initrd";
+ const char *root_dev = "bd/initrd";
if (str_cmp(fstype, "tmpfs") == 0)
@@ -97,5 +97,5 @@
}
- snprintf(null, MAX_DEVICE_NAME, "null%d", null_id);
+ snprintf(null, MAX_DEVICE_NAME, "null/%d", null_id);
int rc = mount("devfs", "/dev", null, "", IPC_FLAG_BLOCKING);
@@ -170,5 +170,5 @@
}
- if (texit != TASK_EXIT_NORMAL || retval != 0) {
+ if ((texit != TASK_EXIT_NORMAL) || (retval != 0)) {
printf(NAME ": Server %s failed to start (returned %d)\n",
fname, retval);
@@ -206,8 +206,8 @@
int rc;
- printf("Trying to mount disk0 on /data... ");
+ printf("Trying to mount bd/disk0 on /data... ");
fflush(stdout);
- rc = mount("fat", "/data", "disk0", "wtcache", 0);
+ rc = mount("fat", "/data", "bd/disk0", "wtcache", 0);
if (rc == EOK)
printf("OK\n");
@@ -256,11 +256,11 @@
#endif
- getvc("vc0", "/app/bdsh");
- getvc("vc1", "/app/bdsh");
- getvc("vc2", "/app/bdsh");
- getvc("vc3", "/app/bdsh");
- getvc("vc4", "/app/bdsh");
- getvc("vc5", "/app/bdsh");
- getvc("vc6", "/app/klog");
+ getvc("term/vc0", "/app/bdsh");
+ getvc("term/vc1", "/app/bdsh");
+ getvc("term/vc2", "/app/bdsh");
+ getvc("term/vc3", "/app/bdsh");
+ getvc("term/vc4", "/app/bdsh");
+ getvc("term/vc5", "/app/bdsh");
+ getvc("term/vc6", "/app/klog");
return 0;
Index: uspace/app/tester/vfs/vfs1.c
===================================================================
--- uspace/app/tester/vfs/vfs1.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/app/tester/vfs/vfs1.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -85,5 +85,5 @@
return "Unable to create null device";
- snprintf(null, MAX_DEVICE_NAME, "null%d", null_id);
+ snprintf(null, MAX_DEVICE_NAME, "null/%d", null_id);
int rc = mount(FS_TYPE, MOUNT_POINT, null, OPTIONS, FLAGS);
switch (rc) {
Index: uspace/lib/libc/generic/devmap.c
===================================================================
--- uspace/lib/libc/generic/devmap.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/lib/libc/generic/devmap.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -35,4 +35,6 @@
#include
#include
+#include
+#include
static int devmap_phone_driver = -1;
@@ -105,6 +107,5 @@
aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
- ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
-
+ ipcarg_t retval = async_data_write_start(phone, name, str_size(name));
if (retval != EOK) {
async_wait_for(req, NULL);
@@ -126,9 +127,10 @@
/** Register new device.
*
- * @param name Device name.
- * @param handle Output: Handle to the created instance of device.
+ * @param namespace Namespace name.
+ * @param fqdn Fully qualified device name.
+ * @param handle Output: Handle to the created instance of device.
*
*/
-int devmap_device_register(const char *name, dev_handle_t *handle)
+int devmap_device_register(const char *fqdn, dev_handle_t *handle)
{
int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
@@ -143,6 +145,5 @@
&answer);
- ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
-
+ ipcarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
if (retval != EOK) {
async_wait_for(req, NULL);
@@ -167,5 +168,5 @@
}
-int devmap_device_get_handle(const char *name, dev_handle_t *handle, unsigned int flags)
+int devmap_device_get_handle(const char *fqdn, dev_handle_t *handle, unsigned int flags)
{
int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
@@ -180,6 +181,5 @@
&answer);
- ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
-
+ ipcarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
if (retval != EOK) {
async_wait_for(req, NULL);
@@ -202,4 +202,55 @@
return retval;
+}
+
+int devmap_namespace_get_handle(const char *name, dev_handle_t *handle, unsigned int flags)
+{
+ int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
+
+ if (phone < 0)
+ return phone;
+
+ async_serialize_start();
+
+ ipc_call_t answer;
+ aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
+ &answer);
+
+ ipcarg_t retval = async_data_write_start(phone, name, str_size(name));
+ if (retval != EOK) {
+ async_wait_for(req, NULL);
+ async_serialize_end();
+ return retval;
+ }
+
+ async_wait_for(req, &retval);
+
+ async_serialize_end();
+
+ if (retval != EOK) {
+ if (handle != NULL)
+ *handle = (dev_handle_t) -1;
+ return retval;
+ }
+
+ if (handle != NULL)
+ *handle = (dev_handle_t) IPC_GET_ARG1(answer);
+
+ return retval;
+}
+
+devmap_handle_type_t devmap_handle_probe(dev_handle_t handle)
+{
+ int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
+
+ if (phone < 0)
+ return phone;
+
+ ipcarg_t type;
+ int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
+ if (retval != EOK)
+ return DEV_HANDLE_NONE;
+
+ return (devmap_handle_type_t) type;
}
@@ -227,5 +278,5 @@
ipcarg_t null_id;
- int retval = async_req_0_1(phone, DEVMAP_DEVICE_NULL_CREATE, &null_id);
+ int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
if (retval != EOK)
return -1;
@@ -241,16 +292,11 @@
return;
- async_req_1_0(phone, DEVMAP_DEVICE_NULL_DESTROY, (ipcarg_t) null_id);
-}
-
-ipcarg_t devmap_device_get_count(void)
-{
- int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-
- if (phone < 0)
- return 0;
-
+ async_req_1_0(phone, DEVMAP_NULL_DESTROY, (ipcarg_t) null_id);
+}
+
+static size_t devmap_count_namespaces_internal(int phone)
+{
ipcarg_t count;
- int retval = async_req_0_1(phone, DEVMAP_DEVICE_GET_COUNT, &count);
+ int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
if (retval != EOK)
return 0;
@@ -259,31 +305,135 @@
}
-ipcarg_t devmap_device_get_devices(ipcarg_t count, dev_desc_t *data)
-{
- int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-
- if (phone < 0)
- return 0;
-
- async_serialize_start();
-
- ipc_call_t answer;
- aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer);
-
- ipcarg_t retval = async_data_read_start(phone, data, count * sizeof(dev_desc_t));
-
- if (retval != EOK) {
- async_wait_for(req, NULL);
- async_serialize_end();
- return 0;
- }
-
- async_wait_for(req, &retval);
-
- async_serialize_end();
-
+static size_t devmap_count_devices_internal(int phone, dev_handle_t ns_handle)
+{
+ ipcarg_t count;
+ int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
if (retval != EOK)
return 0;
- return IPC_GET_ARG1(answer);
-}
+ return count;
+}
+
+size_t devmap_count_namespaces(void)
+{
+ int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
+
+ if (phone < 0)
+ return 0;
+
+ return devmap_count_namespaces_internal(phone);
+}
+
+size_t devmap_count_devices(dev_handle_t ns_handle)
+{
+ int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
+
+ if (phone < 0)
+ return 0;
+
+ return devmap_count_devices_internal(phone, ns_handle);
+}
+
+size_t devmap_get_namespaces(dev_desc_t **data)
+{
+ int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
+
+ if (phone < 0)
+ return 0;
+
+ /* Loop until namespaces read succesful */
+ while (true) {
+ size_t count = devmap_count_namespaces_internal(phone);
+ if (count == 0)
+ return 0;
+
+ dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
+ if (devs == NULL)
+ return 0;
+
+ async_serialize_start();
+
+ ipc_call_t answer;
+ aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
+
+ int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
+ if (rc == EOVERFLOW) {
+ /*
+ * Number of namespaces has changed since
+ * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
+ */
+ async_serialize_end();
+ free(devs);
+ continue;
+ }
+
+ if (rc != EOK) {
+ async_wait_for(req, NULL);
+ async_serialize_end();
+ free(devs);
+ return 0;
+ }
+
+ ipcarg_t retval;
+ async_wait_for(req, &retval);
+ async_serialize_end();
+
+ if (retval != EOK)
+ return 0;
+
+ *data = devs;
+ return count;
+ }
+}
+
+size_t devmap_get_devices(dev_handle_t ns_handle, dev_desc_t **data)
+{
+ int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
+
+ if (phone < 0)
+ return 0;
+
+ /* Loop until namespaces read succesful */
+ while (true) {
+ size_t count = devmap_count_devices_internal(phone, ns_handle);
+ if (count == 0)
+ return 0;
+
+ dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
+ if (devs == NULL)
+ return 0;
+
+ async_serialize_start();
+
+ ipc_call_t answer;
+ aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
+
+ int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
+ if (rc == EOVERFLOW) {
+ /*
+ * Number of devices has changed since
+ * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
+ */
+ async_serialize_end();
+ free(devs);
+ continue;
+ }
+
+ if (rc != EOK) {
+ async_wait_for(req, NULL);
+ async_serialize_end();
+ free(devs);
+ return 0;
+ }
+
+ ipcarg_t retval;
+ async_wait_for(req, &retval);
+ async_serialize_end();
+
+ if (retval != EOK)
+ return 0;
+
+ *data = devs;
+ return count;
+ }
+}
Index: uspace/lib/libc/generic/vfs/vfs.c
===================================================================
--- uspace/lib/libc/generic/vfs/vfs.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/lib/libc/generic/vfs/vfs.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -117,5 +117,5 @@
}
-int mount(const char *fs_name, const char *mp, const char *dev,
+int mount(const char *fs_name, const char *mp, const char *fqdn,
const char *opts, unsigned int flags)
{
@@ -126,5 +126,5 @@
dev_handle_t dev_handle;
- res = devmap_device_get_handle(dev, &dev_handle, flags);
+ res = devmap_device_get_handle(fqdn, &dev_handle, flags);
if (res != EOK)
return res;
@@ -703,8 +703,8 @@
rc = fstat(fildes, &stat);
- if (!stat.devfs_stat.device)
+ if (!stat.device)
return -1;
- return devmap_device_connect(stat.devfs_stat.device, 0);
+ return devmap_device_connect(stat.device, 0);
}
Index: uspace/lib/libc/include/devmap.h
===================================================================
--- uspace/lib/libc/include/devmap.h (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/lib/libc/include/devmap.h (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -38,4 +38,5 @@
#include
#include
+#include
extern int devmap_get_phone(devmap_interface_t, unsigned int);
@@ -46,4 +47,7 @@
extern int devmap_device_get_handle(const char *, dev_handle_t *, unsigned int);
+extern int devmap_namespace_get_handle(const char *, dev_handle_t *, unsigned int);
+extern devmap_handle_type_t devmap_handle_probe(dev_handle_t);
+
extern int devmap_device_connect(dev_handle_t, unsigned int);
@@ -51,6 +55,9 @@
extern void devmap_null_destroy(int);
-extern ipcarg_t devmap_device_get_count(void);
-extern ipcarg_t devmap_device_get_devices(ipcarg_t, dev_desc_t *);
+extern size_t devmap_count_namespaces(void);
+extern size_t devmap_count_devices(dev_handle_t);
+
+extern size_t devmap_get_namespaces(dev_desc_t **);
+extern size_t devmap_get_devices(dev_handle_t, dev_desc_t **);
#endif
Index: uspace/lib/libc/include/ipc/devmap.h
===================================================================
--- uspace/lib/libc/include/ipc/devmap.h (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/lib/libc/include/ipc/devmap.h (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -43,14 +43,23 @@
typedef enum {
+ DEV_HANDLE_NONE,
+ DEV_HANDLE_NAMESPACE,
+ DEV_HANDLE_DEVICE
+} devmap_handle_type_t;
+
+typedef enum {
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
DEVMAP_DRIVER_UNREGISTER,
DEVMAP_DEVICE_REGISTER,
DEVMAP_DEVICE_UNREGISTER,
- DEVMAP_DEVICE_GET_NAME,
DEVMAP_DEVICE_GET_HANDLE,
- DEVMAP_DEVICE_NULL_CREATE,
- DEVMAP_DEVICE_NULL_DESTROY,
- DEVMAP_DEVICE_GET_COUNT,
- DEVMAP_DEVICE_GET_DEVICES
+ DEVMAP_NAMESPACE_GET_HANDLE,
+ DEVMAP_HANDLE_PROBE,
+ DEVMAP_NULL_CREATE,
+ DEVMAP_NULL_DESTROY,
+ DEVMAP_GET_NAMESPACE_COUNT,
+ DEVMAP_GET_DEVICE_COUNT,
+ DEVMAP_GET_NAMESPACES,
+ DEVMAP_GET_DEVICES
} devmap_request_t;
Index: uspace/lib/libc/include/sys/stat.h
===================================================================
--- uspace/lib/libc/include/sys/stat.h (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/lib/libc/include/sys/stat.h (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -42,15 +42,12 @@
struct stat {
- fs_handle_t fs_handle;
- dev_handle_t dev_handle;
- fs_index_t index;
- unsigned lnkcnt;
- bool is_file;
- off_t size;
- union {
- struct {
- dev_handle_t device;
- } devfs_stat;
- };
+ fs_handle_t fs_handle;
+ dev_handle_t dev_handle;
+ fs_index_t index;
+ unsigned int lnkcnt;
+ bool is_file;
+ bool is_directory;
+ off_t size;
+ dev_handle_t device;
};
Index: uspace/lib/libfs/libfs.c
===================================================================
--- uspace/lib/libfs/libfs.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/lib/libfs/libfs.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2009 Jakub Jermar
+ * Copyright (c) 2009 Jakub Jermar
* All rights reserved.
*
@@ -27,13 +27,13 @@
*/
-/** @addtogroup libfs
+/** @addtogroup libfs
* @{
- */
+ */
/**
* @file
- * Glue code which is commonod to all FS implementations.
- */
-
-#include "libfs.h"
+ * Glue code which is common to all FS implementations.
+ */
+
+#include "libfs.h"
#include "../../srv/vfs/vfs.h"
#include
@@ -67,13 +67,14 @@
* code.
*
- * @param vfs_phone Open phone for communication with VFS.
- * @param reg File system registration structure. It will be
- * initialized by this function.
- * @param info VFS info structure supplied by the file system
- * implementation.
- * @param conn Connection fibril for handling all calls originating in
- * VFS.
- *
- * @return EOK on success or a non-zero error code on errror.
+ * @param vfs_phone Open phone for communication with VFS.
+ * @param reg File system registration structure. It will be
+ * initialized by this function.
+ * @param info VFS info structure supplied by the file system
+ * implementation.
+ * @param conn Connection fibril for handling all calls originating in
+ * VFS.
+ *
+ * @return EOK on success or a non-zero error code on errror.
+ *
*/
int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info,
@@ -87,5 +88,5 @@
ipc_call_t answer;
aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer);
-
+
/*
* Send our VFS info structure to VFS.
@@ -96,10 +97,10 @@
return rc;
}
-
+
/*
* Ask VFS for callback connection.
*/
ipc_connect_to_me(vfs_phone, 0, 0, 0, ®->vfs_phonehash);
-
+
/*
* Allocate piece of address space for PLB.
@@ -110,5 +111,5 @@
return ENOMEM;
}
-
+
/*
* Request sharing the Path Lookup Buffer with VFS.
@@ -136,5 +137,5 @@
*/
async_set_client_connection(conn);
-
+
return IPC_GET_RETVAL(answer);
}
@@ -154,18 +155,20 @@
int res;
ipcarg_t rc;
-
+
ipc_call_t call;
ipc_callid_t callid;
-
- /* accept the phone */
+
+ /* Accept the phone */
callid = async_get_call(&call);
int mountee_phone = (int)IPC_GET_ARG1(call);
if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) ||
- mountee_phone < 0) {
+ (mountee_phone < 0)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
- ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */
+
+ /* Acknowledge the mountee_phone */
+ ipc_answer_0(callid, EOK);
res = async_data_write_receive(&callid, NULL);
@@ -176,8 +179,8 @@
return;
}
-
+
fs_node_t *fn;
res = ops->node_get(&fn, mp_dev_handle, mp_fs_index);
- if (res != EOK || !fn) {
+ if ((res != EOK) || (!fn)) {
ipc_hangup(mountee_phone);
ipc_answer_0(callid, combine_rc(res, ENOENT));
@@ -185,5 +188,5 @@
return;
}
-
+
if (fn->mp_data.mp_active) {
ipc_hangup(mountee_phone);
@@ -193,5 +196,5 @@
return;
}
-
+
rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
if (rc != EOK) {
@@ -215,4 +218,5 @@
fn->mp_data.phone = mountee_phone;
}
+
/*
* Do not release the FS node so that it stays in memory.
@@ -238,24 +242,24 @@
ipc_call_t *request)
{
- unsigned first = IPC_GET_ARG1(*request);
- unsigned last = IPC_GET_ARG2(*request);
- unsigned next = first;
+ unsigned int first = IPC_GET_ARG1(*request);
+ unsigned int last = IPC_GET_ARG2(*request);
+ unsigned int next = first;
dev_handle_t dev_handle = IPC_GET_ARG3(*request);
int lflag = IPC_GET_ARG4(*request);
- fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */
+ fs_index_t index = IPC_GET_ARG5(*request);
char component[NAME_MAX + 1];
int len;
int rc;
-
+
if (last < next)
last += PLB_SIZE;
-
+
fs_node_t *par = NULL;
fs_node_t *cur = NULL;
fs_node_t *tmp = NULL;
-
+
rc = ops->root_get(&cur, dev_handle);
on_error(rc, goto out_with_answer);
-
+
if (cur->mp_data.mp_active) {
ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
@@ -265,42 +269,45 @@
return;
}
-
+
+ /* Eat slash */
if (ops->plb_get_char(next) == '/')
- next++; /* eat slash */
+ next++;
while (next <= last) {
bool has_children;
-
+
rc = ops->has_children(&has_children, cur);
on_error(rc, goto out_with_answer);
if (!has_children)
break;
-
- /* collect the component */
+
+ /* Collect the component */
len = 0;
- while ((next <= last) && (ops->plb_get_char(next) != '/')) {
+ while ((next <= last) && (ops->plb_get_char(next) != '/')) {
if (len + 1 == NAME_MAX) {
- /* component length overflow */
+ /* Component length overflow */
ipc_answer_0(rid, ENAMETOOLONG);
goto out;
}
component[len++] = ops->plb_get_char(next);
- next++; /* process next character */
+ /* Process next character */
+ next++;
}
-
+
assert(len);
component[len] = '\0';
- next++; /* eat slash */
-
- /* match the component */
+ /* Eat slash */
+ next++;
+
+ /* Match the component */
rc = ops->match(&tmp, cur, component);
on_error(rc, goto out_with_answer);
-
- if (tmp && tmp->mp_data.mp_active) {
+
+ if ((tmp) && (tmp->mp_data.mp_active)) {
if (next > last)
next = last = first;
else
next--;
-
+
ipc_forward_slow(rid, tmp->mp_data.phone,
VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle,
@@ -312,19 +319,21 @@
return;
}
-
- /* handle miss: match amongst siblings */
+
+ /* Handle miss: match amongst siblings */
if (!tmp) {
if (next <= last) {
- /* there are unprocessed components */
+ /* There are unprocessed components */
ipc_answer_0(rid, ENOENT);
goto out;
}
- /* miss in the last component */
- if (lflag & (L_CREATE | L_LINK)) {
- /* request to create a new link */
+
+ /* Miss in the last component */
+ if (lflag & (L_CREATE | L_LINK)) {
+ /* Request to create a new link */
if (!ops->is_directory(cur)) {
ipc_answer_0(rid, ENOTDIR);
goto out;
}
+
fs_node_t *fn;
if (lflag & L_CREATE)
@@ -335,4 +344,5 @@
index);
on_error(rc, goto out_with_answer);
+
if (fn) {
rc = ops->link(cur, fn, component);
@@ -349,33 +359,34 @@
(void) ops->node_put(fn);
}
- } else {
+ } else
ipc_answer_0(rid, ENOSPC);
- }
+
goto out;
- }
+ }
+
ipc_answer_0(rid, ENOENT);
goto out;
}
-
+
if (par) {
rc = ops->node_put(par);
on_error(rc, goto out_with_answer);
}
-
- /* descend one level */
+
+ /* Descend one level */
par = cur;
cur = tmp;
tmp = NULL;
}
-
- /* handle miss: excessive components */
+
+ /* Handle miss: excessive components */
if (next <= last) {
bool has_children;
-
rc = ops->has_children(&has_children, cur);
on_error(rc, goto out_with_answer);
+
if (has_children)
goto skip_miss;
-
+
if (lflag & (L_CREATE | L_LINK)) {
if (!ops->is_directory(cur)) {
@@ -383,24 +394,28 @@
goto out;
}
-
- /* collect next component */
+
+ /* Collect next component */
len = 0;
while (next <= last) {
if (ops->plb_get_char(next) == '/') {
- /* more than one component */
+ /* More than one component */
ipc_answer_0(rid, ENOENT);
goto out;
}
+
if (len + 1 == NAME_MAX) {
- /* component length overflow */
+ /* Component length overflow */
ipc_answer_0(rid, ENAMETOOLONG);
goto out;
}
+
component[len++] = ops->plb_get_char(next);
- next++; /* process next character */
+ /* Process next character */
+ next++;
}
+
assert(len);
component[len] = '\0';
-
+
fs_node_t *fn;
if (lflag & L_CREATE)
@@ -409,4 +424,5 @@
rc = ops->node_get(&fn, dev_handle, index);
on_error(rc, goto out_with_answer);
+
if (fn) {
rc = ops->link(cur, fn, component);
@@ -423,22 +439,25 @@
(void) ops->node_put(fn);
}
- } else {
+ } else
ipc_answer_0(rid, ENOSPC);
- }
+
goto out;
}
+
ipc_answer_0(rid, ENOENT);
goto out;
}
+
skip_miss:
-
- /* handle hit */
+
+ /* Handle hit */
if (lflag & L_UNLINK) {
- unsigned old_lnkcnt = ops->lnkcnt_get(cur);
+ unsigned int old_lnkcnt = ops->lnkcnt_get(cur);
rc = ops->unlink(par, cur, component);
- ipc_answer_5(rid, (ipcarg_t)rc, fs_handle, dev_handle,
+ ipc_answer_5(rid, (ipcarg_t) rc, fs_handle, dev_handle,
ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
goto out;
}
+
if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) ||
(lflag & L_LINK)) {
@@ -446,27 +465,35 @@
goto out;
}
+
if ((lflag & L_FILE) && (ops->is_directory(cur))) {
ipc_answer_0(rid, EISDIR);
goto out;
}
+
if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
ipc_answer_0(rid, ENOTDIR);
goto out;
}
-
+
out_with_answer:
+
if (rc == EOK) {
- ipc_answer_5(rid, EOK, fs_handle, dev_handle,
+ if (lflag & L_OPEN)
+ rc = ops->node_open(cur);
+
+ ipc_answer_5(rid, rc, fs_handle, dev_handle,
ops->index_get(cur), ops->size_get(cur),
ops->lnkcnt_get(cur));
- } else {
+ } else
ipc_answer_0(rid, rc);
- }
-
+
out:
+
if (par)
(void) ops->node_put(par);
+
if (cur)
(void) ops->node_put(cur);
+
if (tmp)
(void) ops->node_put(tmp);
@@ -478,19 +505,19 @@
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+
fs_node_t *fn;
- int rc;
-
- rc = ops->node_get(&fn, dev_handle, index);
+ int rc = ops->node_get(&fn, dev_handle, index);
on_error(rc, answer_and_return(rid, rc));
-
+
ipc_callid_t callid;
size_t size;
- if (!async_data_read_receive(&callid, &size) ||
- size != sizeof(struct stat)) {
+ if ((!async_data_read_receive(&callid, &size)) ||
+ (size != sizeof(struct stat))) {
+ ops->node_put(fn);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
-
+
struct stat stat;
memset(&stat, 0, sizeof(struct stat));
@@ -499,8 +526,12 @@
stat.dev_handle = dev_handle;
stat.index = index;
- stat.lnkcnt = ops->lnkcnt_get(fn);
+ stat.lnkcnt = ops->lnkcnt_get(fn);
stat.is_file = ops->is_file(fn);
+ stat.is_directory = ops->is_directory(fn);
stat.size = ops->size_get(fn);
-
+ stat.device = ops->device_get(fn);
+
+ ops->node_put(fn);
+
async_data_read_finalize(callid, &stat, sizeof(struct stat));
ipc_answer_0(rid, EOK);
@@ -509,8 +540,8 @@
/** Open VFS triplet.
*
- * @param ops libfs operations structure with function pointers to
- * file system implementation
- * @param rid Request ID of the VFS_OUT_OPEN_NODE request.
- * @param request VFS_OUT_OPEN_NODE request data itself.
+ * @param ops libfs operations structure with function pointers to
+ * file system implementation
+ * @param rid Request ID of the VFS_OUT_OPEN_NODE request.
+ * @param request VFS_OUT_OPEN_NODE request data itself.
*
*/
@@ -531,5 +562,6 @@
}
- ipc_answer_3(rid, EOK, ops->size_get(fn), ops->lnkcnt_get(fn),
+ rc = ops->node_open(fn);
+ ipc_answer_3(rid, rc, ops->size_get(fn), ops->lnkcnt_get(fn),
(ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
Index: uspace/lib/libfs/libfs.h
===================================================================
--- uspace/lib/libfs/libfs.h (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/lib/libfs/libfs.h (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -64,4 +64,5 @@
int (* match)(fs_node_t **, fs_node_t *, const char *);
int (* node_get)(fs_node_t **, dev_handle_t, fs_index_t);
+ int (* node_open)(fs_node_t *);
int (* node_put)(fs_node_t *);
int (* create)(fs_node_t **, dev_handle_t, int);
@@ -76,8 +77,9 @@
fs_index_t (* index_get)(fs_node_t *);
size_t (* size_get)(fs_node_t *);
- unsigned (* lnkcnt_get)(fs_node_t *);
+ unsigned int (* lnkcnt_get)(fs_node_t *);
char (* plb_get_char)(unsigned pos);
bool (* is_directory)(fs_node_t *);
bool (* is_file)(fs_node_t *);
+ dev_handle_t (* device_get)(fs_node_t *);
} libfs_ops_t;
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/bd/ata_bd/ata_bd.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -66,5 +66,6 @@
#include "ata_bd.h"
-#define NAME "ata_bd"
+#define NAME "ata_bd"
+#define NAMESPACE "bd"
/** Physical block size. Should be always 512. */
@@ -135,11 +136,10 @@
if (disk[i].present == false)
continue;
-
- snprintf(name, 16, "disk%d", i);
+
+ snprintf(name, 16, "%s/disk%d", NAMESPACE, i);
rc = devmap_device_register(name, &disk[i].dev_handle);
if (rc != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
- printf(NAME ": Unable to register device %s.\n",
- name);
+ printf(NAME ": Unable to register device %s.\n", name);
return rc;
}
Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -50,5 +50,6 @@
#include
-#define NAME "gxe_bd"
+#define NAME "gxe_bd"
+#define NAMESPACE "bd"
enum {
@@ -141,10 +142,9 @@
for (i = 0; i < MAX_DISKS; i++) {
- snprintf(name, 16, "disk%d", i);
+ snprintf(name, 16, "%s/disk%d", NAMESPACE, i);
rc = devmap_device_register(name, &dev_handle[i]);
if (rc != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
- printf(NAME ": Unable to register device %s.\n",
- name);
+ printf(NAME ": Unable to register device %s.\n", name);
return rc;
}
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/bd/rd/rd.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -228,5 +228,5 @@
dev_handle_t dev_handle;
- if (devmap_device_register("initrd", &dev_handle) != EOK) {
+ if (devmap_device_register("bd/initrd", &dev_handle) != EOK) {
devmap_hangup_phone(DEVMAP_DRIVER);
printf(NAME ": Unable to register device\n");
Index: uspace/srv/console/console.c
===================================================================
--- uspace/srv/console/console.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/console/console.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -57,7 +57,6 @@
#include "screenbuffer.h"
-#define NAME "console"
-
-#define MAX_DEVICE_NAME 32
+#define NAME "console"
+#define NAMESPACE "term"
/** Phone to the keyboard driver. */
@@ -69,5 +68,5 @@
ipcarg_t cols; /**< Framebuffer columns */
ipcarg_t rows; /**< Framebuffer rows */
- int color_cap; /**< Color capabilities (FB_CCAP_xxx) */
+ int color_cap; /**< Color capabilities (FB_CCAP_xxx) */
} fb_info;
@@ -740,6 +739,6 @@
consoles[i].refcount = 0;
- char vc[MAX_DEVICE_NAME];
- snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
+ char vc[DEVMAP_NAME_MAXLEN + 1];
+ snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%u", NAMESPACE, i);
if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/devmap/devmap.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -68,4 +68,18 @@
} devmap_driver_t;
+/** Info about registered namespaces
+ *
+ */
+typedef struct {
+ /** Pointer to the previous and next device in the list of all namespaces */
+ link_t namespaces;
+ /** Unique namespace identifier */
+ dev_handle_t handle;
+ /** Namespace name */
+ char *name;
+ /** Reference count */
+ size_t refcnt;
+} devmap_namespace_t;
+
/** Info about registered device
*
@@ -77,6 +91,8 @@
owned by one driver */
link_t driver_devices;
- /** Unique device identifier */
+ /** Unique device identifier */
dev_handle_t handle;
+ /** Device namespace */
+ devmap_namespace_t *namespace;
/** Device name */
char *name;
@@ -86,4 +102,5 @@
LIST_INITIALIZE(devices_list);
+LIST_INITIALIZE(namespaces_list);
LIST_INITIALIZE(drivers_list);
@@ -117,70 +134,240 @@
}
+/** Convert fully qualified device name to namespace and device name.
+ *
+ * A fully qualified device name can be either a plain device name
+ * (then the namespace is considered to be an empty string) or consist
+ * of two components separated by a slash. No more than one slash
+ * is allowed.
+ *
+ */
+static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
+{
+ size_t cnt = 0;
+ size_t slash_offset = 0;
+ size_t slash_after = 0;
+
+ size_t offset = 0;
+ size_t offset_prev = 0;
+ wchar_t c;
+
+ while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
+ if (c == '/') {
+ cnt++;
+ slash_offset = offset_prev;
+ slash_after = offset;
+ }
+ offset_prev = offset;
+ }
+
+ /* More than one slash */
+ if (cnt > 1)
+ return false;
+
+ /* No slash -> namespace is empty */
+ if (cnt == 0) {
+ *ns_name = str_dup("");
+ if (*ns_name == NULL)
+ return false;
+
+ *name = str_dup(fqdn);
+ if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
+ free(*ns_name);
+ return false;
+ }
+
+ return true;
+ }
+
+ /* Exactly one slash */
+ *ns_name = str_ndup(fqdn, slash_offset);
+ if (*ns_name == NULL)
+ return false;
+
+ *name = str_dup(fqdn + slash_after);
+ if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
+ free(*ns_name);
+ return false;
+ }
+
+ return true;
+}
+
+/** Find namespace with given name.
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static devmap_namespace_t *devmap_namespace_find_name(const char *name)
+{
+ link_t *item = namespaces_list.next;
+
+ while (item != &namespaces_list) {
+ devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+ if (str_cmp(namespace->name, name) == 0)
+ return namespace;
+ item = item->next;
+ }
+
+ return NULL;
+}
+
+/** Find namespace with given handle.
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ * @todo: use hash table
+ *
+ */
+static devmap_namespace_t *devmap_namespace_find_handle(dev_handle_t handle)
+{
+ link_t *item = namespaces_list.next;
+
+ while (item != &namespaces_list) {
+ devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+ if (namespace->handle == handle)
+ return namespace;
+
+ item = item->next;
+ }
+
+ return NULL;
+}
+
/** Find device with given name.
*
- */
-static devmap_device_t *devmap_device_find_name(const char *name)
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static devmap_device_t *devmap_device_find_name(const char *ns_name,
+ const char *name)
{
link_t *item = devices_list.next;
- devmap_device_t *device = NULL;
while (item != &devices_list) {
- device = list_get_instance(item, devmap_device_t, devices);
- if (str_cmp(device->name, name) == 0)
- break;
+ devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
+ if ((str_cmp(device->namespace->name, ns_name) == 0) && (str_cmp(device->name, name) == 0))
+ return device;
item = item->next;
}
- if (item == &devices_list)
+ return NULL;
+}
+
+/** Find device with given handle.
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ * @todo: use hash table
+ *
+ */
+static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
+{
+ link_t *item = devices_list.next;
+
+ while (item != &devices_list) {
+ devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
+ if (device->handle == handle)
+ return device;
+
+ item = item->next;
+ }
+
+ return NULL;
+}
+
+/** Create a namespace (if not already present)
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
+{
+ devmap_namespace_t *namespace = devmap_namespace_find_name(ns_name);
+ if (namespace != NULL)
+ return namespace;
+
+ namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
+ if (namespace == NULL)
return NULL;
- device = list_get_instance(item, devmap_device_t, devices);
- return device;
-}
-
-/** Find device with given handle.
- *
- * @todo: use hash table
- *
- */
-static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
-{
- fibril_mutex_lock(&devices_list_mutex);
-
- link_t *item = (&devices_list)->next;
- devmap_device_t *device = NULL;
-
- while (item != &devices_list) {
- device = list_get_instance(item, devmap_device_t, devices);
- if (device->handle == handle)
- break;
- item = item->next;
- }
-
- if (item == &devices_list) {
- fibril_mutex_unlock(&devices_list_mutex);
+ namespace->name = str_dup(ns_name);
+ if (namespace->name == NULL) {
+ free(namespace);
return NULL;
}
- device = list_get_instance(item, devmap_device_t, devices);
-
- fibril_mutex_unlock(&devices_list_mutex);
-
- return device;
-}
-
-/**
- * Unregister device and free it. It's assumed that driver's device list is
- * already locked.
- */
-static int devmap_device_unregister_core(devmap_device_t *device)
-{
+ namespace->handle = devmap_create_handle();
+ namespace->refcnt = 0;
+
+ /*
+ * Insert new namespace into list of registered namespaces
+ */
+ list_append(&(namespace->namespaces), &namespaces_list);
+
+ return namespace;
+}
+
+/** Destroy a namespace (if it is no longer needed)
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_namespace_destroy(devmap_namespace_t *namespace)
+{
+ if (namespace->refcnt == 0) {
+ list_remove(&(namespace->namespaces));
+
+ free(namespace->name);
+ free(namespace);
+ }
+}
+
+/** Increase namespace reference count by including device
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_namespace_addref(devmap_namespace_t *namespace,
+ devmap_device_t *device)
+{
+ device->namespace = namespace;
+ namespace->refcnt++;
+}
+
+/** Decrease namespace reference count
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_namespace_delref(devmap_namespace_t *namespace)
+{
+ namespace->refcnt--;
+ devmap_namespace_destroy(namespace);
+}
+
+/** Unregister device and free it
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_device_unregister_core(devmap_device_t *device)
+{
+ devmap_namespace_delref(device->namespace);
list_remove(&(device->devices));
list_remove(&(device->driver_devices));
+ free(device->namespace);
free(device->name);
free(device);
-
- return EOK;
}
@@ -189,8 +376,6 @@
* drivers.
*/
-static void devmap_driver_register(devmap_driver_t **odriver)
-{
- *odriver = NULL;
-
+static devmap_driver_t *devmap_driver_register(void)
+{
ipc_call_t icall;
ipc_callid_t iid = async_get_call(&icall);
@@ -198,5 +383,5 @@
if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
ipc_answer_0(iid, EREFUSED);
- return;
+ return NULL;
}
@@ -205,5 +390,5 @@
if (driver == NULL) {
ipc_answer_0(iid, ENOMEM);
- return;
+ return NULL;
}
@@ -211,42 +396,10 @@
* Get driver name
*/
- ipc_callid_t callid;
- size_t name_size;
- if (!async_data_write_receive(&callid, &name_size)) {
+ int rc = async_data_string_receive(&driver->name, DEVMAP_NAME_MAXLEN);
+ if (rc != EOK) {
free(driver);
- ipc_answer_0(callid, EREFUSED);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- if (name_size > DEVMAP_NAME_MAXLEN) {
- free(driver);
- ipc_answer_0(callid, EINVAL);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- /*
- * Allocate buffer for device name.
- */
- driver->name = (char *) malloc(name_size + 1);
- if (driver->name == NULL) {
- free(driver);
- ipc_answer_0(callid, ENOMEM);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- /*
- * Send confirmation to sender and get data into buffer.
- */
- if (async_data_write_finalize(callid, driver->name, name_size) != EOK) {
- free(driver->name);
- free(driver);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- driver->name[name_size] = 0;
+ ipc_answer_0(iid, rc);
+ return NULL;
+ }
/* Initialize mutex for list of devices owned by this driver */
@@ -262,5 +415,5 @@
*/
ipc_call_t call;
- callid = async_get_call(&call);
+ ipc_callid_t callid = async_get_call(&call);
if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
@@ -270,5 +423,5 @@
free(driver);
ipc_answer_0(iid, ENOTSUP);
- return;
+ return NULL;
}
@@ -293,5 +446,5 @@
ipc_answer_0(iid, EOK);
- *odriver = driver;
+ return driver;
}
@@ -355,42 +508,43 @@
}
- /* Get device name */
- ipc_callid_t callid;
- size_t size;
- if (!async_data_write_receive(&callid, &size)) {
+ /* Get fqdn */
+ char *fqdn;
+ int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
+ if (rc != EOK) {
free(device);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- if (size > DEVMAP_NAME_MAXLEN) {
+ ipc_answer_0(iid, rc);
+ return;
+ }
+
+ char *ns_name;
+ if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
+ free(fqdn);
free(device);
- ipc_answer_0(callid, EINVAL);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- /* +1 for terminating \0 */
- device->name = (char *) malloc(size + 1);
-
- if (device->name == NULL) {
+ ipc_answer_0(iid, EINVAL);
+ return;
+ }
+
+ free(fqdn);
+
+ fibril_mutex_lock(&devices_list_mutex);
+
+ devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
+ free(ns_name);
+ if (!namespace) {
+ fibril_mutex_unlock(&devices_list_mutex);
free(device);
- ipc_answer_0(callid, ENOMEM);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- async_data_write_finalize(callid, device->name, size);
- device->name[size] = 0;
+ ipc_answer_0(iid, ENOMEM);
+ return;
+ }
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
- fibril_mutex_lock(&devices_list_mutex);
-
- /* Check that device with such name is not already registered */
- if (NULL != devmap_device_find_name(device->name)) {
- printf(NAME ": Device '%s' already registered\n", device->name);
+ /* Check that device is not already registered */
+ if (devmap_device_find_name(namespace->name, device->name) != NULL) {
+ printf(NAME ": Device '%s/%s' already registered\n", device->namespace, device->name);
+ devmap_namespace_destroy(namespace);
fibril_mutex_unlock(&devices_list_mutex);
+ free(device->namespace);
free(device->name);
free(device);
@@ -402,4 +556,5 @@
device->handle = devmap_create_handle();
+ devmap_namespace_addref(namespace, device);
device->driver = driver;
@@ -437,4 +592,6 @@
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
{
+ fibril_mutex_lock(&devices_list_mutex);
+
/*
* Get handle from request
@@ -450,4 +607,6 @@
ipc_forward_fast(callid, dev->driver->phone, dev->handle,
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
+
+ fibril_mutex_unlock(&devices_list_mutex);
}
@@ -458,53 +617,34 @@
*
*/
-static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
- /*
- * Wait for incoming message with device name (but do not
- * read the name itself until the buffer is allocated).
- */
- ipc_callid_t callid;
- size_t size;
- if (!async_data_write_receive(&callid, &size)) {
- ipc_answer_0(callid, EREFUSED);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
- ipc_answer_0(callid, EINVAL);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- /*
- * Allocate buffer for device name.
- */
- char *name = (char *) malloc(size + 1);
- if (name == NULL) {
- ipc_answer_0(callid, ENOMEM);
- ipc_answer_0(iid, EREFUSED);
- return;
- }
-
- /*
- * Send confirmation to sender and get data into buffer.
- */
- ipcarg_t retval = async_data_write_finalize(callid, name, size);
- if (retval != EOK) {
- ipc_answer_0(iid, EREFUSED);
- free(name);
- return;
- }
- name[size] = '\0';
+static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+ char *fqdn;
+
+ /* Get fqdn */
+ int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
+ if (rc != EOK) {
+ ipc_answer_0(iid, rc);
+ return;
+ }
+
+ char *ns_name;
+ char *name;
+ if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
+ free(fqdn);
+ ipc_answer_0(iid, EINVAL);
+ return;
+ }
+
+ free(fqdn);
fibril_mutex_lock(&devices_list_mutex);
const devmap_device_t *dev;
+
recheck:
-
+
/*
* Find device name in the list of known devices.
*/
- dev = devmap_device_find_name(name);
+ dev = devmap_device_find_name(ns_name, name);
/*
@@ -520,4 +660,5 @@
ipc_answer_0(iid, ENOENT);
+ free(ns_name);
free(name);
fibril_mutex_unlock(&devices_list_mutex);
@@ -527,51 +668,96 @@
ipc_answer_1(iid, EOK, dev->handle);
+ free(ns_name);
free(name);
}
-/** Find name of device identified by id and send it to caller.
- *
- */
-static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
-{
- const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
+/** Find handle for namespace identified by name.
+ *
+ * In answer will be send EOK and device handle in arg1 or a error
+ * code from errno.h.
+ *
+ */
+static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+ char *name;
+
+ /* Get device name */
+ int rc = async_data_string_receive(&name, DEVMAP_NAME_MAXLEN);
+ if (rc != EOK) {
+ ipc_answer_0(iid, rc);
+ return;
+ }
+
+ fibril_mutex_lock(&devices_list_mutex);
+ const devmap_namespace_t *namespace;
+
+recheck:
/*
- * Device not found.
+ * Find namespace name in the list of known namespaces.
*/
- if (device == NULL) {
+ namespace = devmap_namespace_find_name(name);
+
+ /*
+ * Namespace was not found.
+ */
+ if (namespace == NULL) {
+ if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
+ /* Blocking lookup */
+ fibril_condvar_wait(&devices_list_cv,
+ &devices_list_mutex);
+ goto recheck;
+ }
+
ipc_answer_0(iid, ENOENT);
- return;
- }
-
- ipc_answer_0(iid, EOK);
-
- /* FIXME:
- * We have no channel from DEVMAP to client, therefore
- * sending must be initiated by client.
- *
- * size_t name_size = str_size(device->name);
- *
- * int rc = async_data_write_send(phone, device->name, name_size);
- * if (rc != EOK) {
- * async_wait_for(req, NULL);
- * return rc;
- * }
- */
-
- /* TODO: send name in response */
-}
-
-static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
+ free(name);
+ fibril_mutex_unlock(&devices_list_mutex);
+ return;
+ }
+ fibril_mutex_unlock(&devices_list_mutex);
+
+ ipc_answer_1(iid, EOK, namespace->handle);
+ free(name);
+}
+
+static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&devices_list_mutex);
- ipc_answer_1(iid, EOK, list_count(&devices_list));
+
+ devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+ if (namespace == NULL) {
+ devmap_device_t *dev = devmap_device_find_handle(IPC_GET_ARG1(*icall));
+ if (dev == NULL)
+ ipc_answer_1(iid, EOK, DEV_HANDLE_NONE);
+ else
+ ipc_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
+ } else
+ ipc_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
+
fibril_mutex_unlock(&devices_list_mutex);
}
-static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
+static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&devices_list_mutex);
-
+ ipc_answer_1(iid, EOK, list_count(&namespaces_list));
+ fibril_mutex_unlock(&devices_list_mutex);
+}
+
+static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
+{
+ fibril_mutex_lock(&devices_list_mutex);
+
+ devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+ if (namespace == NULL)
+ ipc_answer_0(iid, EEXISTS);
+ else
+ ipc_answer_1(iid, EOK, namespace->refcnt);
+
+ fibril_mutex_unlock(&devices_list_mutex);
+}
+
+static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
+{
ipc_callid_t callid;
size_t size;
@@ -584,9 +770,80 @@
if ((size % sizeof(dev_desc_t)) != 0) {
ipc_answer_0(callid, EINVAL);
+ ipc_answer_0(iid, EINVAL);
+ return;
+ }
+
+ fibril_mutex_lock(&devices_list_mutex);
+
+ size_t count = size / sizeof(dev_desc_t);
+ if (count != list_count(&namespaces_list)) {
+ ipc_answer_0(callid, EOVERFLOW);
+ ipc_answer_0(iid, EOVERFLOW);
+ return;
+ }
+
+ dev_desc_t *desc = (dev_desc_t *) malloc(size);
+ if (desc == NULL) {
+ ipc_answer_0(callid, ENOMEM);
+ ipc_answer_0(iid, ENOMEM);
+ return;
+ }
+
+ link_t *item = namespaces_list.next;
+ size_t pos = 0;
+ while (item != &namespaces_list) {
+ devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+
+ desc[pos].handle = namespace->handle;
+ str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
+ pos++;
+
+ item = item->next;
+ }
+
+ ipcarg_t retval = async_data_read_finalize(callid, desc, size);
+
+ free(desc);
+ fibril_mutex_unlock(&devices_list_mutex);
+
+ ipc_answer_0(iid, retval);
+}
+
+static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
+{
+ /* FIXME: Use faster algorithm which can make better use
+ of namespaces */
+
+ ipc_callid_t callid;
+ size_t size;
+ if (!async_data_read_receive(&callid, &size)) {
+ ipc_answer_0(callid, EREFUSED);
ipc_answer_0(iid, EREFUSED);
return;
}
+ if ((size % sizeof(dev_desc_t)) != 0) {
+ ipc_answer_0(callid, EINVAL);
+ ipc_answer_0(iid, EINVAL);
+ return;
+ }
+
+ fibril_mutex_lock(&devices_list_mutex);
+
+ devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+ if (namespace == NULL) {
+ fibril_mutex_unlock(&devices_list_mutex);
+ ipc_answer_0(callid, ENOENT);
+ ipc_answer_0(iid, ENOENT);
+ return;
+ }
+
size_t count = size / sizeof(dev_desc_t);
+ if (count != namespace->refcnt) {
+ ipc_answer_0(callid, EOVERFLOW);
+ ipc_answer_0(iid, EOVERFLOW);
+ return;
+ }
+
dev_desc_t *desc = (dev_desc_t *) malloc(size);
if (desc == NULL) {
@@ -596,28 +853,24 @@
}
+ link_t *item = devices_list.next;
size_t pos = 0;
- link_t *item = devices_list.next;
-
- while ((item != &devices_list) && (pos < count)) {
+ while (item != &devices_list) {
devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
- desc[pos].handle = device->handle;
- str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
- pos++;
+ if (device->namespace == namespace) {
+ desc[pos].handle = device->handle;
+ str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
+ pos++;
+ }
+
item = item->next;
}
- ipcarg_t retval = async_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
- if (retval != EOK) {
- ipc_answer_0(iid, EREFUSED);
- free(desc);
- return;
- }
+ ipcarg_t retval = async_data_read_finalize(callid, desc, size);
free(desc);
-
fibril_mutex_unlock(&devices_list_mutex);
- ipc_answer_1(iid, EOK, pos);
+ ipc_answer_0(iid, retval);
}
@@ -642,5 +895,14 @@
}
- /* Create NULL device entry */
+ char null[DEVMAP_NAME_MAXLEN];
+ snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
+
+ char *dev_name = str_dup(null);
+ if (dev_name == NULL) {
+ fibril_mutex_unlock(&null_devices_mutex);
+ ipc_answer_0(iid, ENOMEM);
+ return;
+ }
+
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
if (device == NULL) {
@@ -650,11 +912,10 @@
}
- char null[DEVMAP_NAME_MAXLEN];
- snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
-
- device->name = str_dup(null);
- if (device->name == NULL) {
+ fibril_mutex_lock(&devices_list_mutex);
+
+ devmap_namespace_t *namespace = devmap_namespace_create("null");
+ if (!namespace) {
+ fibril_mutex_lock(&devices_list_mutex);
fibril_mutex_unlock(&null_devices_mutex);
- free(device);
ipc_answer_0(iid, ENOMEM);
return;
@@ -663,10 +924,11 @@
list_initialize(&(device->devices));
list_initialize(&(device->driver_devices));
-
- fibril_mutex_lock(&devices_list_mutex);
/* Get unique device handle */
device->handle = devmap_create_handle();
device->driver = NULL;
+
+ devmap_namespace_addref(namespace, device);
+ device->name = dev_name;
/* Insert device into list of all devices
@@ -692,5 +954,8 @@
}
+ fibril_mutex_lock(&devices_list_mutex);
devmap_device_unregister_core(null_devices[i]);
+ fibril_mutex_unlock(&devices_list_mutex);
+
null_devices[i] = NULL;
@@ -725,8 +990,6 @@
ipc_answer_0(iid, EOK);
- devmap_driver_t *driver = NULL;
- devmap_driver_register(&driver);
-
- if (NULL == driver)
+ devmap_driver_t *driver = devmap_driver_register();
+ if (driver == NULL)
return;
@@ -755,8 +1018,8 @@
break;
case DEVMAP_DEVICE_GET_HANDLE:
- devmap_get_handle(callid, &call);
- break;
- case DEVMAP_DEVICE_GET_NAME:
- devmap_get_name(callid, &call);
+ devmap_device_get_handle(callid, &call);
+ break;
+ case DEVMAP_NAMESPACE_GET_HANDLE:
+ devmap_namespace_get_handle(callid, &call);
break;
default:
@@ -793,19 +1056,28 @@
continue;
case DEVMAP_DEVICE_GET_HANDLE:
- devmap_get_handle(callid, &call);
- break;
- case DEVMAP_DEVICE_GET_NAME:
- devmap_get_name(callid, &call);
- break;
- case DEVMAP_DEVICE_NULL_CREATE:
+ devmap_device_get_handle(callid, &call);
+ break;
+ case DEVMAP_NAMESPACE_GET_HANDLE:
+ devmap_namespace_get_handle(callid, &call);
+ break;
+ case DEVMAP_HANDLE_PROBE:
+ devmap_handle_probe(callid, &call);
+ break;
+ case DEVMAP_NULL_CREATE:
devmap_null_create(callid, &call);
break;
- case DEVMAP_DEVICE_NULL_DESTROY:
+ case DEVMAP_NULL_DESTROY:
devmap_null_destroy(callid, &call);
break;
- case DEVMAP_DEVICE_GET_COUNT:
- devmap_get_count(callid, &call);
- break;
- case DEVMAP_DEVICE_GET_DEVICES:
+ case DEVMAP_GET_NAMESPACE_COUNT:
+ devmap_get_namespace_count(callid, &call);
+ break;
+ case DEVMAP_GET_DEVICE_COUNT:
+ devmap_get_device_count(callid, &call);
+ break;
+ case DEVMAP_GET_NAMESPACES:
+ devmap_get_namespaces(callid, &call);
+ break;
+ case DEVMAP_GET_DEVICES:
devmap_get_devices(callid, &call);
break;
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/fs/devfs/devfs_ops.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -44,9 +44,15 @@
#include
#include
+#include
#include
+#include
+#include
#include "devfs.h"
#include "devfs_ops.h"
-#define PLB_GET_CHAR(pos) (devfs_reg.plb_ro[pos % PLB_SIZE])
+typedef struct {
+ devmap_handle_type_t type;
+ dev_handle_t handle;
+} devfs_node_t;
/** Opened devices structure */
@@ -91,4 +97,309 @@
};
+static int devfs_node_get_internal(fs_node_t **rfn, devmap_handle_type_t type,
+ dev_handle_t handle)
+{
+ devfs_node_t *node = (devfs_node_t *) malloc(sizeof(devfs_node_t));
+ if (node == NULL) {
+ *rfn = NULL;
+ return ENOMEM;
+ }
+
+ *rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
+ if (*rfn == NULL) {
+ free(node);
+ *rfn = NULL;
+ return ENOMEM;
+ }
+
+ fs_node_initialize(*rfn);
+ node->type = type;
+ node->handle = handle;
+
+ (*rfn)->data = node;
+ return EOK;
+}
+
+static int devfs_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
+{
+ return devfs_node_get_internal(rfn, DEV_HANDLE_NONE, 0);
+}
+
+static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+ devfs_node_t *node = (devfs_node_t *) pfn->data;
+
+ if (node->handle == 0) {
+ /* Root directory */
+
+ dev_desc_t *devs;
+ size_t count = devmap_get_namespaces(&devs);
+
+ if (count > 0) {
+ size_t pos;
+ for (pos = 0; pos < count; pos++) {
+ /* Ignore root namespace */
+ if (str_cmp(devs[pos].name, "") == 0)
+ continue;
+
+ if (str_cmp(devs[pos].name, component) == 0) {
+ free(devs);
+ return devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
+ }
+ }
+
+ free(devs);
+ }
+
+ /* Search root namespace */
+ dev_handle_t namespace;
+ if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
+ count = devmap_get_devices(namespace, &devs);
+
+ if (count > 0) {
+ size_t pos;
+ for (pos = 0; pos < count; pos++) {
+ if (str_cmp(devs[pos].name, component) == 0) {
+ free(devs);
+ return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
+ }
+ }
+
+ free(devs);
+ }
+ }
+
+ *rfn = NULL;
+ return EOK;
+ }
+
+ if (node->type == DEV_HANDLE_NAMESPACE) {
+ /* Namespace directory */
+
+ dev_desc_t *devs;
+ size_t count = devmap_get_devices(node->handle, &devs);
+ if (count > 0) {
+ size_t pos;
+ for (pos = 0; pos < count; pos++) {
+ if (str_cmp(devs[pos].name, component) == 0) {
+ free(devs);
+ return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
+ }
+ }
+
+ free(devs);
+ }
+
+ *rfn = NULL;
+ return EOK;
+ }
+
+ *rfn = NULL;
+ return EOK;
+}
+
+static int devfs_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
+{
+ return devfs_node_get_internal(rfn, devmap_handle_probe(index), index);
+}
+
+static int devfs_node_open(fs_node_t *fn)
+{
+ devfs_node_t *node = (devfs_node_t *) fn->data;
+
+ if (node->handle == 0) {
+ /* Root directory */
+ return EOK;
+ }
+
+ devmap_handle_type_t type = devmap_handle_probe(node->handle);
+
+ if (type == DEV_HANDLE_NAMESPACE) {
+ /* Namespace directory */
+ return EOK;
+ }
+
+ if (type == DEV_HANDLE_DEVICE) {
+ /* Device node */
+
+ unsigned long key[] = {
+ [DEVICES_KEY_HANDLE] = (unsigned long) node->handle
+ };
+
+ fibril_mutex_lock(&devices_mutex);
+ link_t *lnk = hash_table_find(&devices, key);
+ if (lnk == NULL) {
+ device_t *dev = (device_t *) malloc(sizeof(device_t));
+ if (dev == NULL) {
+ fibril_mutex_unlock(&devices_mutex);
+ return ENOMEM;
+ }
+
+ int phone = devmap_device_connect(node->handle, 0);
+ if (phone < 0) {
+ fibril_mutex_unlock(&devices_mutex);
+ free(dev);
+ return ENOENT;
+ }
+
+ dev->handle = node->handle;
+ dev->phone = phone;
+ dev->refcount = 1;
+
+ hash_table_insert(&devices, key, &dev->link);
+ } else {
+ device_t *dev = hash_table_get_instance(lnk, device_t, link);
+ dev->refcount++;
+ }
+
+ fibril_mutex_unlock(&devices_mutex);
+
+ return EOK;
+ }
+
+ return ENOENT;
+}
+
+static int devfs_node_put(fs_node_t *fn)
+{
+ free(fn->data);
+ free(fn);
+ return EOK;
+}
+
+static int devfs_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int lflag)
+{
+ assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
+
+ *rfn = NULL;
+ return ENOTSUP;
+}
+
+static int devfs_destroy_node(fs_node_t *fn)
+{
+ return ENOTSUP;
+}
+
+static int devfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+ return ENOTSUP;
+}
+
+static int devfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+ return ENOTSUP;
+}
+
+static int devfs_has_children(bool *has_children, fs_node_t *fn)
+{
+ devfs_node_t *node = (devfs_node_t *) fn->data;
+
+ if (node->handle == 0) {
+ size_t count = devmap_count_namespaces();
+ if (count > 0) {
+ *has_children = true;
+ return EOK;
+ }
+
+ /* Root namespace */
+ dev_handle_t namespace;
+ if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
+ count = devmap_count_devices(namespace);
+ if (count > 0) {
+ *has_children = true;
+ return EOK;
+ }
+ }
+
+ *has_children = false;
+ return EOK;
+ }
+
+ if (node->type == DEV_HANDLE_NAMESPACE) {
+ size_t count = devmap_count_devices(node->handle);
+ if (count > 0) {
+ *has_children = true;
+ return EOK;
+ }
+
+ *has_children = false;
+ return EOK;
+ }
+
+ *has_children = false;
+ return EOK;
+}
+
+static fs_index_t devfs_index_get(fs_node_t *fn)
+{
+ devfs_node_t *node = (devfs_node_t *) fn->data;
+ return node->handle;
+}
+
+static size_t devfs_size_get(fs_node_t *fn)
+{
+ return 0;
+}
+
+static unsigned int devfs_lnkcnt_get(fs_node_t *fn)
+{
+ devfs_node_t *node = (devfs_node_t *) fn->data;
+
+ if (node->handle == 0)
+ return 0;
+
+ return 1;
+}
+
+static char devfs_plb_get_char(unsigned pos)
+{
+ return devfs_reg.plb_ro[pos % PLB_SIZE];
+}
+
+static bool devfs_is_directory(fs_node_t *fn)
+{
+ devfs_node_t *node = (devfs_node_t *) fn->data;
+
+ return ((node->type == DEV_HANDLE_NONE) || (node->type == DEV_HANDLE_NAMESPACE));
+}
+
+static bool devfs_is_file(fs_node_t *fn)
+{
+ devfs_node_t *node = (devfs_node_t *) fn->data;
+
+ return (node->type == DEV_HANDLE_DEVICE);
+}
+
+static dev_handle_t devfs_device_get(fs_node_t *fn)
+{
+ devfs_node_t *node = (devfs_node_t *) fn->data;
+
+ if (node->type == DEV_HANDLE_DEVICE)
+ return node->handle;
+
+ return 0;
+}
+
+/** libfs operations */
+libfs_ops_t devfs_libfs_ops = {
+ .root_get = devfs_root_get,
+ .match = devfs_match,
+ .node_get = devfs_node_get,
+ .node_open = devfs_node_open,
+ .node_put = devfs_node_put,
+ .create = devfs_create_node,
+ .destroy = devfs_destroy_node,
+ .link = devfs_link_node,
+ .unlink = devfs_unlink_node,
+ .has_children = devfs_has_children,
+ .index_get = devfs_index_get,
+ .size_get = devfs_size_get,
+ .lnkcnt_get = devfs_lnkcnt_get,
+ .plb_get_char = devfs_plb_get_char,
+ .is_directory = devfs_is_directory,
+ .is_file = devfs_is_file,
+ .device_get = devfs_device_get
+};
+
bool devfs_init(void)
{
@@ -105,29 +416,14 @@
void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
{
+ char *opts;
+
/* Accept the mount options */
- ipc_callid_t callid;
- size_t size;
- if (!async_data_write_receive(&callid, &size)) {
- ipc_answer_0(callid, EINVAL);
- ipc_answer_0(rid, EINVAL);
- return;
- }
-
- char *opts = malloc(size + 1);
- if (!opts) {
- ipc_answer_0(callid, ENOMEM);
- ipc_answer_0(rid, ENOMEM);
- return;
- }
-
- ipcarg_t retval = async_data_write_finalize(callid, opts, size);
+ ipcarg_t retval = async_data_string_receive(&opts, 0);
if (retval != EOK) {
ipc_answer_0(rid, retval);
- free(opts);
return;
}
free(opts);
-
ipc_answer_3(rid, EOK, 0, 0, 0);
}
@@ -135,194 +431,111 @@
void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
{
- ipc_answer_0(rid, ENOTSUP);
+ libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
}
void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
{
- ipcarg_t first = IPC_GET_ARG1(*request);
- ipcarg_t last = IPC_GET_ARG2(*request);
- dev_handle_t dev_handle = IPC_GET_ARG3(*request);
- ipcarg_t lflag = IPC_GET_ARG4(*request);
- fs_index_t index = IPC_GET_ARG5(*request);
-
- /* Hierarchy is flat, no altroot is supported */
- if (index != 0) {
- ipc_answer_0(rid, ENOENT);
- return;
- }
-
- if ((lflag & L_LINK) || (lflag & L_UNLINK)) {
- ipc_answer_0(rid, ENOTSUP);
- return;
- }
-
- /* Eat slash */
- if (PLB_GET_CHAR(first) == '/') {
- first++;
- first %= PLB_SIZE;
- }
-
- if (first >= last) {
- /* Root entry */
- if (!(lflag & L_FILE))
- ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0);
- else
- ipc_answer_0(rid, ENOENT);
- } else {
- if (!(lflag & L_DIRECTORY)) {
- size_t len;
- if (last >= first)
- len = last - first + 1;
- else
- len = first + PLB_SIZE - last + 1;
+ libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
+}
+
+void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
+{
+ libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
+}
+
+void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
+{
+ libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
+}
+
+void devfs_read(ipc_callid_t rid, ipc_call_t *request)
+{
+ fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+ off_t pos = (off_t) IPC_GET_ARG3(*request);
+
+ if (index == 0) {
+ ipc_callid_t callid;
+ size_t size;
+ if (!async_data_read_receive(&callid, &size)) {
+ ipc_answer_0(callid, EINVAL);
+ ipc_answer_0(rid, EINVAL);
+ return;
+ }
+
+ dev_desc_t *desc;
+ size_t count = devmap_get_namespaces(&desc);
+
+ /* Get rid of root namespace */
+ size_t i;
+ for (i = 0; i < count; i++) {
+ if (str_cmp(desc[i].name, "") == 0) {
+ if (pos >= i)
+ pos++;
+
+ break;
+ }
+ }
+
+ if (pos < count) {
+ async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+ free(desc);
+ ipc_answer_1(rid, EOK, 1);
+ return;
+ }
+
+ free(desc);
+ pos -= count;
+
+ /* Search root namespace */
+ dev_handle_t namespace;
+ if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
+ count = devmap_get_devices(namespace, &desc);
- char *name = (char *) malloc(len + 1);
- if (name == NULL) {
- ipc_answer_0(rid, ENOMEM);
+ if (pos < count) {
+ async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+ free(desc);
+ ipc_answer_1(rid, EOK, 1);
return;
}
- size_t i;
- for (i = 0; i < len; i++)
- name[i] = PLB_GET_CHAR(first + i);
-
- name[len] = 0;
-
- dev_handle_t handle;
- if (devmap_device_get_handle(name, &handle, 0) != EOK) {
- free(name);
- ipc_answer_0(rid, ENOENT);
- return;
- }
-
- if (lflag & L_OPEN) {
- unsigned long key[] = {
- [DEVICES_KEY_HANDLE] = (unsigned long) handle
- };
-
- fibril_mutex_lock(&devices_mutex);
- link_t *lnk = hash_table_find(&devices, key);
- if (lnk == NULL) {
- int phone = devmap_device_connect(handle, 0);
- if (phone < 0) {
- fibril_mutex_unlock(&devices_mutex);
- free(name);
- ipc_answer_0(rid, ENOENT);
- return;
- }
-
- device_t *dev = (device_t *) malloc(sizeof(device_t));
- if (dev == NULL) {
- fibril_mutex_unlock(&devices_mutex);
- free(name);
- ipc_answer_0(rid, ENOMEM);
- return;
- }
-
- dev->handle = handle;
- dev->phone = phone;
- dev->refcount = 1;
-
- hash_table_insert(&devices, key, &dev->link);
- } else {
- device_t *dev = hash_table_get_instance(lnk, device_t, link);
- dev->refcount++;
- }
- fibril_mutex_unlock(&devices_mutex);
- }
-
- free(name);
-
- ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1);
- } else
- ipc_answer_0(rid, ENOENT);
- }
-}
-
-void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
- dev_handle_t handle = IPC_GET_ARG2(*request);
-
- unsigned long key[] = {
- [DEVICES_KEY_HANDLE] = (unsigned long) handle
- };
-
- fibril_mutex_lock(&devices_mutex);
- link_t *lnk = hash_table_find(&devices, key);
- if (lnk == NULL) {
- int phone = devmap_device_connect(handle, 0);
- if (phone < 0) {
- fibril_mutex_unlock(&devices_mutex);
- ipc_answer_0(rid, ENOENT);
- return;
- }
-
- device_t *dev = (device_t *) malloc(sizeof(device_t));
- if (dev == NULL) {
- fibril_mutex_unlock(&devices_mutex);
- ipc_answer_0(rid, ENOMEM);
- return;
- }
-
- dev->handle = handle;
- dev->phone = phone;
- dev->refcount = 1;
-
- hash_table_insert(&devices, key, &dev->link);
- } else {
- device_t *dev = hash_table_get_instance(lnk, device_t, link);
- dev->refcount++;
- }
- fibril_mutex_unlock(&devices_mutex);
-
- ipc_answer_3(rid, EOK, 0, 1, L_FILE);
-}
-
-void devfs_stat(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);
-
- ipc_callid_t callid;
- size_t size;
- if (!async_data_read_receive(&callid, &size) ||
- size != sizeof(struct stat)) {
- ipc_answer_0(callid, EINVAL);
- ipc_answer_0(rid, EINVAL);
- return;
- }
-
- struct stat stat;
- memset(&stat, 0, sizeof(struct stat));
-
- stat.fs_handle = devfs_reg.fs_handle;
- stat.dev_handle = dev_handle;
- stat.index = index;
- stat.lnkcnt = 1;
- stat.is_file = (index != 0);
- stat.size = 0;
-
- if (index != 0) {
- unsigned long key[] = {
- [DEVICES_KEY_HANDLE] = (unsigned long) index
- };
-
- fibril_mutex_lock(&devices_mutex);
- link_t *lnk = hash_table_find(&devices, key);
- if (lnk != NULL)
- stat.devfs_stat.device = (dev_handle_t)index;
- fibril_mutex_unlock(&devices_mutex);
- }
-
- async_data_read_finalize(callid, &stat, sizeof(struct stat));
- ipc_answer_0(rid, EOK);
-}
-
-void devfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
- fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
- off_t pos = (off_t) IPC_GET_ARG3(*request);
-
- if (index != 0) {
+ free(desc);
+ }
+
+ ipc_answer_0(callid, ENOENT);
+ ipc_answer_1(rid, ENOENT, 0);
+ return;
+ }
+
+ devmap_handle_type_t type = devmap_handle_probe(index);
+
+ if (type == DEV_HANDLE_NAMESPACE) {
+ /* Namespace directory */
+ ipc_callid_t callid;
+ size_t size;
+ if (!async_data_read_receive(&callid, &size)) {
+ ipc_answer_0(callid, EINVAL);
+ ipc_answer_0(rid, EINVAL);
+ return;
+ }
+
+ dev_desc_t *desc;
+ size_t count = devmap_get_devices(index, &desc);
+
+ if (pos < count) {
+ async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+ free(desc);
+ ipc_answer_1(rid, EOK, 1);
+ return;
+ }
+
+ free(desc);
+ ipc_answer_0(callid, ENOENT);
+ ipc_answer_1(rid, ENOENT, 0);
+ return;
+ }
+
+ if (type == DEV_HANDLE_DEVICE) {
+ /* Device node */
+
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
@@ -364,35 +577,8 @@
/* Driver reply is the final result of the whole operation */
ipc_answer_1(rid, rc, bytes);
- } else {
- ipc_callid_t callid;
- size_t size;
- if (!async_data_read_receive(&callid, &size)) {
- ipc_answer_0(callid, EINVAL);
- ipc_answer_0(rid, EINVAL);
- return;
- }
-
- size_t count = devmap_device_get_count();
- dev_desc_t *desc = malloc(count * sizeof(dev_desc_t));
- if (desc == NULL) {
- ipc_answer_0(callid, ENOMEM);
- ipc_answer_1(rid, ENOMEM, 0);
- return;
- }
-
- size_t max = devmap_device_get_devices(count, desc);
-
- if (pos < max) {
- async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
- } else {
- ipc_answer_0(callid, ENOENT);
- ipc_answer_1(rid, ENOENT, 0);
- return;
- }
-
- free(desc);
-
- ipc_answer_1(rid, EOK, 1);
- }
+ return;
+ }
+
+ ipc_answer_0(rid, ENOENT);
}
@@ -402,5 +588,19 @@
off_t pos = (off_t) IPC_GET_ARG3(*request);
- if (index != 0) {
+ if (index == 0) {
+ ipc_answer_0(rid, ENOTSUP);
+ return;
+ }
+
+ devmap_handle_type_t type = devmap_handle_probe(index);
+
+ if (type == DEV_HANDLE_NAMESPACE) {
+ /* Namespace directory */
+ ipc_answer_0(rid, ENOTSUP);
+ return;
+ }
+
+ if (type == DEV_HANDLE_DEVICE) {
+ /* Device node */
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
@@ -443,8 +643,8 @@
/* Driver reply is the final result of the whole operation */
ipc_answer_1(rid, rc, bytes);
- } else {
- /* Read-only filesystem */
- ipc_answer_0(rid, ENOTSUP);
- }
+ return;
+ }
+
+ ipc_answer_0(rid, ENOENT);
}
@@ -458,5 +658,18 @@
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
- if (index != 0) {
+ if (index == 0) {
+ ipc_answer_0(rid, EOK);
+ return;
+ }
+
+ devmap_handle_type_t type = devmap_handle_probe(index);
+
+ if (type == DEV_HANDLE_NAMESPACE) {
+ /* Namespace directory */
+ ipc_answer_0(rid, EOK);
+ return;
+ }
+
+ if (type == DEV_HANDLE_DEVICE) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
@@ -482,6 +695,8 @@
ipc_answer_0(rid, EOK);
- } else
- ipc_answer_0(rid, ENOTSUP);
+ return;
+ }
+
+ ipc_answer_0(rid, ENOENT);
}
@@ -490,5 +705,18 @@
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
- if (index != 0) {
+ if (index == 0) {
+ ipc_answer_0(rid, EOK);
+ return;
+ }
+
+ devmap_handle_type_t type = devmap_handle_probe(index);
+
+ if (type == DEV_HANDLE_NAMESPACE) {
+ /* Namespace directory */
+ ipc_answer_0(rid, EOK);
+ return;
+ }
+
+ if (type == DEV_HANDLE_DEVICE) {
unsigned long key[] = {
[DEVICES_KEY_HANDLE] = (unsigned long) index
@@ -518,6 +746,8 @@
/* Driver reply is the final result of the whole operation */
ipc_answer_0(rid, rc);
- } else
- ipc_answer_0(rid, ENOTSUP);
+ return;
+ }
+
+ ipc_answer_0(rid, ENOENT);
}
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/fs/fat/fat_ops.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -71,4 +71,5 @@
static int fat_match(fs_node_t **, fs_node_t *, const char *);
static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t);
+static int fat_node_open(fs_node_t *);
static int fat_node_put(fs_node_t *);
static int fat_create_node(fs_node_t **, dev_handle_t, int);
@@ -83,4 +84,5 @@
static bool fat_is_directory(fs_node_t *);
static bool fat_is_file(fs_node_t *node);
+static dev_handle_t fat_device_get(fs_node_t *node);
/*
@@ -407,4 +409,13 @@
}
+int fat_node_open(fs_node_t *fn)
+{
+ /*
+ * Opening a file is stateless, nothing
+ * to be done here.
+ */
+ return EOK;
+}
+
int fat_node_put(fs_node_t *fn)
{
@@ -867,4 +878,9 @@
}
+dev_handle_t fat_device_get(fs_node_t *node)
+{
+ return 0;
+}
+
/** libfs operations */
libfs_ops_t fat_libfs_ops = {
@@ -872,4 +888,5 @@
.match = fat_match,
.node_get = fat_node_get,
+ .node_open = fat_node_open,
.node_put = fat_node_put,
.create = fat_create_node,
@@ -881,7 +898,8 @@
.size_get = fat_size_get,
.lnkcnt_get = fat_lnkcnt_get,
- .plb_get_char = fat_plb_get_char,
+ .plb_get_char = fat_plb_get_char,
.is_directory = fat_is_directory,
- .is_file = fat_is_file
+ .is_file = fat_is_file,
+ .device_get = fat_device_get
};
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c (revision fc6dd18feebbc66893aec4d86827b7c815dbbfe7)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c (revision 1313ee92979dd133fd0dd0717213410aada3df10)
@@ -69,4 +69,5 @@
static int tmpfs_match(fs_node_t **, fs_node_t *, const char *);
static int tmpfs_node_get(fs_node_t **, dev_handle_t, fs_index_t);
+static int tmpfs_node_open(fs_node_t *);
static int tmpfs_node_put(fs_node_t *);
static int tmpfs_create_node(fs_node_t **, dev_handle_t, int);
@@ -117,4 +118,9 @@
}
+static dev_handle_t tmpfs_device_get(fs_node_t *fn)
+{
+ return 0;
+}
+
/** libfs operations */
libfs_ops_t tmpfs_libfs_ops = {
@@ -122,4 +128,5 @@
.match = tmpfs_match,
.node_get = tmpfs_node_get,
+ .node_open = tmpfs_node_open,
.node_put = tmpfs_node_put,
.create = tmpfs_create_node,
@@ -133,5 +140,6 @@
.plb_get_char = tmpfs_plb_get_char,
.is_directory = tmpfs_is_directory,
- .is_file = tmpfs_is_file
+ .is_file = tmpfs_is_file,
+ .device_get = tmpfs_device_get
};
@@ -241,4 +249,10 @@
}
return EOK;
+}
+
+int tmpfs_node_open(fs_node_t *fn)
+{
+ /* nothing to do */
+ return EOK;
}