Subversion Repositories HelenOS

Rev

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

Rev 4509 Rev 4518
Line 42... Line 42...
42
#include <stdio.h>
42
#include <stdio.h>
43
#include <stdlib.h>
43
#include <stdlib.h>
44
#include <string.h>
44
#include <string.h>
45
#include <bool.h>
45
#include <bool.h>
46
#include <futex.h>
46
#include <futex.h>
47
#include <rwlock.h>
47
#include <fibril_sync.h>
48
#include <adt/list.h>
48
#include <adt/list.h>
49
#include <unistd.h>
49
#include <unistd.h>
50
#include <ctype.h>
50
#include <ctype.h>
51
#include <fcntl.h>
51
#include <fcntl.h>
52
#include <assert.h>
52
#include <assert.h>
Line 70... Line 70...
70
 
70
 
71
/**
71
/**
72
 * This rwlock prevents the race between a triplet-to-VFS-node resolution and a
72
 * This rwlock prevents the race between a triplet-to-VFS-node resolution and a
73
 * concurrent VFS operation which modifies the file system namespace.
73
 * concurrent VFS operation which modifies the file system namespace.
74
 */
74
 */
75
RWLOCK_INITIALIZE(namespace_rwlock);
75
FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
76
 
76
 
77
vfs_pair_t rootfs = {
77
vfs_pair_t rootfs = {
78
    .fs_handle = 0,
78
    .fs_handle = 0,
79
    .dev_handle = 0
79
    .dev_handle = 0
80
};
80
};
Line 93... Line 93...
93
    int phone;
93
    int phone;
94
    aid_t msg;
94
    aid_t msg;
95
    ipc_call_t answer;
95
    ipc_call_t answer;
96
   
96
   
97
    /* Resolve the path to the mountpoint. */
97
    /* Resolve the path to the mountpoint. */
98
    rwlock_write_lock(&namespace_rwlock);
98
    fibril_rwlock_write_lock(&namespace_rwlock);
99
    if (rootfs.fs_handle) {
99
    if (rootfs.fs_handle) {
100
        /* We already have the root FS. */
100
        /* We already have the root FS. */
101
        if (str_cmp(mp, "/") == 0) {
101
        if (str_cmp(mp, "/") == 0) {
102
            /* Trying to mount root FS over root FS */
102
            /* Trying to mount root FS over root FS */
-
 
103
            fibril_rwlock_write_unlock(&namespace_rwlock);
103
            ipc_answer_0(rid, EBUSY);
104
            ipc_answer_0(rid, EBUSY);
104
            rwlock_write_unlock(&namespace_rwlock);
-
 
105
            return;
105
            return;
106
        }
106
        }
107
       
107
       
108
        rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
108
        rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
109
        if (rc != EOK) {
109
        if (rc != EOK) {
110
            /* The lookup failed for some reason. */
110
            /* The lookup failed for some reason. */
-
 
111
            fibril_rwlock_write_unlock(&namespace_rwlock);
111
            ipc_answer_0(rid, rc);
112
            ipc_answer_0(rid, rc);
112
            rwlock_write_unlock(&namespace_rwlock);
-
 
113
            return;
113
            return;
114
        }
114
        }
115
       
115
       
116
        mp_node = vfs_node_get(&mp_res);
116
        mp_node = vfs_node_get(&mp_res);
117
        if (!mp_node) {
117
        if (!mp_node) {
-
 
118
            fibril_rwlock_write_unlock(&namespace_rwlock);
118
            ipc_answer_0(rid, ENOMEM);
119
            ipc_answer_0(rid, ENOMEM);
119
            rwlock_write_unlock(&namespace_rwlock);
-
 
120
            return;
120
            return;
121
        }
121
        }
122
       
122
       
123
        /*
123
        /*
124
         * Now we hold a reference to mp_node.
124
         * Now we hold a reference to mp_node.
Line 139... Line 139...
139
                (ipcarg_t) dev_handle, &answer);
139
                (ipcarg_t) dev_handle, &answer);
140
            /* send the mount options */
140
            /* send the mount options */
141
            rc = ipc_data_write_start(phone, (void *)opts,
141
            rc = ipc_data_write_start(phone, (void *)opts,
142
                str_size(opts));
142
                str_size(opts));
143
            if (rc != EOK) {
143
            if (rc != EOK) {
144
                async_wait_for(msg, NULL);
-
 
145
                vfs_release_phone(phone);
144
                vfs_release_phone(phone);
-
 
145
                async_wait_for(msg, NULL);
-
 
146
                fibril_rwlock_write_unlock(&namespace_rwlock);
146
                ipc_answer_0(rid, rc);
147
                ipc_answer_0(rid, rc);
147
                rwlock_write_unlock(&namespace_rwlock);
-
 
148
                return;
148
                return;
149
            }
149
            }
150
            async_wait_for(msg, &rc);
-
 
151
            vfs_release_phone(phone);
150
            vfs_release_phone(phone);
-
 
151
            async_wait_for(msg, &rc);
152
           
152
           
153
            if (rc != EOK) {
153
            if (rc != EOK) {
-
 
154
                fibril_rwlock_write_unlock(&namespace_rwlock);
154
                ipc_answer_0(rid, rc);
155
                ipc_answer_0(rid, rc);
155
                rwlock_write_unlock(&namespace_rwlock);
-
 
156
                return;
156
                return;
157
            }
157
            }
158
 
158
 
159
            rindex = (fs_index_t) IPC_GET_ARG1(answer);
159
            rindex = (fs_index_t) IPC_GET_ARG1(answer);
160
            rsize = (size_t) IPC_GET_ARG2(answer);
160
            rsize = (size_t) IPC_GET_ARG2(answer);
Line 172... Line 172...
172
           
172
           
173
            /* Add reference to the mounted root. */
173
            /* Add reference to the mounted root. */
174
            mr_node = vfs_node_get(&mr_res);
174
            mr_node = vfs_node_get(&mr_res);
175
            assert(mr_node);
175
            assert(mr_node);
176
           
176
           
-
 
177
            fibril_rwlock_write_unlock(&namespace_rwlock);
177
            ipc_answer_0(rid, rc);
178
            ipc_answer_0(rid, rc);
178
            rwlock_write_unlock(&namespace_rwlock);
-
 
179
            return;
179
            return;
180
        } else {
180
        } else {
181
            /*
181
            /*
182
             * We can't resolve this without the root filesystem
182
             * We can't resolve this without the root filesystem
183
             * being mounted first.
183
             * being mounted first.
184
             */
184
             */
-
 
185
            fibril_rwlock_write_unlock(&namespace_rwlock);
185
            ipc_answer_0(rid, ENOENT);
186
            ipc_answer_0(rid, ENOENT);
186
            rwlock_write_unlock(&namespace_rwlock);
-
 
187
            return;
187
            return;
188
        }
188
        }
189
    }
189
    }
190
   
190
   
191
    /*
191
    /*
Line 205... Line 205...
205
        (ipcarg_t) dev_handle, &answer);
205
        (ipcarg_t) dev_handle, &answer);
206
   
206
   
207
    /* send connection */
207
    /* send connection */
208
    rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
208
    rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
209
    if (rc != EOK) {
209
    if (rc != EOK) {
210
        async_wait_for(msg, NULL);
-
 
211
        vfs_release_phone(phone);
210
        vfs_release_phone(phone);
-
 
211
        async_wait_for(msg, NULL);
212
        /* Mount failed, drop reference to mp_node. */
212
        /* Mount failed, drop reference to mp_node. */
213
        if (mp_node)
213
        if (mp_node)
214
            vfs_node_put(mp_node);
214
            vfs_node_put(mp_node);
215
        ipc_answer_0(rid, rc);
215
        ipc_answer_0(rid, rc);
216
        rwlock_write_unlock(&namespace_rwlock);
216
        fibril_rwlock_write_unlock(&namespace_rwlock);
217
        return;
217
        return;
218
    }
218
    }
219
   
219
   
220
    /* send the mount options */
220
    /* send the mount options */
221
    rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
221
    rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
222
    if (rc != EOK) {
222
    if (rc != EOK) {
223
        async_wait_for(msg, NULL);
-
 
224
        vfs_release_phone(phone);
223
        vfs_release_phone(phone);
-
 
224
        async_wait_for(msg, NULL);
225
        /* Mount failed, drop reference to mp_node. */
225
        /* Mount failed, drop reference to mp_node. */
226
        if (mp_node)
226
        if (mp_node)
227
            vfs_node_put(mp_node);
227
            vfs_node_put(mp_node);
-
 
228
        fibril_rwlock_write_unlock(&namespace_rwlock);
228
        ipc_answer_0(rid, rc);
229
        ipc_answer_0(rid, rc);
229
        rwlock_write_unlock(&namespace_rwlock);
-
 
230
        return;
230
        return;
231
    }
231
    }
232
    async_wait_for(msg, &rc);
-
 
233
    vfs_release_phone(phone);
232
    vfs_release_phone(phone);
-
 
233
    async_wait_for(msg, &rc);
234
   
234
   
235
    if (rc == EOK) {
235
    if (rc == EOK) {
236
        rindex = (fs_index_t) IPC_GET_ARG1(answer);
236
        rindex = (fs_index_t) IPC_GET_ARG1(answer);
237
        rsize = (size_t) IPC_GET_ARG2(answer);
237
        rsize = (size_t) IPC_GET_ARG2(answer);
238
        rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
238
        rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
Line 252... Line 252...
252
        if (mp_node)
252
        if (mp_node)
253
            vfs_node_put(mp_node);
253
            vfs_node_put(mp_node);
254
    }
254
    }
255
 
255
 
256
    ipc_answer_0(rid, rc);
256
    ipc_answer_0(rid, rc);
257
    rwlock_write_unlock(&namespace_rwlock);
257
    fibril_rwlock_write_unlock(&namespace_rwlock);
258
}
258
}
259
 
259
 
260
/** Process pending mount requests */
260
/** Process pending mount requests */
261
void vfs_process_pending_mount(void)
261
void vfs_process_pending_mount(void)
262
{
262
{
Line 506... Line 506...
506
   
506
   
507
    /*
507
    /*
508
     * Make sure that we are called with exactly one of L_FILE and
508
     * Make sure that we are called with exactly one of L_FILE and
509
     * L_DIRECTORY. Make sure that the user does not pass L_OPEN.
509
     * L_DIRECTORY. Make sure that the user does not pass L_OPEN.
510
     */
510
     */
511
    if (((lflag & (L_FILE | L_DIRECTORY)) == 0)
511
    if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
512
        || ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY))
512
        ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
513
        || ((lflag & L_OPEN) != 0)) {
513
        ((lflag & L_OPEN) != 0)) {
514
        ipc_answer_0(rid, EINVAL);
514
        ipc_answer_0(rid, EINVAL);
515
        return;
515
        return;
516
    }
516
    }
517
   
517
   
518
    if (oflag & O_CREAT)
518
    if (oflag & O_CREAT)
Line 546... Line 546...
546
     * Avoid the race condition in which the file can be deleted before we
546
     * Avoid the race condition in which the file can be deleted before we
547
     * find/create-and-lock the VFS node corresponding to the looked-up
547
     * find/create-and-lock the VFS node corresponding to the looked-up
548
     * triplet.
548
     * triplet.
549
     */
549
     */
550
    if (lflag & L_CREATE)
550
    if (lflag & L_CREATE)
551
        rwlock_write_lock(&namespace_rwlock);
551
        fibril_rwlock_write_lock(&namespace_rwlock);
552
    else
552
    else
553
        rwlock_read_lock(&namespace_rwlock);
553
        fibril_rwlock_read_lock(&namespace_rwlock);
554
   
554
   
555
    /* The path is now populated and we can call vfs_lookup_internal(). */
555
    /* The path is now populated and we can call vfs_lookup_internal(). */
556
    vfs_lookup_res_t lr;
556
    vfs_lookup_res_t lr;
557
    rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
557
    rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
558
    if (rc != EOK) {
558
    if (rc != EOK) {
559
        if (lflag & L_CREATE)
559
        if (lflag & L_CREATE)
560
            rwlock_write_unlock(&namespace_rwlock);
560
            fibril_rwlock_write_unlock(&namespace_rwlock);
561
        else
561
        else
562
            rwlock_read_unlock(&namespace_rwlock);
562
            fibril_rwlock_read_unlock(&namespace_rwlock);
563
        ipc_answer_0(rid, rc);
563
        ipc_answer_0(rid, rc);
564
        free(path);
564
        free(path);
565
        return;
565
        return;
566
    }
566
    }
567
   
567
   
568
    /* Path is no longer needed. */
568
    /* Path is no longer needed. */
569
    free(path);
569
    free(path);
570
   
570
   
571
    vfs_node_t *node = vfs_node_get(&lr);
571
    vfs_node_t *node = vfs_node_get(&lr);
572
    if (lflag & L_CREATE)
572
    if (lflag & L_CREATE)
573
        rwlock_write_unlock(&namespace_rwlock);
573
        fibril_rwlock_write_unlock(&namespace_rwlock);
574
    else
574
    else
575
        rwlock_read_unlock(&namespace_rwlock);
575
        fibril_rwlock_read_unlock(&namespace_rwlock);
576
   
576
   
577
    /* Truncate the file if requested and if necessary. */
577
    /* Truncate the file if requested and if necessary. */
578
    if (oflag & O_TRUNC) {
578
    if (oflag & O_TRUNC) {
579
        rwlock_write_lock(&node->contents_rwlock);
579
        fibril_rwlock_write_lock(&node->contents_rwlock);
580
        if (node->size) {
580
        if (node->size) {
581
            rc = vfs_truncate_internal(node->fs_handle,
581
            rc = vfs_truncate_internal(node->fs_handle,
582
                node->dev_handle, node->index, 0);
582
                node->dev_handle, node->index, 0);
583
            if (rc) {
583
            if (rc) {
584
                rwlock_write_unlock(&node->contents_rwlock);
584
                fibril_rwlock_write_unlock(&node->contents_rwlock);
585
                vfs_node_put(node);
585
                vfs_node_put(node);
586
                ipc_answer_0(rid, rc);
586
                ipc_answer_0(rid, rc);
587
                return;
587
                return;
588
            }
588
            }
589
            node->size = 0;
589
            node->size = 0;
590
        }
590
        }
591
        rwlock_write_unlock(&node->contents_rwlock);
591
        fibril_rwlock_write_unlock(&node->contents_rwlock);
592
    }
592
    }
593
   
593
   
594
    /*
594
    /*
595
     * Get ourselves a file descriptor and the corresponding vfs_file_t
595
     * Get ourselves a file descriptor and the corresponding vfs_file_t
596
     * structure.
596
     * structure.
Line 637... Line 637...
637
    lr.triplet.fs_handle = IPC_GET_ARG1(*request);
637
    lr.triplet.fs_handle = IPC_GET_ARG1(*request);
638
    lr.triplet.dev_handle = IPC_GET_ARG2(*request);
638
    lr.triplet.dev_handle = IPC_GET_ARG2(*request);
639
    lr.triplet.index = IPC_GET_ARG3(*request);
639
    lr.triplet.index = IPC_GET_ARG3(*request);
640
    int oflag = IPC_GET_ARG4(*request);
640
    int oflag = IPC_GET_ARG4(*request);
641
   
641
   
642
    rwlock_read_lock(&namespace_rwlock);
642
    fibril_rwlock_read_lock(&namespace_rwlock);
643
   
643
   
644
    int rc = vfs_open_node_internal(&lr);
644
    int rc = vfs_open_node_internal(&lr);
645
    if (rc != EOK) {
645
    if (rc != EOK) {
646
        rwlock_read_unlock(&namespace_rwlock);
646
        fibril_rwlock_read_unlock(&namespace_rwlock);
647
        ipc_answer_0(rid, rc);
647
        ipc_answer_0(rid, rc);
648
        return;
648
        return;
649
    }
649
    }
650
   
650
   
651
    vfs_node_t *node = vfs_node_get(&lr);
651
    vfs_node_t *node = vfs_node_get(&lr);
652
    rwlock_read_unlock(&namespace_rwlock);
652
    fibril_rwlock_read_unlock(&namespace_rwlock);
653
   
653
   
654
    /* Truncate the file if requested and if necessary. */
654
    /* Truncate the file if requested and if necessary. */
655
    if (oflag & O_TRUNC) {
655
    if (oflag & O_TRUNC) {
656
        rwlock_write_lock(&node->contents_rwlock);
656
        fibril_rwlock_write_lock(&node->contents_rwlock);
657
        if (node->size) {
657
        if (node->size) {
658
            rc = vfs_truncate_internal(node->fs_handle,
658
            rc = vfs_truncate_internal(node->fs_handle,
659
                node->dev_handle, node->index, 0);
659
                node->dev_handle, node->index, 0);
660
            if (rc) {
660
            if (rc) {
661
                rwlock_write_unlock(&node->contents_rwlock);
661
                fibril_rwlock_write_unlock(&node->contents_rwlock);
662
                vfs_node_put(node);
662
                vfs_node_put(node);
663
                ipc_answer_0(rid, rc);
663
                ipc_answer_0(rid, rc);
664
                return;
664
                return;
665
            }
665
            }
666
            node->size = 0;
666
            node->size = 0;
667
        }
667
        }
668
        rwlock_write_unlock(&node->contents_rwlock);
668
        fibril_rwlock_write_unlock(&node->contents_rwlock);
669
    }
669
    }
670
   
670
   
671
    /*
671
    /*
672
     * Get ourselves a file descriptor and the corresponding vfs_file_t
672
     * Get ourselves a file descriptor and the corresponding vfs_file_t
673
     * structure.
673
     * structure.
Line 706... Line 706...
706
    if (!file) {
706
    if (!file) {
707
        ipc_answer_0(rid, ENOENT);
707
        ipc_answer_0(rid, ENOENT);
708
        return;
708
        return;
709
    }
709
    }
710
   
710
   
711
    ipc_answer_3(rid, EOK, file->node->fs_handle,
711
    ipc_answer_3(rid, EOK, file->node->fs_handle, file->node->dev_handle,
712
        file->node->dev_handle, file->node->index);
712
        file->node->index);
713
}
713
}
714
 
714
 
715
void vfs_device(ipc_callid_t rid, ipc_call_t *request)
715
void vfs_device(ipc_callid_t rid, ipc_call_t *request)
716
{
716
{
717
    int fd = IPC_GET_ARG1(*request);
717
    int fd = IPC_GET_ARG1(*request);
Line 725... Line 725...
725
   
725
   
726
    /*
726
    /*
727
     * Lock the open file structure so that no other thread can manipulate
727
     * Lock the open file structure so that no other thread can manipulate
728
     * the same open file at a time.
728
     * the same open file at a time.
729
     */
729
     */
730
    futex_down(&file->lock);
730
    fibril_mutex_lock(&file->lock);
731
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
731
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
732
   
732
   
733
    /* Make a VFS_DEVICE request at the destination FS server. */
733
    /* Make a VFS_DEVICE request at the destination FS server. */
734
    aid_t msg;
734
    aid_t msg;
735
    ipc_call_t answer;
735
    ipc_call_t answer;
736
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
736
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
737
        file->node->dev_handle, file->node->index, &answer);
737
        file->node->dev_handle, file->node->index, &answer);
738
   
738
   
-
 
739
    vfs_release_phone(fs_phone);
-
 
740
 
739
    /* Wait for reply from the FS server. */
741
    /* Wait for reply from the FS server. */
740
    ipcarg_t rc;
742
    ipcarg_t rc;
741
    async_wait_for(msg, &rc);
743
    async_wait_for(msg, &rc);
742
   
744
   
743
    vfs_release_phone(fs_phone);
-
 
744
    futex_up(&file->lock);
745
    fibril_mutex_unlock(&file->lock);
745
   
746
   
746
    ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer));
747
    ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer));
747
}
748
}
748
 
749
 
749
void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
750
void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
Line 759... Line 760...
759
   
760
   
760
    /*
761
    /*
761
     * Lock the open file structure so that no other thread can manipulate
762
     * Lock the open file structure so that no other thread can manipulate
762
     * the same open file at a time.
763
     * the same open file at a time.
763
     */
764
     */
764
    futex_down(&file->lock);
765
    fibril_mutex_lock(&file->lock);
765
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
766
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
766
   
767
   
767
    /* Make a VFS_SYMC request at the destination FS server. */
768
    /* Make a VFS_SYMC request at the destination FS server. */
768
    aid_t msg;
769
    aid_t msg;
769
    ipc_call_t answer;
770
    ipc_call_t answer;
770
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
771
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
771
        file->node->dev_handle, file->node->index, &answer);
772
        file->node->dev_handle, file->node->index, &answer);
-
 
773
 
-
 
774
    vfs_release_phone(fs_phone);
772
   
775
 
773
    /* Wait for reply from the FS server. */
776
    /* Wait for reply from the FS server. */
774
    ipcarg_t rc;
777
    ipcarg_t rc;
775
    async_wait_for(msg, &rc);
778
    async_wait_for(msg, &rc);
776
   
779
   
777
    vfs_release_phone(fs_phone);
-
 
778
    futex_up(&file->lock);
780
    fibril_mutex_unlock(&file->lock);
779
   
781
   
780
    ipc_answer_0(rid, rc);
782
    ipc_answer_0(rid, rc);
781
}
783
}
782
 
784
 
783
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
785
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
Line 793... Line 795...
793
   
795
   
794
    /*
796
    /*
795
     * Lock the open file structure so that no other thread can manipulate
797
     * Lock the open file structure so that no other thread can manipulate
796
     * the same open file at a time.
798
     * the same open file at a time.
797
     */
799
     */
798
    futex_down(&file->lock);
800
    fibril_mutex_lock(&file->lock);
799
   
801
   
800
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
802
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
801
   
803
   
802
    /* Make a VFS_CLOSE request at the destination FS server. */
804
    /* Make a VFS_CLOSE request at the destination FS server. */
803
    aid_t msg;
805
    aid_t msg;
804
    ipc_call_t answer;
806
    ipc_call_t answer;
805
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
807
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
806
        file->node->dev_handle, file->node->index, &answer);
808
        file->node->dev_handle, file->node->index, &answer);
-
 
809
 
-
 
810
    vfs_release_phone(fs_phone);
807
   
811
   
808
    /* Wait for reply from the FS server. */
812
    /* Wait for reply from the FS server. */
809
    ipcarg_t rc;
813
    ipcarg_t rc;
810
    async_wait_for(msg, &rc);
814
    async_wait_for(msg, &rc);
811
   
815
   
812
    vfs_release_phone(fs_phone);
-
 
813
    futex_up(&file->lock);
816
    fibril_mutex_unlock(&file->lock);
814
   
817
   
815
    int retval = IPC_GET_ARG1(answer);
818
    int retval = IPC_GET_ARG1(answer);
816
    if (retval != EOK)
819
    if (retval != EOK)
817
        ipc_answer_0(rid, retval);
820
        ipc_answer_0(rid, retval);
818
   
821
   
Line 860... Line 863...
860
   
863
   
861
    /*
864
    /*
862
     * Lock the open file structure so that no other thread can manipulate
865
     * Lock the open file structure so that no other thread can manipulate
863
     * the same open file at a time.
866
     * the same open file at a time.
864
     */
867
     */
865
    futex_down(&file->lock);
868
    fibril_mutex_lock(&file->lock);
866
 
869
 
867
    /*
870
    /*
868
     * Lock the file's node so that no other client can read/write to it at
871
     * Lock the file's node so that no other client can read/write to it at
869
     * the same time.
872
     * the same time.
870
     */
873
     */
871
    if (read)
874
    if (read)
872
        rwlock_read_lock(&file->node->contents_rwlock);
875
        fibril_rwlock_read_lock(&file->node->contents_rwlock);
873
    else
876
    else
874
        rwlock_write_lock(&file->node->contents_rwlock);
877
        fibril_rwlock_write_lock(&file->node->contents_rwlock);
875
 
878
 
876
    if (file->node->type == VFS_NODE_DIRECTORY) {
879
    if (file->node->type == VFS_NODE_DIRECTORY) {
877
        /*
880
        /*
878
         * Make sure that no one is modifying the namespace
881
         * Make sure that no one is modifying the namespace
879
         * while we are in readdir().
882
         * while we are in readdir().
880
         */
883
         */
881
        assert(read);
884
        assert(read);
882
        rwlock_read_lock(&namespace_rwlock);
885
        fibril_rwlock_read_lock(&namespace_rwlock);
883
    }
886
    }
884
   
887
   
885
    int fs_phone = vfs_grab_phone(file->node->fs_handle);  
888
    int fs_phone = vfs_grab_phone(file->node->fs_handle);  
886
   
889
   
887
    /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
890
    /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
Line 897... Line 900...
897
     * destination FS server. The call will be routed as if sent by
900
     * destination FS server. The call will be routed as if sent by
898
     * ourselves. Note that call arguments are immutable in this case so we
901
     * ourselves. Note that call arguments are immutable in this case so we
899
     * don't have to bother.
902
     * don't have to bother.
900
     */
903
     */
901
    ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
904
    ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
-
 
905
 
-
 
906
    vfs_release_phone(fs_phone);
902
   
907
   
903
    /* Wait for reply from the FS server. */
908
    /* Wait for reply from the FS server. */
904
    ipcarg_t rc;
909
    ipcarg_t rc;
905
    async_wait_for(msg, &rc);
910
    async_wait_for(msg, &rc);
906
   
911
   
907
    vfs_release_phone(fs_phone);
-
 
908
   
-
 
909
    size_t bytes = IPC_GET_ARG1(answer);
912
    size_t bytes = IPC_GET_ARG1(answer);
910
 
913
 
911
    if (file->node->type == VFS_NODE_DIRECTORY)
914
    if (file->node->type == VFS_NODE_DIRECTORY)
912
        rwlock_read_unlock(&namespace_rwlock);
915
        fibril_rwlock_read_unlock(&namespace_rwlock);
913
   
916
   
914
    /* Unlock the VFS node. */
917
    /* Unlock the VFS node. */
915
    if (read)
918
    if (read)
916
        rwlock_read_unlock(&file->node->contents_rwlock);
919
        fibril_rwlock_read_unlock(&file->node->contents_rwlock);
917
    else {
920
    else {
918
        /* Update the cached version of node's size. */
921
        /* Update the cached version of node's size. */
919
        if (rc == EOK)
922
        if (rc == EOK)
920
            file->node->size = IPC_GET_ARG2(answer);
923
            file->node->size = IPC_GET_ARG2(answer);
921
        rwlock_write_unlock(&file->node->contents_rwlock);
924
        fibril_rwlock_write_unlock(&file->node->contents_rwlock);
922
    }
925
    }
923
   
926
   
924
    /* Update the position pointer and unlock the open file. */
927
    /* Update the position pointer and unlock the open file. */
925
    if (rc == EOK)
928
    if (rc == EOK)
926
        file->pos += bytes;
929
        file->pos += bytes;
927
    futex_up(&file->lock);
930
    fibril_mutex_unlock(&file->lock);
928
   
931
   
929
    /*
932
    /*
930
     * FS server's reply is the final result of the whole operation we
933
     * FS server's reply is the final result of the whole operation we
931
     * return to the client.
934
     * return to the client.
932
     */
935
     */
Line 956... Line 959...
956
        ipc_answer_0(rid, ENOENT);
959
        ipc_answer_0(rid, ENOENT);
957
        return;
960
        return;
958
    }
961
    }
959
 
962
 
960
    off_t newpos;
963
    off_t newpos;
961
    futex_down(&file->lock);
964
    fibril_mutex_lock(&file->lock);
962
    if (whence == SEEK_SET) {
965
    if (whence == SEEK_SET) {
963
        file->pos = off;
966
        file->pos = off;
964
        futex_up(&file->lock);
967
        fibril_mutex_unlock(&file->lock);
965
        ipc_answer_1(rid, EOK, off);
968
        ipc_answer_1(rid, EOK, off);
966
        return;
969
        return;
967
    }
970
    }
968
    if (whence == SEEK_CUR) {
971
    if (whence == SEEK_CUR) {
969
        if (file->pos + off < file->pos) {
972
        if (file->pos + off < file->pos) {
970
            futex_up(&file->lock);
973
            fibril_mutex_unlock(&file->lock);
971
            ipc_answer_0(rid, EOVERFLOW);
974
            ipc_answer_0(rid, EOVERFLOW);
972
            return;
975
            return;
973
        }
976
        }
974
        file->pos += off;
977
        file->pos += off;
975
        newpos = file->pos;
978
        newpos = file->pos;
976
        futex_up(&file->lock);
979
        fibril_mutex_unlock(&file->lock);
977
        ipc_answer_1(rid, EOK, newpos);
980
        ipc_answer_1(rid, EOK, newpos);
978
        return;
981
        return;
979
    }
982
    }
980
    if (whence == SEEK_END) {
983
    if (whence == SEEK_END) {
981
        rwlock_read_lock(&file->node->contents_rwlock);
984
        fibril_rwlock_read_lock(&file->node->contents_rwlock);
982
        size_t size = file->node->size;
985
        size_t size = file->node->size;
983
        rwlock_read_unlock(&file->node->contents_rwlock);
986
        fibril_rwlock_read_unlock(&file->node->contents_rwlock);
984
        if (size + off < size) {
987
        if (size + off < size) {
985
            futex_up(&file->lock);
988
            fibril_mutex_unlock(&file->lock);
986
            ipc_answer_0(rid, EOVERFLOW);
989
            ipc_answer_0(rid, EOVERFLOW);
987
            return;
990
            return;
988
        }
991
        }
989
        newpos = size + off;
992
        newpos = size + off;
990
        futex_up(&file->lock);
993
        fibril_mutex_unlock(&file->lock);
991
        ipc_answer_1(rid, EOK, newpos);
994
        ipc_answer_1(rid, EOK, newpos);
992
        return;
995
        return;
993
    }
996
    }
994
    futex_up(&file->lock);
997
    fibril_mutex_unlock(&file->lock);
995
    ipc_answer_0(rid, EINVAL);
998
    ipc_answer_0(rid, EINVAL);
996
}
999
}
997
 
1000
 
998
int
1001
int
999
vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,
1002
vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,
Line 1018... Line 1021...
1018
    vfs_file_t *file = vfs_file_get(fd);
1021
    vfs_file_t *file = vfs_file_get(fd);
1019
    if (!file) {
1022
    if (!file) {
1020
        ipc_answer_0(rid, ENOENT);
1023
        ipc_answer_0(rid, ENOENT);
1021
        return;
1024
        return;
1022
    }
1025
    }
1023
    futex_down(&file->lock);
1026
    fibril_mutex_lock(&file->lock);
1024
 
1027
 
1025
    rwlock_write_lock(&file->node->contents_rwlock);
1028
    fibril_rwlock_write_lock(&file->node->contents_rwlock);
1026
    rc = vfs_truncate_internal(file->node->fs_handle,
1029
    rc = vfs_truncate_internal(file->node->fs_handle,
1027
        file->node->dev_handle, file->node->index, size);
1030
        file->node->dev_handle, file->node->index, size);
1028
    if (rc == EOK)
1031
    if (rc == EOK)
1029
        file->node->size = size;
1032
        file->node->size = size;
1030
    rwlock_write_unlock(&file->node->contents_rwlock);
1033
    fibril_rwlock_write_unlock(&file->node->contents_rwlock);
1031
 
1034
 
1032
    futex_up(&file->lock);
1035
    fibril_mutex_unlock(&file->lock);
1033
    ipc_answer_0(rid, (ipcarg_t)rc);
1036
    ipc_answer_0(rid, (ipcarg_t)rc);
1034
}
1037
}
1035
 
1038
 
1036
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request)
1039
void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request)
1037
{
1040
{
Line 1057... Line 1060...
1057
        free(path);
1060
        free(path);
1058
        return;
1061
        return;
1059
    }
1062
    }
1060
    path[len] = '\0';
1063
    path[len] = '\0';
1061
   
1064
   
1062
    rwlock_write_lock(&namespace_rwlock);
1065
    fibril_rwlock_write_lock(&namespace_rwlock);
1063
    int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE;
1066
    int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE;
1064
    rc = vfs_lookup_internal(path, lflag, NULL, NULL);
1067
    rc = vfs_lookup_internal(path, lflag, NULL, NULL);
1065
    rwlock_write_unlock(&namespace_rwlock);
1068
    fibril_rwlock_write_unlock(&namespace_rwlock);
1066
    free(path);
1069
    free(path);
1067
    ipc_answer_0(rid, rc);
1070
    ipc_answer_0(rid, rc);
1068
}
1071
}
1069
 
1072
 
1070
void vfs_unlink(ipc_callid_t rid, ipc_call_t *request)
1073
void vfs_unlink(ipc_callid_t rid, ipc_call_t *request)
Line 1091... Line 1094...
1091
        free(path);
1094
        free(path);
1092
        return;
1095
        return;
1093
    }
1096
    }
1094
    path[len] = '\0';
1097
    path[len] = '\0';
1095
   
1098
   
1096
    rwlock_write_lock(&namespace_rwlock);
1099
    fibril_rwlock_write_lock(&namespace_rwlock);
1097
    lflag &= L_DIRECTORY;   /* sanitize lflag */
1100
    lflag &= L_DIRECTORY;   /* sanitize lflag */
1098
    vfs_lookup_res_t lr;
1101
    vfs_lookup_res_t lr;
1099
    rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL);
1102
    rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL);
1100
    free(path);
1103
    free(path);
1101
    if (rc != EOK) {
1104
    if (rc != EOK) {
1102
        rwlock_write_unlock(&namespace_rwlock);
1105
        fibril_rwlock_write_unlock(&namespace_rwlock);
1103
        ipc_answer_0(rid, rc);
1106
        ipc_answer_0(rid, rc);
1104
        return;
1107
        return;
1105
    }
1108
    }
1106
 
1109
 
1107
    /*
1110
    /*
Line 1111... Line 1114...
1111
     */
1114
     */
1112
    vfs_node_t *node = vfs_node_get(&lr);
1115
    vfs_node_t *node = vfs_node_get(&lr);
1113
    futex_down(&nodes_futex);
1116
    futex_down(&nodes_futex);
1114
    node->lnkcnt--;
1117
    node->lnkcnt--;
1115
    futex_up(&nodes_futex);
1118
    futex_up(&nodes_futex);
1116
    rwlock_write_unlock(&namespace_rwlock);
1119
    fibril_rwlock_write_unlock(&namespace_rwlock);
1117
    vfs_node_put(node);
1120
    vfs_node_put(node);
1118
    ipc_answer_0(rid, EOK);
1121
    ipc_answer_0(rid, EOK);
1119
}
1122
}
1120
 
1123
 
1121
void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
1124
void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
Line 1192... Line 1195...
1192
    }
1195
    }
1193
   
1196
   
1194
    vfs_lookup_res_t old_lr;
1197
    vfs_lookup_res_t old_lr;
1195
    vfs_lookup_res_t new_lr;
1198
    vfs_lookup_res_t new_lr;
1196
    vfs_lookup_res_t new_par_lr;
1199
    vfs_lookup_res_t new_par_lr;
1197
    rwlock_write_lock(&namespace_rwlock);
1200
    fibril_rwlock_write_lock(&namespace_rwlock);
1198
    /* Lookup the node belonging to the old file name. */
1201
    /* Lookup the node belonging to the old file name. */
1199
    rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
1202
    rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
1200
    if (rc != EOK) {
1203
    if (rc != EOK) {
1201
        rwlock_write_unlock(&namespace_rwlock);
1204
        fibril_rwlock_write_unlock(&namespace_rwlock);
1202
        ipc_answer_0(rid, rc);
1205
        ipc_answer_0(rid, rc);
1203
        free(old);
1206
        free(old);
1204
        free(new);
1207
        free(new);
1205
        return;
1208
        return;
1206
    }
1209
    }
1207
    vfs_node_t *old_node = vfs_node_get(&old_lr);
1210
    vfs_node_t *old_node = vfs_node_get(&old_lr);
1208
    if (!old_node) {
1211
    if (!old_node) {
1209
        rwlock_write_unlock(&namespace_rwlock);
1212
        fibril_rwlock_write_unlock(&namespace_rwlock);
1210
        ipc_answer_0(rid, ENOMEM);
1213
        ipc_answer_0(rid, ENOMEM);
1211
        free(old);
1214
        free(old);
1212
        free(new);
1215
        free(new);
1213
        return;
1216
        return;
1214
    }
1217
    }
1215
    /* Determine the path to the parent of the node with the new name. */
1218
    /* Determine the path to the parent of the node with the new name. */
1216
    char *parentc = str_dup(newc);
1219
    char *parentc = str_dup(newc);
1217
    if (!parentc) {
1220
    if (!parentc) {
1218
        rwlock_write_unlock(&namespace_rwlock);
1221
        fibril_rwlock_write_unlock(&namespace_rwlock);
1219
        ipc_answer_0(rid, rc);
1222
        ipc_answer_0(rid, rc);
1220
        free(old);
1223
        free(old);
1221
        free(new);
1224
        free(new);
1222
        return;
1225
        return;
1223
    }
1226
    }
Line 1228... Line 1231...
1228
        parentc[1] = '\0';
1231
        parentc[1] = '\0';
1229
    /* Lookup parent of the new file name. */
1232
    /* Lookup parent of the new file name. */
1230
    rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
1233
    rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
1231
    free(parentc);  /* not needed anymore */
1234
    free(parentc);  /* not needed anymore */
1232
    if (rc != EOK) {
1235
    if (rc != EOK) {
1233
        rwlock_write_unlock(&namespace_rwlock);
1236
        fibril_rwlock_write_unlock(&namespace_rwlock);
1234
        ipc_answer_0(rid, rc);
1237
        ipc_answer_0(rid, rc);
1235
        free(old);
1238
        free(old);
1236
        free(new);
1239
        free(new);
1237
        return;
1240
        return;
1238
    }
1241
    }
1239
    /* Check whether linking to the same file system instance. */
1242
    /* Check whether linking to the same file system instance. */
1240
    if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
1243
    if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
1241
        (old_node->dev_handle != new_par_lr.triplet.dev_handle)) {
1244
        (old_node->dev_handle != new_par_lr.triplet.dev_handle)) {
1242
        rwlock_write_unlock(&namespace_rwlock);
1245
        fibril_rwlock_write_unlock(&namespace_rwlock);
1243
        ipc_answer_0(rid, EXDEV);   /* different file systems */
1246
        ipc_answer_0(rid, EXDEV);   /* different file systems */
1244
        free(old);
1247
        free(old);
1245
        free(new);
1248
        free(new);
1246
        return;
1249
        return;
1247
    }
1250
    }
Line 1253... Line 1256...
1253
        /* simply not in our way */
1256
        /* simply not in our way */
1254
        break;
1257
        break;
1255
    case EOK:
1258
    case EOK:
1256
        new_node = vfs_node_get(&new_lr);
1259
        new_node = vfs_node_get(&new_lr);
1257
        if (!new_node) {
1260
        if (!new_node) {
1258
            rwlock_write_unlock(&namespace_rwlock);
1261
            fibril_rwlock_write_unlock(&namespace_rwlock);
1259
            ipc_answer_0(rid, ENOMEM);
1262
            ipc_answer_0(rid, ENOMEM);
1260
            free(old);
1263
            free(old);
1261
            free(new);
1264
            free(new);
1262
            return;
1265
            return;
1263
        }
1266
        }
1264
        futex_down(&nodes_futex);
1267
        futex_down(&nodes_futex);
1265
        new_node->lnkcnt--;
1268
        new_node->lnkcnt--;
1266
        futex_up(&nodes_futex);
1269
        futex_up(&nodes_futex);
1267
        break;
1270
        break;
1268
    default:
1271
    default:
1269
        rwlock_write_unlock(&namespace_rwlock);
1272
        fibril_rwlock_write_unlock(&namespace_rwlock);
1270
        ipc_answer_0(rid, ENOTEMPTY);
1273
        ipc_answer_0(rid, ENOTEMPTY);
1271
        free(old);
1274
        free(old);
1272
        free(new);
1275
        free(new);
1273
        return;
1276
        return;
1274
    }
1277
    }
1275
    /* Create the new link for the new name. */
1278
    /* Create the new link for the new name. */
1276
    rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
1279
    rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
1277
    if (rc != EOK) {
1280
    if (rc != EOK) {
1278
        rwlock_write_unlock(&namespace_rwlock);
1281
        fibril_rwlock_write_unlock(&namespace_rwlock);
1279
        if (new_node)
1282
        if (new_node)
1280
            vfs_node_put(new_node);
1283
            vfs_node_put(new_node);
1281
        ipc_answer_0(rid, rc);
1284
        ipc_answer_0(rid, rc);
1282
        free(old);
1285
        free(old);
1283
        free(new);
1286
        free(new);
Line 1287... Line 1290...
1287
    old_node->lnkcnt++;
1290
    old_node->lnkcnt++;
1288
    futex_up(&nodes_futex);
1291
    futex_up(&nodes_futex);
1289
    /* Destroy the link for the old name. */
1292
    /* Destroy the link for the old name. */
1290
    rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
1293
    rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
1291
    if (rc != EOK) {
1294
    if (rc != EOK) {
1292
        rwlock_write_unlock(&namespace_rwlock);
1295
        fibril_rwlock_write_unlock(&namespace_rwlock);
1293
        vfs_node_put(old_node);
1296
        vfs_node_put(old_node);
1294
        if (new_node)
1297
        if (new_node)
1295
            vfs_node_put(new_node);
1298
            vfs_node_put(new_node);
1296
        ipc_answer_0(rid, rc);
1299
        ipc_answer_0(rid, rc);
1297
        free(old);
1300
        free(old);
Line 1299... Line 1302...
1299
        return;
1302
        return;
1300
    }
1303
    }
1301
    futex_down(&nodes_futex);
1304
    futex_down(&nodes_futex);
1302
    old_node->lnkcnt--;
1305
    old_node->lnkcnt--;
1303
    futex_up(&nodes_futex);
1306
    futex_up(&nodes_futex);
1304
    rwlock_write_unlock(&namespace_rwlock);
1307
    fibril_rwlock_write_unlock(&namespace_rwlock);
1305
    vfs_node_put(old_node);
1308
    vfs_node_put(old_node);
1306
    if (new_node)
1309
    if (new_node)
1307
        vfs_node_put(new_node);
1310
        vfs_node_put(new_node);
1308
    free(old);
1311
    free(old);
1309
    free(new);
1312
    free(new);