Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4326 → Rev 4327

/branches/network/uspace/srv/vfs/vfs_ops.c
60,6 → 60,7
link_t link;
char *fs_name; /**< File system name */
char *mp; /**< Mount point */
char *opts; /**< Mount options. */
ipc_callid_t callid; /**< Call ID waiting for the mount */
ipc_callid_t rid; /**< Request ID */
dev_handle_t dev_handle; /**< Device handle */
80,18 → 81,21
};
 
static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle,
fs_handle_t fs_handle, char *mp)
fs_handle_t fs_handle, char *mp, char *opts)
{
/* Resolve the path to the mountpoint. */
vfs_lookup_res_t mp_res;
vfs_node_t *mp_node = NULL;
int rc;
ipcarg_t rc;
int phone;
aid_t msg;
ipc_call_t answer;
 
/* Resolve the path to the mountpoint. */
futex_down(&rootfs_futex);
if (rootfs.fs_handle) {
/* We already have the root FS. */
rwlock_write_lock(&namespace_rwlock);
if ((strlen(mp) == 1) && (mp[0] == '/')) {
if (str_cmp(mp, "/") == 0) {
/* Trying to mount root FS over root FS */
rwlock_write_unlock(&namespace_rwlock);
futex_up(&rootfs_futex);
124,12 → 128,12
rwlock_write_unlock(&namespace_rwlock);
} else {
/* We still don't have the root file system mounted. */
if ((strlen(mp) == 1) && (mp[0] == '/')) {
if (str_cmp(mp, "/") == 0) {
vfs_lookup_res_t mr_res;
vfs_node_t *mr_node;
ipcarg_t rindex;
ipcarg_t rsize;
ipcarg_t rlnkcnt;
fs_index_t rindex;
size_t rsize;
unsigned rlnkcnt;
/*
* For this simple, but important case,
138,8 → 142,19
/* Tell the mountee that it is being mounted. */
phone = vfs_grab_phone(fs_handle);
rc = async_req_1_3(phone, VFS_MOUNTED,
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt);
msg = async_send_1(phone, VFS_MOUNTED,
(ipcarg_t) dev_handle, &answer);
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts,
str_size(opts));
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(phone);
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
async_wait_for(msg, &rc);
vfs_release_phone(phone);
if (rc != EOK) {
147,12 → 162,16
ipc_answer_0(rid, rc);
return;
}
 
rindex = (fs_index_t) IPC_GET_ARG1(answer);
rsize = (size_t) IPC_GET_ARG2(answer);
rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
mr_res.triplet.fs_handle = fs_handle;
mr_res.triplet.dev_handle = dev_handle;
mr_res.triplet.index = (fs_index_t) rindex;
mr_res.size = (size_t) rsize;
mr_res.lnkcnt = (unsigned) rlnkcnt;
mr_res.triplet.index = rindex;
mr_res.size = rsize;
mr_res.lnkcnt = rlnkcnt;
mr_res.type = VFS_NODE_DIRECTORY;
rootfs.fs_handle = fs_handle;
183,11 → 202,23
*/
phone = vfs_grab_phone(mp_res.triplet.fs_handle);
rc = async_req_4_0(phone, VFS_MOUNT,
msg = async_send_4(phone, VFS_MOUNT,
(ipcarg_t) mp_res.triplet.dev_handle,
(ipcarg_t) mp_res.triplet.index,
(ipcarg_t) fs_handle,
(ipcarg_t) dev_handle);
(ipcarg_t) dev_handle, &answer);
/* send the mount options */
rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
if (rc != EOK) {
async_wait_for(msg, NULL);
vfs_release_phone(phone);
/* Mount failed, drop reference to mp_node. */
if (mp_node)
vfs_node_put(mp_node);
ipc_answer_0(rid, rc);
return;
}
async_wait_for(msg, &rc);
vfs_release_phone(phone);
if (rc != EOK) {
216,10 → 247,12
ipc_answer_0(pr->callid, EOK);
/* Do the mount */
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp);
vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp,
pr->opts);
free(pr->fs_name);
free(pr->mp);
free(pr->opts);
list_remove(cur);
free(pr);
goto loop;
272,12 → 305,47
/* Deliver the mount point. */
ipcarg_t retval = ipc_data_write_finalize(callid, mp, size);
if (retval != EOK) {
ipc_answer_0(rid, EREFUSED);
ipc_answer_0(rid, retval);
free(mp);
return;
}
mp[size] = '\0';
/* Now we expect to receive the mount options. */
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(mp);
return;
}
 
/* Check the offered options size. */
if (size < 0 || size > MAX_MNTOPTS_LEN) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(mp);
return;
}
 
/* Allocate buffer for the mount options. */
char *opts = (char *) malloc(size + 1);
if (!opts) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
free(mp);
return;
}
 
/* Deliver the mount options. */
retval = ipc_data_write_finalize(callid, opts, size);
if (retval != EOK) {
ipc_answer_0(rid, retval);
free(mp);
free(opts);
return;
}
opts[size] = '\0';
/*
* Now, we expect the client to send us data with the name of the file
* system.
286,6 → 354,7
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(mp);
free(opts);
return;
}
297,6 → 366,7
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(mp);
free(opts);
return;
}
306,8 → 376,9
char *fs_name = (char *) malloc(size + 1);
if (fs_name == NULL) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, EREFUSED);
ipc_answer_0(rid, ENOMEM);
free(mp);
free(opts);
return;
}
314,14 → 385,30
/* Deliver the file system name. */
retval = ipc_data_write_finalize(callid, fs_name, size);
if (retval != EOK) {
ipc_answer_0(rid, EREFUSED);
ipc_answer_0(rid, retval);
free(mp);
free(opts);
free(fs_name);
return;
}
fs_name[size] = '\0';
 
/*
* Wait for IPC_M_PING so that we can return an error if we don't know
* fs_name.
*/
ipc_call_t data;
callid = async_get_call(&data);
if (IPC_GET_METHOD(data) != IPC_M_PING) {
ipc_answer_0(callid, ENOTSUP);
ipc_answer_0(rid, ENOTSUP);
free(mp);
free(opts);
free(fs_name);
return;
}
 
/*
* Check if we know a file system with the same name as is in fs_name.
* This will also give us its file system handle.
*/
328,18 → 415,22
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
if (!fs_handle) {
if (flags & IPC_FLAG_BLOCKING) {
pending_req_t *pr;
 
/* Blocking mount, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
free(mp);
free(fs_name);
free(opts);
return;
}
pr->fs_name = fs_name;
pr->mp = mp;
pr->opts = opts;
pr->callid = callid;
pr->rid = rid;
pr->dev_handle = dev_handle;
352,6 → 443,7
ipc_answer_0(rid, ENOENT);
free(mp);
free(fs_name);
free(opts);
return;
}
359,9 → 451,10
ipc_answer_0(callid, EOK);
/* Do the mount */
vfs_mount_internal(rid, dev_handle, fs_handle, mp);
vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts);
free(mp);
free(fs_name);
free(opts);
}
 
void vfs_open(ipc_callid_t rid, ipc_call_t *request)
804,37 → 897,37
 
void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
{
size_t len;
size_t olen, nlen;
ipc_callid_t callid;
int rc;
 
/* Retrieve the old path. */
if (!ipc_data_write_receive(&callid, &len)) {
if (!ipc_data_write_receive(&callid, &olen)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
char *old = malloc(len + 1);
char *old = malloc(olen + 1);
if (!old) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
if ((rc = ipc_data_write_finalize(callid, old, len))) {
if ((rc = ipc_data_write_finalize(callid, old, olen))) {
ipc_answer_0(rid, rc);
free(old);
return;
}
old[len] = '\0';
old[olen] = '\0';
/* Retrieve the new path. */
if (!ipc_data_write_receive(&callid, &len)) {
if (!ipc_data_write_receive(&callid, &nlen)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
free(old);
return;
}
char *new = malloc(len + 1);
char *new = malloc(nlen + 1);
if (!new) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
841,16 → 934,16
free(old);
return;
}
if ((rc = ipc_data_write_finalize(callid, new, len))) {
if ((rc = ipc_data_write_finalize(callid, new, nlen))) {
ipc_answer_0(rid, rc);
free(old);
free(new);
return;
}
new[len] = '\0';
new[nlen] = '\0';
 
char *oldc = canonify(old, &len);
char *newc = canonify(new, NULL);
char *oldc = canonify(old, &olen);
char *newc = canonify(new, &nlen);
if (!oldc || !newc) {
ipc_answer_0(rid, EINVAL);
free(old);
857,7 → 950,9
free(new);
return;
}
if (!strncmp(newc, oldc, len)) {
oldc[olen] = '\0';
newc[nlen] = '\0';
if (!str_lcmp(newc, oldc, str_length(oldc))) {
/* oldc is a prefix of newc */
ipc_answer_0(rid, EINVAL);
free(old);
/branches/network/uspace/srv/vfs/vfs_register.c
376,8 → 376,7
link_t *cur;
for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
if (strncmp(fs->vfs_info.name, name,
sizeof(fs->vfs_info.name)) == 0) {
if (str_cmp(fs->vfs_info.name, name) == 0) {
handle = fs->fs_handle;
break;
}
/branches/network/uspace/srv/vfs/vfs.h
254,6 → 254,8
extern uint8_t *plb; /**< Path Lookup Buffer */
extern link_t plb_head; /**< List of active PLB entries. */
 
#define MAX_MNTOPTS_LEN 256
 
/** Holding this rwlock prevents changes in file system namespace. */
extern rwlock_t namespace_rwlock;