source: trunk/kernel/syscalls/sys_stat.c @ 625

Last change on this file since 625 was 624, checked in by alain, 5 years ago

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 4.2 KB
Line 
1/*
2 * sys_stat.c - kernel function implementing the "stat" syscall.
3 *
4 * Author    Alain Greiner  (2016,2017,2018,2019)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_uspace.h>
26#include <hal_vmm.h>
27#include <hal_special.h>
28#include <errno.h>
29#include <thread.h>
30#include <printk.h>
31#include <vfs.h>
32#include <vmm.h>
33#include <process.h>
34
35#include <syscalls.h>
36
37/////////////////////////////////////
38int sys_stat( char        * pathname,
39              struct stat * u_stat )
40{
41    error_t       error;
42    vseg_t      * vseg;                   // for user space checking
43    struct stat   k_stat;                 // in kernel space
44    xptr_t        root_inode_xp;          // extended pointer on path root inode
45
46    char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
47       
48        thread_t  * this    = CURRENT_THREAD;
49        process_t * process = this->process;
50
51#if (DEBUG_SYS_STAT || CONFIG_INSTRUMENTATION_SYSCALLS)
52uint64_t     tm_start = hal_get_cycles();
53#endif
54
55    // check stat structure in user space
56    error = vmm_get_vseg( process , (intptr_t)u_stat , &vseg );
57
58        if( error )
59        {
60
61#if DEBUG_SYSCALLS_ERROR
62printk("\n[ERROR] in %s / thread[%x,%x] : stat structure %x unmapped\n",
63__FUNCTION__ , process->pid , this->trdid, u_stat );
64hal_vmm_display( process , false );
65#endif
66                this->errno = EINVAL;
67                return -1;
68        }       
69
70    // check pathname length
71    if( hal_strlen_from_uspace( pathname ) >= CONFIG_VFS_MAX_PATH_LENGTH )
72    {
73
74#if DEBUG_SYSCALLS_ERROR
75printk("\n[ERROR] in %s / thread[%x,%x] : pathname too long\n",
76 __FUNCTION__ , process->pid , this->trdid );
77#endif
78        this->errno = ENFILE;
79        return -1;
80    }
81
82    // copy pathname in kernel space
83    hal_strcpy_from_uspace( kbuf , pathname , CONFIG_VFS_MAX_PATH_LENGTH );
84
85#if DEBUG_SYS_STAT
86if( DEBUG_SYS_STAT < tm_start )
87printk("\n[%s] thread[%x,%x] enter for file <%s> / cycle %d\n",
88__FUNCTION__, process->pid, this->trdid, kbuf, (uint32_t)tm_start );
89#endif
90
91    // compute root inode for path
92    if( kbuf[0] == '/' )                        // absolute path
93    {
94        // use extended pointer on VFS root inode
95        root_inode_xp = process->vfs_root_xp;
96    }
97    else                                        // relative path
98    {
99        // get cluster and local pointer on reference process
100        xptr_t      ref_xp  = process->ref_xp;
101        process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
102        cxy_t       ref_cxy = GET_CXY( ref_xp );
103
104        // use extended pointer on CWD inode
105        root_inode_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->cwd_xp ) );
106    }
107
108    // call the relevant VFS function
109    error = vfs_stat( root_inode_xp,
110                      kbuf,
111                      &k_stat ); 
112    if( error )
113        {
114
115#if DEBUG_SYSCALLS_ERROR
116printk("\n[ERROR] in %s / thread[%x,%x] : cannot get stats for inode <%s>\n",
117__FUNCTION__ , process->pid , this->trdid , pathname );
118#endif
119                this->errno = ENFILE;
120                return -1;
121        }
122   
123    // copy k_stat to u_stat
124    hal_copy_to_uspace( u_stat , &k_stat , sizeof(struct stat) );
125
126    hal_fence();
127
128#if (DEBUG_SYS_STAT || CONFIG_INSTRUMENTATION_SYSCALLS)
129uint64_t     tm_end = hal_get_cycles();
130#endif
131
132#if DEBUG_SYS_STAT
133if( DEBUG_SYS_STAT < tm_end )
134printk("\n[%s] thread[%x,%x] exit for file <%s> / size %d / mode %d / cycle %d\n",
135__FUNCTION__, process->pid, this->trdid, kbuf,
136k_stat.st_size, k_stat.st_mode, (uint32_t)tm_end );
137#endif
138 
139#if CONFIG_INSTRUMENTATION_SYSCALLS
140hal_atomic_add( &syscalls_cumul_cost[SYS_STAT] , tm_end - tm_start );
141hal_atomic_add( &syscalls_occurences[SYS_STAT] , 1 );
142#endif
143
144        return 0;
145
146}  // end sys_stat()
147
Note: See TracBrowser for help on using the repository browser.