Subversion Repositories HelenOS

Rev

Rev 3011 | Rev 3425 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3011 Rev 3424
Line 60... Line 60...
60
 * concurrent VFS operation which modifies the file system namespace.
60
 * concurrent VFS operation which modifies the file system namespace.
61
 */
61
 */
62
RWLOCK_INITIALIZE(namespace_rwlock);
62
RWLOCK_INITIALIZE(namespace_rwlock);
63
 
63
 
64
futex_t rootfs_futex = FUTEX_INITIALIZER;
64
futex_t rootfs_futex = FUTEX_INITIALIZER;
65
vfs_triplet_t rootfs = {
65
vfs_pair_t rootfs = {
66
    .fs_handle = 0,
66
    .fs_handle = 0,
67
    .dev_handle = 0,
67
    .dev_handle = 0
68
    .index = 0,
-
 
69
};
68
};
70
 
69
 
71
static int
-
 
72
lookup_root(fs_handle_t fs_handle, dev_handle_t dev_handle,
-
 
73
    vfs_lookup_res_t *result)
-
 
74
{
-
 
75
    vfs_pair_t altroot = {
-
 
76
        .fs_handle = fs_handle,
-
 
77
        .dev_handle = dev_handle,
-
 
78
    };
-
 
79
 
-
 
80
    return vfs_lookup_internal("/", L_DIRECTORY, result, &altroot);
-
 
81
}
-
 
82
 
-
 
83
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
70
void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
84
{
71
{
85
    dev_handle_t dev_handle;
72
    dev_handle_t dev_handle;
86
    vfs_node_t *mp_node = NULL;
73
    vfs_node_t *mp_node = NULL;
87
    int rc;
74
    int rc;
Line 161... Line 148...
161
 
148
 
162
    /* Deliver the mount point. */
149
    /* Deliver the mount point. */
163
    (void) ipc_data_write_finalize(callid, buf, size);
150
    (void) ipc_data_write_finalize(callid, buf, size);
164
    buf[size] = '\0';
151
    buf[size] = '\0';
165
 
152
 
166
    /*
-
 
167
     * Lookup the root node of the filesystem being mounted.
-
 
168
     * In this case, we don't need to take the namespace_futex as the root
-
 
169
     * node cannot be removed. However, we do take a reference to it so
-
 
170
     * that we can track how many times it has been mounted.
-
 
171
     */
-
 
172
    vfs_lookup_res_t mr_res;
-
 
173
    rc = lookup_root(fs_handle, dev_handle, &mr_res);
-
 
174
    if (rc != EOK) {
-
 
175
        free(buf);
-
 
176
        ipc_answer_0(rid, rc);
-
 
177
        return;
-
 
178
    }
-
 
179
    vfs_node_t *mr_node = vfs_node_get(&mr_res);
-
 
180
    if (!mr_node) {
-
 
181
        free(buf);
-
 
182
        ipc_answer_0(rid, ENOMEM);
-
 
183
        return;
-
 
184
    }
-
 
185
 
-
 
186
    /* Finally, we need to resolve the path to the mountpoint. */
153
    /* Resolve the path to the mountpoint. */
187
    vfs_lookup_res_t mp_res;
154
    vfs_lookup_res_t mp_res;
188
    futex_down(&rootfs_futex);
155
    futex_down(&rootfs_futex);
189
    if (rootfs.fs_handle) {
156
    if (rootfs.fs_handle) {
190
        /* We already have the root FS. */
157
        /* We already have the root FS. */
191
        rwlock_write_lock(&namespace_rwlock);
158
        rwlock_write_lock(&namespace_rwlock);
192
        if ((size == 1) && (buf[0] == '/')) {
159
        if ((size == 1) && (buf[0] == '/')) {
193
            /* Trying to mount root FS over root FS */
160
            /* Trying to mount root FS over root FS */
194
            rwlock_write_unlock(&namespace_rwlock);
161
            rwlock_write_unlock(&namespace_rwlock);
195
            futex_up(&rootfs_futex);
162
            futex_up(&rootfs_futex);
196
            vfs_node_put(mr_node);
-
 
197
            free(buf);
163
            free(buf);
198
            ipc_answer_0(rid, EBUSY);
164
            ipc_answer_0(rid, EBUSY);
199
            return;
165
            return;
200
        }
166
        }
201
        rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL);
167
        rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL);
202
        if (rc != EOK) {
168
        if (rc != EOK) {
203
            /* The lookup failed for some reason. */
169
            /* The lookup failed for some reason. */
204
            rwlock_write_unlock(&namespace_rwlock);
170
            rwlock_write_unlock(&namespace_rwlock);
205
            futex_up(&rootfs_futex);
171
            futex_up(&rootfs_futex);
206
            vfs_node_put(mr_node);  /* failed -> drop reference */
-
 
207
            free(buf);
172
            free(buf);
208
            ipc_answer_0(rid, rc);
173
            ipc_answer_0(rid, rc);
209
            return;
174
            return;
210
        }
175
        }
211
        mp_node = vfs_node_get(&mp_res);
176
        mp_node = vfs_node_get(&mp_res);
212
        if (!mp_node) {
177
        if (!mp_node) {
213
            rwlock_write_unlock(&namespace_rwlock);
178
            rwlock_write_unlock(&namespace_rwlock);
214
            futex_up(&rootfs_futex);
179
            futex_up(&rootfs_futex);
215
            vfs_node_put(mr_node);  /* failed -> drop reference */
-
 
216
            free(buf);
180
            free(buf);
217
            ipc_answer_0(rid, ENOMEM);
181
            ipc_answer_0(rid, ENOMEM);
218
            return;
182
            return;
219
        }
183
        }
220
        /*
184
        /*
Line 230... Line 194...
230
             * For this simple, but important case,
194
             * For this simple, but important case,
231
             * we are almost done.
195
             * we are almost done.
232
             */
196
             */
233
            free(buf);
197
            free(buf);
234
           
198
           
235
            /* Inform the mount point about the root mount. */
199
            /* Tell the mountee that it is being mounted. */
236
            phone = vfs_grab_phone(mr_res.triplet.fs_handle);
200
            phone = vfs_grab_phone(fs_handle);
237
            rc = async_req_5_0(phone, VFS_MOUNT,
201
            rc = async_req_1_0(phone, VFS_MOUNTED,
238
                (ipcarg_t) mr_res.triplet.dev_handle,
-
 
239
                (ipcarg_t) mr_res.triplet.index,
-
 
240
                (ipcarg_t) mr_res.triplet.fs_handle,
-
 
241
                (ipcarg_t) mr_res.triplet.dev_handle,
202
                (ipcarg_t) dev_handle);
242
                (ipcarg_t) mr_res.triplet.index);
-
 
243
            vfs_release_phone(phone);
203
            vfs_release_phone(phone);
244
 
204
 
245
            if (rc == EOK)
205
            if (rc == EOK) {
246
                rootfs = mr_res.triplet;
206
                rootfs.fs_handle = fs_handle;
-
 
207
                rootfs.dev_handle = dev_handle;
247
            else
208
            }
248
                vfs_node_put(mr_node);
-
 
249
 
209
 
250
            futex_up(&rootfs_futex);
210
            futex_up(&rootfs_futex);
251
            ipc_answer_0(rid, rc);
211
            ipc_answer_0(rid, rc);
252
            return;
212
            return;
253
        } else {
213
        } else {
Line 255... Line 215...
255
             * We can't resolve this without the root filesystem
215
             * We can't resolve this without the root filesystem
256
             * being mounted first.
216
             * being mounted first.
257
             */
217
             */
258
            futex_up(&rootfs_futex);
218
            futex_up(&rootfs_futex);
259
            free(buf);
219
            free(buf);
260
            vfs_node_put(mr_node);  /* failed -> drop reference */
-
 
261
            ipc_answer_0(rid, ENOENT);
220
            ipc_answer_0(rid, ENOENT);
262
            return;
221
            return;
263
        }
222
        }
264
    }
223
    }
265
    futex_up(&rootfs_futex);
224
    futex_up(&rootfs_futex);
266
   
225
   
267
    free(buf);  /* The buffer is not needed anymore. */
226
    free(buf);  /* The buffer is not needed anymore. */
268
   
227
   
269
    /*
228
    /*
270
     * At this point, we have all necessary pieces: file system and device
229
     * At this point, we have all necessary pieces: file system and device
271
     * handles, and we know the mount point VFS node and also the root node
230
     * handles, and we know the mount point VFS node.
272
     * of the file system being mounted.
-
 
273
     */
231
     */
274
 
232
 
275
    /**
-
 
276
     * @todo
-
 
277
     * Add more IPC parameters so that we can send mount mode/flags.
-
 
278
     */
-
 
279
    phone = vfs_grab_phone(mp_res.triplet.fs_handle);
233
    phone = vfs_grab_phone(mp_res.triplet.fs_handle);
280
    rc = async_req_5_0(phone, VFS_MOUNT,
234
    rc = async_req_4_0(phone, VFS_MOUNT,
281
        (ipcarg_t) mp_res.triplet.dev_handle,
235
        (ipcarg_t) mp_res.triplet.dev_handle,
282
        (ipcarg_t) mp_res.triplet.index,
236
        (ipcarg_t) mp_res.triplet.index,
283
        (ipcarg_t) mr_res.triplet.fs_handle,
237
        (ipcarg_t) fs_handle,
284
        (ipcarg_t) mr_res.triplet.dev_handle,
238
        (ipcarg_t) dev_handle);
285
        (ipcarg_t) mr_res.triplet.index);
-
 
286
    vfs_release_phone(phone);
239
    vfs_release_phone(phone);
287
 
240
 
288
    if (rc != EOK) {
241
    if (rc != EOK) {
289
        /* Mount failed, drop references to mr_node and mp_node. */
242
        /* Mount failed, drop reference to mp_node. */
290
        vfs_node_put(mr_node);
-
 
291
        if (mp_node)
243
        if (mp_node)
292
            vfs_node_put(mp_node);
244
            vfs_node_put(mp_node);
293
    }
245
    }
294
   
246
   
295
    ipc_answer_0(rid, rc);
247
    ipc_answer_0(rid, rc);
Line 442... Line 394...
442
     * Additional synchronization needs to be added once the table of
394
     * Additional synchronization needs to be added once the table of
443
     * open files supports parallel access!
395
     * open files supports parallel access!
444
     */
396
     */
445
 
397
 
446
    int fd = IPC_GET_ARG1(*request);
398
    int fd = IPC_GET_ARG1(*request);
447
 
399
   
448
    /* Lookup the file structure corresponding to the file descriptor. */
400
    /* Lookup the file structure corresponding to the file descriptor. */
449
    vfs_file_t *file = vfs_file_get(fd);
401
    vfs_file_t *file = vfs_file_get(fd);
450
    if (!file) {
402
    if (!file) {
451
        ipc_answer_0(rid, ENOENT);
403
        ipc_answer_0(rid, ENOENT);
452
        return;
404
        return;
453
    }
405
    }
454
 
406
   
455
    /*
407
    /*
456
     * Now we need to receive a call with client's
408
     * Now we need to receive a call with client's
457
     * IPC_M_DATA_READ/IPC_M_DATA_WRITE request.
409
     * IPC_M_DATA_READ/IPC_M_DATA_WRITE request.
458
     */
410
     */
459
    ipc_callid_t callid;
411
    ipc_callid_t callid;
Line 465... Line 417...
465
    if (!res) {
417
    if (!res) {
466
        ipc_answer_0(callid, EINVAL);
418
        ipc_answer_0(callid, EINVAL);
467
        ipc_answer_0(rid, EINVAL);
419
        ipc_answer_0(rid, EINVAL);
468
        return;
420
        return;
469
    }
421
    }
470
 
422
   
471
    /*
423
    /*
472
     * Lock the open file structure so that no other thread can manipulate
424
     * Lock the open file structure so that no other thread can manipulate
473
     * the same open file at a time.
425
     * the same open file at a time.
474
     */
426
     */
475
    futex_down(&file->lock);
427
    futex_down(&file->lock);
476
 
428
   
477
    /*
429
    /*
478
     * Lock the file's node so that no other client can read/write to it at
430
     * Lock the file's node so that no other client can read/write to it at
479
     * the same time.
431
     * the same time.
480
     */
432
     */
481
    if (read)
433
    if (read)
482
        rwlock_read_lock(&file->node->contents_rwlock);
434
        rwlock_read_lock(&file->node->contents_rwlock);
483
    else
435
    else
484
        rwlock_write_lock(&file->node->contents_rwlock);
436
        rwlock_write_lock(&file->node->contents_rwlock);
485
 
437
   
486
    int fs_phone = vfs_grab_phone(file->node->fs_handle);  
438
    int fs_phone = vfs_grab_phone(file->node->fs_handle);  
487
   
439
   
488
    /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
440
    /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
489
    aid_t msg;
441
    aid_t msg;
490
    ipc_call_t answer;
442
    ipc_call_t answer;
Line 498... Line 450...
498
     * destination FS server. The call will be routed as if sent by
450
     * destination FS server. The call will be routed as if sent by
499
     * ourselves. Note that call arguments are immutable in this case so we
451
     * ourselves. Note that call arguments are immutable in this case so we
500
     * don't have to bother.
452
     * don't have to bother.
501
     */
453
     */
502
    ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
454
    ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
503
 
455
   
504
    vfs_release_phone(fs_phone);
456
    vfs_release_phone(fs_phone);
505
 
457
   
506
    /* Wait for reply from the FS server. */
458
    /* Wait for reply from the FS server. */
507
    ipcarg_t rc;
459
    ipcarg_t rc;
508
    async_wait_for(msg, &rc);
460
    async_wait_for(msg, &rc);
509
    size_t bytes = IPC_GET_ARG1(answer);
461
    size_t bytes = IPC_GET_ARG1(answer);
510
 
462
   
511
    /* Unlock the VFS node. */
463
    /* Unlock the VFS node. */
512
    if (read)
464
    if (read)
513
        rwlock_read_unlock(&file->node->contents_rwlock);
465
        rwlock_read_unlock(&file->node->contents_rwlock);
514
    else {
466
    else {
515
        /* Update the cached version of node's size. */
467
        /* Update the cached version of node's size. */
516
        if (rc == EOK)
468
        if (rc == EOK)
517
            file->node->size = IPC_GET_ARG2(answer);
469
            file->node->size = IPC_GET_ARG2(answer);
518
        rwlock_write_unlock(&file->node->contents_rwlock);
470
        rwlock_write_unlock(&file->node->contents_rwlock);
519
    }
471
    }
520
 
472
   
521
    /* Update the position pointer and unlock the open file. */
473
    /* Update the position pointer and unlock the open file. */
522
    if (rc == EOK)
474
    if (rc == EOK)
523
        file->pos += bytes;
475
        file->pos += bytes;
524
    futex_up(&file->lock);
476
    futex_up(&file->lock);
525
 
477
   
526
    /*
478
    /*
527
     * FS server's reply is the final result of the whole operation we
479
     * FS server's reply is the final result of the whole operation we
528
     * return to the client.
480
     * return to the client.
529
     */
481
     */
530
    ipc_answer_1(rid, rc, bytes);
482
    ipc_answer_1(rid, rc, bytes);