~jkavalik/cdfs/main

« back to all changes in this revision

Viewing changes to uspace/srv/fs/devfs/devfs_ops.c

merge mainline
update async in cdfs
add READ TOC support in ata_bd, libblock and cdfs

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
 * @brief Implementation of VFS operations for the devfs file system server.
36
36
 */
37
37
 
38
 
#include <ipc/ipc.h>
39
38
#include <macros.h>
40
39
#include <bool.h>
41
40
#include <errno.h>
59
58
/** Opened devices structure */
60
59
typedef struct {
61
60
        devmap_handle_t handle;
62
 
        int phone;
 
61
        int phone;              /**< When < 0, the structure is incomplete. */
63
62
        size_t refcount;
64
63
        link_t link;
 
64
        fibril_condvar_t cv;    /**< Broadcast when completed. */
65
65
} device_t;
66
66
 
67
67
/** Hash table of opened devices */
129
129
static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
130
130
{
131
131
        devfs_node_t *node = (devfs_node_t *) pfn->data;
 
132
        int ret;
132
133
        
133
134
        if (node->handle == 0) {
134
135
                /* Root directory */
144
145
                                        continue;
145
146
                                
146
147
                                if (str_cmp(devs[pos].name, component) == 0) {
 
148
                                        ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
147
149
                                        free(devs);
148
 
                                        return devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
 
150
                                        return ret;
149
151
                                }
150
152
                        }
151
153
                        
161
163
                                size_t pos;
162
164
                                for (pos = 0; pos < count; pos++) {
163
165
                                        if (str_cmp(devs[pos].name, component) == 0) {
 
166
                                                ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
164
167
                                                free(devs);
165
 
                                                return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
 
168
                                                return ret;
166
169
                                        }
167
170
                                }
168
171
                                
183
186
                        size_t pos;
184
187
                        for (pos = 0; pos < count; pos++) {
185
188
                                if (str_cmp(devs[pos].name, component) == 0) {
 
189
                                        ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
186
190
                                        free(devs);
187
 
                                        return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
 
191
                                        return ret;
188
192
                                }
189
193
                        }
190
194
                        
226
230
                unsigned long key[] = {
227
231
                        [DEVICES_KEY_HANDLE] = (unsigned long) node->handle
228
232
                };
229
 
                
 
233
                link_t *lnk;
 
234
 
230
235
                fibril_mutex_lock(&devices_mutex);
231
 
                link_t *lnk = hash_table_find(&devices, key);
 
236
restart:
 
237
                lnk = hash_table_find(&devices, key);
232
238
                if (lnk == NULL) {
233
239
                        device_t *dev = (device_t *) malloc(sizeof(device_t));
234
240
                        if (dev == NULL) {
236
242
                                return ENOMEM;
237
243
                        }
238
244
                        
 
245
                        dev->handle = node->handle;
 
246
                        dev->phone = -1;        /* mark as incomplete */
 
247
                        dev->refcount = 1;
 
248
                        fibril_condvar_initialize(&dev->cv);
 
249
 
 
250
                        /*
 
251
                         * Insert the incomplete device structure so that other
 
252
                         * fibrils will not race with us when we drop the mutex
 
253
                         * below.
 
254
                         */
 
255
                        hash_table_insert(&devices, key, &dev->link);
 
256
 
 
257
                        /*
 
258
                         * Drop the mutex to allow recursive devfs requests.
 
259
                         */
 
260
                        fibril_mutex_unlock(&devices_mutex);
 
261
 
239
262
                        int phone = devmap_device_connect(node->handle, 0);
 
263
 
 
264
                        fibril_mutex_lock(&devices_mutex);
 
265
 
 
266
                        /*
 
267
                         * Notify possible waiters about this device structure
 
268
                         * being completed (or destroyed).
 
269
                         */
 
270
                        fibril_condvar_broadcast(&dev->cv);
 
271
 
240
272
                        if (phone < 0) {
 
273
                                /*
 
274
                                 * Connecting failed, need to remove the
 
275
                                 * entry and free the device structure.
 
276
                                 */
 
277
                                hash_table_remove(&devices, key, DEVICES_KEYS);
241
278
                                fibril_mutex_unlock(&devices_mutex);
242
 
                                free(dev);
 
279
 
243
280
                                return ENOENT;
244
281
                        }
245
282
                        
246
 
                        dev->handle = node->handle;
 
283
                        /* Set the correct phone. */
247
284
                        dev->phone = phone;
248
 
                        dev->refcount = 1;
249
 
                        
250
 
                        hash_table_insert(&devices, key, &dev->link);
251
285
                } else {
252
286
                        device_t *dev = hash_table_get_instance(lnk, device_t, link);
 
287
 
 
288
                        if (dev->phone < 0) {
 
289
                                /*
 
290
                                 * Wait until the device structure is completed
 
291
                                 * and start from the beginning as the device
 
292
                                 * structure might have entirely disappeared
 
293
                                 * while we were not holding the mutex in
 
294
                                 * fibril_condvar_wait().
 
295
                                 */
 
296
                                fibril_condvar_wait(&dev->cv, &devices_mutex);
 
297
                                goto restart;
 
298
                        }
 
299
 
253
300
                        dev->refcount++;
254
301
                }
255
302
                
408
455
            DEVICES_KEYS, &devices_ops))
409
456
                return false;
410
457
        
411
 
        if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
412
 
                return false;
413
 
        
414
458
        return true;
415
459
}
416
460
 
422
466
        sysarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
423
467
            0, NULL);
424
468
        if (retval != EOK) {
425
 
                ipc_answer_0(rid, retval);
 
469
                async_answer_0(rid, retval);
426
470
                return;
427
471
        }
428
472
        
429
473
        free(opts);
430
 
        ipc_answer_3(rid, EOK, 0, 0, 0);
 
474
        async_answer_3(rid, EOK, 0, 0, 0);
431
475
}
432
476
 
433
477
void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
437
481
 
438
482
void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
439
483
{
440
 
        ipc_answer_0(rid, ENOTSUP);
 
484
        async_answer_0(rid, ENOTSUP);
441
485
}
442
486
 
443
487
void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
470
514
                ipc_callid_t callid;
471
515
                size_t size;
472
516
                if (!async_data_read_receive(&callid, &size)) {
473
 
                        ipc_answer_0(callid, EINVAL);
474
 
                        ipc_answer_0(rid, EINVAL);
 
517
                        async_answer_0(callid, EINVAL);
 
518
                        async_answer_0(rid, EINVAL);
475
519
                        return;
476
520
                }
477
521
                
492
536
                if (pos < count) {
493
537
                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
494
538
                        free(desc);
495
 
                        ipc_answer_1(rid, EOK, 1);
 
539
                        async_answer_1(rid, EOK, 1);
496
540
                        return;
497
541
                }
498
542
                
507
551
                        if (pos < count) {
508
552
                                async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
509
553
                                free(desc);
510
 
                                ipc_answer_1(rid, EOK, 1);
 
554
                                async_answer_1(rid, EOK, 1);
511
555
                                return;
512
556
                        }
513
557
                        
514
558
                        free(desc);
515
559
                }
516
560
                
517
 
                ipc_answer_0(callid, ENOENT);
518
 
                ipc_answer_1(rid, ENOENT, 0);
 
561
                async_answer_0(callid, ENOENT);
 
562
                async_answer_1(rid, ENOENT, 0);
519
563
                return;
520
564
        }
521
565
        
526
570
                ipc_callid_t callid;
527
571
                size_t size;
528
572
                if (!async_data_read_receive(&callid, &size)) {
529
 
                        ipc_answer_0(callid, EINVAL);
530
 
                        ipc_answer_0(rid, EINVAL);
 
573
                        async_answer_0(callid, EINVAL);
 
574
                        async_answer_0(rid, EINVAL);
531
575
                        return;
532
576
                }
533
577
                
537
581
                if (pos < count) {
538
582
                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
539
583
                        free(desc);
540
 
                        ipc_answer_1(rid, EOK, 1);
 
584
                        async_answer_1(rid, EOK, 1);
541
585
                        return;
542
586
                }
543
587
                
544
588
                free(desc);
545
 
                ipc_answer_0(callid, ENOENT);
546
 
                ipc_answer_1(rid, ENOENT, 0);
 
589
                async_answer_0(callid, ENOENT);
 
590
                async_answer_1(rid, ENOENT, 0);
547
591
                return;
548
592
        }
549
593
        
558
602
                link_t *lnk = hash_table_find(&devices, key);
559
603
                if (lnk == NULL) {
560
604
                        fibril_mutex_unlock(&devices_mutex);
561
 
                        ipc_answer_0(rid, ENOENT);
 
605
                        async_answer_0(rid, ENOENT);
562
606
                        return;
563
607
                }
564
608
                
565
609
                device_t *dev = hash_table_get_instance(lnk, device_t, link);
 
610
                assert(dev->phone >= 0);
566
611
                
567
612
                ipc_callid_t callid;
568
613
                if (!async_data_read_receive(&callid, NULL)) {
569
614
                        fibril_mutex_unlock(&devices_mutex);
570
 
                        ipc_answer_0(callid, EINVAL);
571
 
                        ipc_answer_0(rid, EINVAL);
 
615
                        async_answer_0(callid, EINVAL);
 
616
                        async_answer_0(rid, EINVAL);
572
617
                        return;
573
618
                }
574
619
                
579
624
                    IPC_GET_ARG3(*request), &answer);
580
625
                
581
626
                /* Forward the IPC_M_DATA_READ request to the driver */
582
 
                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 
627
                async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
583
628
                fibril_mutex_unlock(&devices_mutex);
584
629
                
585
630
                /* Wait for reply from the driver. */
588
633
                size_t bytes = IPC_GET_ARG1(answer);
589
634
                
590
635
                /* Driver reply is the final result of the whole operation */
591
 
                ipc_answer_1(rid, rc, bytes);
 
636
                async_answer_1(rid, rc, bytes);
592
637
                return;
593
638
        }
594
639
        
595
 
        ipc_answer_0(rid, ENOENT);
 
640
        async_answer_0(rid, ENOENT);
596
641
}
597
642
 
598
643
void devfs_write(ipc_callid_t rid, ipc_call_t *request)
599
644
{
600
645
        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
601
646
        if (index == 0) {
602
 
                ipc_answer_0(rid, ENOTSUP);
 
647
                async_answer_0(rid, ENOTSUP);
603
648
                return;
604
649
        }
605
650
        
607
652
        
608
653
        if (type == DEV_HANDLE_NAMESPACE) {
609
654
                /* Namespace directory */
610
 
                ipc_answer_0(rid, ENOTSUP);
 
655
                async_answer_0(rid, ENOTSUP);
611
656
                return;
612
657
        }
613
658
        
621
666
                link_t *lnk = hash_table_find(&devices, key);
622
667
                if (lnk == NULL) {
623
668
                        fibril_mutex_unlock(&devices_mutex);
624
 
                        ipc_answer_0(rid, ENOENT);
 
669
                        async_answer_0(rid, ENOENT);
625
670
                        return;
626
671
                }
627
672
                
628
673
                device_t *dev = hash_table_get_instance(lnk, device_t, link);
 
674
                assert(dev->phone >= 0);
629
675
                
630
676
                ipc_callid_t callid;
631
677
                if (!async_data_write_receive(&callid, NULL)) {
632
678
                        fibril_mutex_unlock(&devices_mutex);
633
 
                        ipc_answer_0(callid, EINVAL);
634
 
                        ipc_answer_0(rid, EINVAL);
 
679
                        async_answer_0(callid, EINVAL);
 
680
                        async_answer_0(rid, EINVAL);
635
681
                        return;
636
682
                }
637
683
                
642
688
                    IPC_GET_ARG3(*request), &answer);
643
689
                
644
690
                /* Forward the IPC_M_DATA_WRITE request to the driver */
645
 
                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
 
691
                async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
646
692
                
647
693
                fibril_mutex_unlock(&devices_mutex);
648
694
                
652
698
                size_t bytes = IPC_GET_ARG1(answer);
653
699
                
654
700
                /* Driver reply is the final result of the whole operation */
655
 
                ipc_answer_1(rid, rc, bytes);
 
701
                async_answer_1(rid, rc, bytes);
656
702
                return;
657
703
        }
658
704
        
659
 
        ipc_answer_0(rid, ENOENT);
 
705
        async_answer_0(rid, ENOENT);
660
706
}
661
707
 
662
708
void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
663
709
{
664
 
        ipc_answer_0(rid, ENOTSUP);
 
710
        async_answer_0(rid, ENOTSUP);
665
711
}
666
712
 
667
713
void devfs_close(ipc_callid_t rid, ipc_call_t *request)
669
715
        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
670
716
        
671
717
        if (index == 0) {
672
 
                ipc_answer_0(rid, EOK);
 
718
                async_answer_0(rid, EOK);
673
719
                return;
674
720
        }
675
721
        
677
723
        
678
724
        if (type == DEV_HANDLE_NAMESPACE) {
679
725
                /* Namespace directory */
680
 
                ipc_answer_0(rid, EOK);
 
726
                async_answer_0(rid, EOK);
681
727
                return;
682
728
        }
683
729
        
690
736
                link_t *lnk = hash_table_find(&devices, key);
691
737
                if (lnk == NULL) {
692
738
                        fibril_mutex_unlock(&devices_mutex);
693
 
                        ipc_answer_0(rid, ENOENT);
 
739
                        async_answer_0(rid, ENOENT);
694
740
                        return;
695
741
                }
696
742
                
697
743
                device_t *dev = hash_table_get_instance(lnk, device_t, link);
 
744
                assert(dev->phone >= 0);
698
745
                dev->refcount--;
699
746
                
700
747
                if (dev->refcount == 0) {
701
 
                        ipc_hangup(dev->phone);
 
748
                        async_hangup(dev->phone);
702
749
                        hash_table_remove(&devices, key, DEVICES_KEYS);
703
750
                }
704
751
                
705
752
                fibril_mutex_unlock(&devices_mutex);
706
753
                
707
 
                ipc_answer_0(rid, EOK);
 
754
                async_answer_0(rid, EOK);
708
755
                return;
709
756
        }
710
757
        
711
 
        ipc_answer_0(rid, ENOENT);
 
758
        async_answer_0(rid, ENOENT);
712
759
}
713
760
 
714
761
void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
716
763
        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
717
764
        
718
765
        if (index == 0) {
719
 
                ipc_answer_0(rid, EOK);
 
766
                async_answer_0(rid, EOK);
720
767
                return;
721
768
        }
722
769
        
724
771
        
725
772
        if (type == DEV_HANDLE_NAMESPACE) {
726
773
                /* Namespace directory */
727
 
                ipc_answer_0(rid, EOK);
 
774
                async_answer_0(rid, EOK);
728
775
                return;
729
776
        }
730
777
        
737
784
                link_t *lnk = hash_table_find(&devices, key);
738
785
                if (lnk == NULL) {
739
786
                        fibril_mutex_unlock(&devices_mutex);
740
 
                        ipc_answer_0(rid, ENOENT);
 
787
                        async_answer_0(rid, ENOENT);
741
788
                        return;
742
789
                }
743
790
                
744
791
                device_t *dev = hash_table_get_instance(lnk, device_t, link);
 
792
                assert(dev->phone >= 0);
745
793
                
746
794
                /* Make a request at the driver */
747
795
                ipc_call_t answer;
755
803
                async_wait_for(msg, &rc);
756
804
                
757
805
                /* Driver reply is the final result of the whole operation */
758
 
                ipc_answer_0(rid, rc);
 
806
                async_answer_0(rid, rc);
759
807
                return;
760
808
        }
761
809
        
762
 
        ipc_answer_0(rid, ENOENT);
 
810
        async_answer_0(rid, ENOENT);
763
811
}
764
812
 
765
813
void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
766
814
{
767
 
        ipc_answer_0(rid, ENOTSUP);
 
815
        async_answer_0(rid, ENOTSUP);
768
816
}
769
817
 
770
818
/**