>



File Manager



This module contains the functions that manages files.

Important Note: All functions in this module expect that the inode is locked before they are called.



Function Number Function Name Arguments Return Value
BUFFERED_WRITE = 1 Buffered Write Disk Block Number, Offset, Word NIL
BUFFERED_READ = 2 Buffered Read Disk Block Number, Offset, Memory Address NIL
OPEN = 3 Open File Name File Table Index, -1 or -2
CLOSE = 4 Close File Table Index NIL


Buffered Write

Description : The disk page provided is loaded to the corresponding buffer. The word provided is written into the offset position of the buffer.
Buffer managemnet is handled by this function internally.

    Identify the buffer ; 			
    /* Buffer Number = (Disk Number % 4) is a simple scheme, 
    good enough for our purposes. More efficient schemes are used in real systems */
    
    Acquire the buffer by calling the Acquire_Buffer() function	
    in the Resource Manager module;
    
    if (the buffer contains a different disk block){  			/* check block number in Buffer Table. */
        
        if (the buffer contents are dirty){					/* check DIRTY BIT of buffer table */
              Write back the contents of the buffer
              to the disk by invoking disk_store() 
              function in the device manager module;
        }
        
        Load the required disk block into the buffer by invoking
        the disk_load() function in the device manager module;

        Set the new Disk block number in the Buffer table entry;
    }
    
    Write the contents of the word taken as input into the offset
    location in the buffer; 
    
    Mark the buffer as Dirty;
    
    Release the buffer by calling the Release_Buffer() function
    in the Resource Manager module;
    
    return;
Called by the Write system call.

Buffered Read

Description : The disk page provided is loaded to the corresponding buffer. The word present at the offset position of the buffer is copied to the Memory address provided as input. Buffer management is handled by this function internally.

NOTE: Physical memory address must be provided.

    Identify the buffer ; 			
    /* Buffer Number = (Disk Number % 4) is a simple scheme, 
    good enough for our purposes. More efficient schemes are used in real systems */
    
    Acquire the buffer by calling the Acquire_Buffer() function
    in the Resource Manager module;
    
    if (the buffer contains a different disk block){  			/* check block number in Buffer Table. */
        
        if (the buffer contents are dirty){					/* check DIRTY BIT of buffer table */
              Write back the contents of the buffer
              to the disk by invoking disk_store() 
              function in the device manager module;
              
              Mark the buffer as clean in the 
              corresponding buffer table entry;
        }
        
        Load the required disk block into the buffer by invoking
        the disk_load() function in the device manager module;

        Set the new Disk block number in the Buffer table entry;
    }
    
    Copy the contents in the offset location in the buffer to the
    physical address given as input; 
        
    Release the buffer by calling the Release_Buffer() function
    in the Resource Manager module;
    
    return;

Called by the Read system call.


Open

Description : Locates the file in the inode table and makes an entry in the Open File Table. Returns the Open File Table index or an error code if file does not exist or the table is full. On a successfull open, the file status table entry of the file is incremented.

Note: This function must not be called unless a the calling process has a free entry available in the per-process resource table to store the open file table index returned by this function.


Find the index of the Inode Table entry of the file. If the entry is not found, return -1.

Call the acquire_inode() function in the Resource Manager module.   /* Lock the inode */
If the locking fails, return -1. 

If the file is of type EXEC, release_inode() and return -1. 	/* Only data files can be opened */

Find a free entry in the Open File Table.
If there are no free entries, release_inode() and return -2.  /* Reached maximum number of open files in the system. */

If the file name is "root" then 
	Set the INODE INDEX field in the open file table entry to INODE_ROOT. 
else
	In the File Status Table, if the File Open Count is -1, set it to 1. Otherwise, increment the File Open Count.
	Set the INODE INDEX field in the open file table entry to the inode table index of the file. 

Set the OPEN INSTANCE COUNT to 1 and LSEEK to 0 in the open file table entry.

Call the release_inode() function in the Resource Manager module.   /* Free the inode */

return the Open File Table Index.

Question: 
	1. Why don't we need to maintain file open count for the root file? We still need to maintain open instance count for the root file, why?
	2. After acquiring the inode, why do we check if the input file name matches the inode table entry?
Called by the open system call.

Close

Description : Closes the open instance of a file. Assumes a valid Open File Table index is given as input.


Find the index of the Inode Table entry of the file from the Open File Table.

In the Open File Table Entry, decrement the Open Instance Count.

If the Open Instance Count becomes 0
	Invalidate the entry by setting all fields to -1.
	If the file is not the "root", decrement the File Open Count in the File (Inode) Status Table.
	If the File Open Count in File Status Table becomes 0, set it to -1.
	/* Check the INODE_INDEX field in the Open File Table entry */

return;
Called by the close, exit system call.