Quote:
Originally Posted by GroupInode
Thank you for your reply monkeyboy.
I have decided to go with your suggestion. I am now stuck as to how is VFS actually triggered in the file system. I read vfs_syscalls.c , vfs_nops.c as well as vfs_ops.c etc.
Now the real puzzle for me is that, for the actual inode and the dinode structures the system calls like stat() and open() have only two arguments. Whereas, the similar system calls specified by VFS have 5 arguments ( most probably taking the form of struct fileops).
I tried to search a lot but couldn't get the actual place where the distinction is made OR where the 2 arguments become 5 arguments and back again. Really need some help with this.
I need to trace
1. How the system calls are invoked
2. Referring which source code files
3. Also need to check the arguments and their return values
4. FINALLY, the transition from the 2 argument format to 5 argument format
Any ideas?
|
I don't have ready access to full source right now. I can't answer all your questions. However I will try to take a few stabs.
First, I don't think the answers to your questions are really needed to get the work done that you want, assuming that I understand what you are trying to do. The details of how a syscall ends up within
vfs_syscalls.c shouldn't matter since, AFAIK, you won't be needing to change any syscalls, the number of arguments or adding any syscalls. I believe all you really need to do is to add a few fields to the struct returned by stat(2). Thus the struct stat returned will have to be larger, but I think that is the only change that you need to make, from a syscall standpoint. Then of course, all utilities that call stat(2) will have to be recompiled, and you will want to add new code in ls(1), perhaps other user commands as you have the energy, like find(1). The tricky ones will be things like dump/restore -- I haven't looked at that issue at all.
I am going mostly from memory here and would need full source to be certain and more detailed, but... the path from syscall to
vfs_syscalls.c would be something like this...
A program like ls(1) makes a stat(2) call. It is a C library routine that has its arguments pushed on the stack and then issues a trap instruction (machine dependent). The kernel's trap handler gets control and now you are in kernel space instead of user space. The trap handler determines which syscall was responsible for the trap, presuming it is legal. It is machine dependent: some CPU's encode the syscall number right in the trap instruction, others may have other mechanisms to carry that number into the kernel, like sticking the syscall number in a register.
A list of syscall numbers is in
/usr/include/sys/syscall.h . These numbers are actually an index into the table
sysent[] which has a structure defined in
/usr/include/sys/sysent.h.
This
sysent[] table also contains the function pointer to the kernel routine that is to handle the syscall. Its all in the file
init_sysent.c.
Remember that the real arguments to the syscall were pushed on the stack in user space. The kernel has to go and fetch them out of user space. IIRC, some implementations have the C library support code fashion an argument block before issuing the trap (I think as pointers immediately following the trap instruction), but in either case, the arguments still live in user space, though short arguments can be passed via the user registers.
As far as return values from the syscall, I believe the kernel sets the value of one of the registers which will be restored during the process of returning from the trap. Other values returned are implemented by having the kernel directly writing user memory, using the pointers presented as arguments to the syscall. This is what happens to return the struct stat from the stat(2) call.
Again, although educational, I don't see why you need to know the details of any of this since, to my understanding, your mods shouldn't have to change any of this. Instead look into the kernel side of stat(2) and the definition of struct stat and start by adding extra fields (
muid,
mgid) to it, set by
vn_stat() -- It looks to me that the business end of stat(2) is indeed in
vn_stat(). So that part looks pretty easy...
More later... Let's see if you can make the simple mods to struct stat and
vn_stat and have ls(1) get the new info...
(to be really explicit, add the fields
st_muid and
st_mgid to struct stat, then in
vn_stat(), set them to something like
sb->st_muid = 42; sb->st_mgid = 43; then recompile the kernel and at least
ls.c if not the world (probably safer since all programs that call stat(2) will now be broken. If you don't want to change the sizeof struct stat at this early stage (wise), it looks like there is some extra padding currently there that could be used to start with).