You are on page 1of 18

Operating

Systems Project Report

Table of Contents
Introduction 0
About 1
Working 2
File System Calls 3
Testing 4
User Interface 5
Installation 6
Conclusion 7

2
Operating Systems Project Report

Kushan Joshi 201301189

Shubham Chaturvedi 201301227

Introduction
A file system is the methods and data structures that an operating system uses to keep track
of files on a disk partition, that is , the way files are organized on the disk. Without a file
system , information placed in a storage area would be one large body data with no way to
tell where information stops and where the next piece of information begins. By separating
the information into individual pieces and giving each piece a name , the information is easily
separated identified.

There are different types of file systems ,each one having different structure , logic and
properties. Some of the famous systems are FAT , NTFS , ext2 and ext3.

File system layout and inodes.


File systems are located on disks and most disks are divided into one or more partitions.
Each partition starts with a superblock which contains all the key parameters about the file
system and is read into memory when the computer is booted. Next is the information about
the free blocks in the system which is followed by inodes.

An inode is a data structure in UNIX like operating systems which contains all the
information about a file. Each file is associated with an inode , an inode is of fixed size and
contains information about the file starting with the file attributes followed by disk address
information. The first 10 addresses are stored in the inode itself, if the file has more than 10
address allocations. For larger files, one of the address in the address field is to a block
called single indirect block. Similarly, in some cases a single indirect block may refer to a
block called a double indirect block which in turn refers to a triple indirect block when
needed.

Introduction 3
Operating Systems Project Report

Introduction 4
Operating Systems Project Report

UNIX v7 File System


The early versions of Linux had a very sophisticated multi-user file system. The file system is
in a form of a tree starting at the root directory, the file names contain only ASCII characters
(except /). A UNIX directory entry contains one entry for each file in that directory. Each entry
is extremely simple as the concept of inodes is used. A directory entry contains two fields -
the file name(14 bytes) and the inode number for that file(2 bytes). The inode contains 3
attributes , the file name , date created and last modified. Each inode's size is 64bytes.

Project Description
With this project we aim to model a file system based on the UNIX v7 file system and
implement system calls - create() , delete() , open() , close() , read() and rename(). on a
hierarchical file system.

The disk structure contains segments for superblock , inode , root directory and the
corresponding data. The inode data has an upper limit of 4096 bytes divided into chunks of
1024 bytes. Since in UNIX v7 , each inode size is 64bytes, there will be total 16 inode
addresses and total of 64 inodes(16*4).

About 5
Operating Systems Project Report

Working
We have written the code for the file system in JavaScript using node.js library. The following
is the description of a few parameters in our code along followed by a few snippets.

NO_NODE_REFS -
This indicates the total number of inode references, in UNIX v7, the default value is 8.

INODE_ARRAY_SIZE -
This indicates the size of the inode array. It's deault value is 4096 bytes.

SINGLE_INDIRECT_ENTRIES-
The size of the single indirect reference nodes. We have set it to be 512.

FILE_DATA-
This indicates the maximum size of a file possible.

Inside the inode.js file , we have created various functions for our inodes. These are -

Get Index

getIndex(i) {
return this.refs[i];
}

This function retuns the index of the inode.

addRef

Working 6
Operating Systems Project Report

addRef(ptr) {
if (this.length === this.NO_INODE_REFS - 1) { // should be 8
this.refs[this.length] = new SingleIndirect(this.params);
this.refs[this.length].addRef(ptr);
this.length = this.length + 1;
return;
}
if (this.length === this.NO_INODE_REFS) {
this.refs[this.length-1].addRef(ptr);
return;
}
this.refs[this.length++] = ptr;
return;
}

This function addds references to the inodes.

removeAllRefs

removeAllRefs = () => {
this.refs = new Array(this.NO_INODE_REFS);
this.length = 0;
}

This function removes all the references in an inode.

removeRef

removeRef() {
if (this.length === 0) {
return null;
}
if (this.length === this.NO_INODE_REFS) {
const isRemovedFromSIN = this.refs[this.length - 1].removeRef();
if (!isRemovedFromSIN) {
this.length = this.length - 1;
this.refs[this.length] = undefined;
}
return null;
}
this.length = this.length - 1;
this.refs[this.length] = undefined;
return null;
}

This function remoes the last reference from the inode.

Working 7
Operating Systems Project Report

getAllRefs

getAllRefs() {
if (this.length === this.NO_INODE_REFS) {
return this.refs.slice(0, this.length - 1).concat(this.refs[this.length - 1].getAllRefs());
}
return this.refs.slice(0, this.length);
}

This function returns all the references for an inode.

Working 8
Operating Systems Project Report

File System Calls Implemeted


We have implemented various file system calls in our filesystem, these are :

1. Create File
This function is called every time the user wants to create a file and correspondingly an new
file is created.

createFile(data) {
let dataLeft = data;
const inode = this.addInode([0, 'Yesterday', 'Monday']);
let flag = true;
while (flag) {
const freeBlock = this.getFreeBlock();
dataLeft = this.disk[freeBlock].insert(dataLeft);
inode.addRef(freeBlock);
if (!dataLeft) {
flag = false;
}
}
return inode;
}

2. Edit File
This function is called to edit a previously created file.

editFile = (iNode, data) => {


this.releaseAllRefs(iNode);
const inode = this.disk[this.iNtoD(iNode)];
inode.removeAllRefs();
let flag = true;
let dataLeft = data;
while (flag) {
const freeBlock = this.getFreeBlock();
dataLeft = this.disk[freeBlock].insert(dataLeft);
inode.addRef(freeBlock);
if (!dataLeft) {
flag = false;
}
}
}

File System Calls 9


Operating Systems Project Report

3. Read File
This function is called when a user wants to read an existing file on the disk.

readFile(inode) {
return this.disk[this.iNtoD(inode)].getAllRefs().map((e) => {
return this.disk[e].data;
}).join('');
}

4. Delete File
This function is called to delete an existing file on the disk.

deleteFile(inode) {
this.disk[1+inode] = null;
}
}

5. Make Directory
This function is used to create a new directory.

mkdir(name) {
const dirStruct = [name];
let dataLeft = JSON.stringify(dirStruct);
createFile(data)
const inode = this.addInode([0, 'Yesterday', 'Monday']);
let flag = true;
while (flag) {
const freeBlock = this.getFreeBlock();
dataLeft = this.disk[freeBlock].insert(dataLeft);
inode.addRef(freeBlock);
if (!dataLeft) {
flag = false;
}
}
}

File System Calls 10


Operating Systems Project Report

Testing
In order to test our system we created a few test cases and ran them using mochaJs - a test
framework for java script. For testing ,we defined a few local parameters which are listed
below.

const gParams = {
NO_INODE_REFS: 2,
INODE_ARRAY_SIZE: 10,
BLOCK_SIZE: 2,
SINGE_INDIRECT_ENTRIES: 512,
FILE_DATA: 50,
};

function getDataIndex(params, i) {
return 2 + params.INODE_ARRAY_SIZE + i;
}

Below are the test cases which we ran on termial , all the test cases given passed and the
actual output was same as the expected output.

it('should have block 0 as null', () => {


const fs = new FS(gParams);
expect(fs.disk[0]).to.equal(null);
});

This test case was to check whether the block 0 of the default parameters is null.

it('should have block 1 as super block', () => {


const fs = new FS(gParams);
expect(fs.disk[1].diskBlocks).to.equal(0);
expect(fs.disk[1].inodes).to.equal(2);
});

This cheks if the block 1 has been set as a superblock or not

Testing 11
Operating Systems Project Report

it('should have block 2 as n1 which should be null', () => {


const fs = new FS(gParams);
expect(fs.disk[2]).to.equal(null);
});

The above test case is to check whether the first inode has been set as null or not.

it('should have block 3 as n2 which should be root inode', () => {


const fs = new FS(gParams);
expect(fs.disk[3].index).to.equal(2);
});

This test case checks if the second inode has been set for the root file or not.

it('should find disk index 4 if I delete n3', () => {


const fs = new FS(gParams);
fs.createFile('whahsikfalkjdfljkasnfkladsnlfjkadhslkjfkldasjfwhahsikfalkjdfljkasnfkladsnlfjkadhsl
fs.deleteFile(3, null);
expect(fs.findFreeInodeIndex()).to.equal(4);
});

it('should increase diskblock count on creating a file', () => {


const fs = new FS(gParams);
fs.createFile('Kushan joshi');
expect(fs.disk[1].diskBlocks).to.be.above(0);
});

This test case check if the number of diskblocks increase on creating a new file or not.

Testing 12
Operating Systems Project Report

it('should fill up all the blocks', () => {


const fs = new FS(gParams);
fs.createFile('Shub');
fs.createFile('Kushan');
fs.createFile('Sahil')
// console.log(fs.disk[2+gParams.INODE_ARRAY_SIZE]);
expect(fs.disk[getDataIndex(gParams,5)].data).to.equal('Sa');
});

The above test case checks if after creating 3 files, the equivalent number of blocks are filled
or not.

it('test editing', () => {


const params = {
NO_INODE_REFS: 8,
INODE_ARRAY_SIZE: 6,
BLOCK_SIZE: 3,
SINGE_INDIRECT_ENTRIES: 512,
FILE_DATA: 6,
};
const fs = new FS(params);
fs.createFile('kushan');
expect(fs.disk[getDataIndex(params, 0)].data).to.equal('kus');

fs.createFile('shubham');
expect(fs.disk[getDataIndex(params, 2)].data).to.equal('shu');

fs.createFile('sha');
expect(fs.disk[getDataIndex(params, 5)].data).to.equal('sha');
fs.editFile(4, 'khu');
expect(fs.disk[getDataIndex(params, 2)].data).to.equal('khu');
fs.editFile(3, 'ku');
fs.createFile('muchhala');
expect(fs.disk[getDataIndex(params, 0)].data).to.equal('hha');
expect(fs.readFile(3)).to.equal('ku');
expect(fs.readFile(4)).to.equal('khu');
expect(fs.readFile(5)).to.equal('sha');
expect(fs.readFile(6)).to.equal('muchhala');
});

In the above test case, we create 3 files , edit them and finally check in which block each
edited file was saved.

Testing 13
Operating Systems Project Report

it('first free index',()=> {


const newParams={
NO_INODE_REFS : 3,
INODE_ARRAY_SIZE: 6,
BLOCK_SIZE: 2,
SINGE_INDIRECT_ENTRIES: 512,
FILE_DATA: 20,
};
const fs = new FS(newParams);
var inode = fs.createFile('Shubham');
// console.log(fs.disk[inode.refs[1]]);

expect(fs.disk[inode.refs[0]].data).to.equal('sh');
expect(fs.disk[inode.refs[1]].data).to.equal('ub');
expect(fs.disk[inode.refs[2].refs[0]].data).to.equal('ha');
expect(fs.disk[inode.refs[2].refs[1]].data).to.equal('m');
});

In the above test case , the inode array size was reduced to 6, this test case verified the ues
of first indirect in our system.

Testing 14
Operating Systems Project Report

User Interface
As stated in our project proposal, we have incorporated a user interface in our file system
which runs on javascript and can be opened in any browser.

The following are the commands which are implemented

touch
This command can be used to create a new file. example -

$ touch shubham.txt
$ touch kushan.txt

This will create files named shubham.txt and kushan.txt respectively.

cat
This command displays all the data inside the file.

$ cat shubham.txt

rm
This command will be used to remove a file.

$ rm shubham.txt

write
This command will be used to write data to a file

$ write kushan.txt "Hello there"

User Interface 15
Operating Systems Project Report

ls
This lists all the existing files

$ ls

mkdir
This is used to create a new directory.

$ mkdir kushan

This will create a directory named kushan

cd
This command is used to go to a particular directory.

$ cd kushan

This will take you to the directory kushan

cd ..
This command will take you to the previous directory.

User Interface 16
Operating Systems Project Report

Installation
In order to run this project, you need to be on a linux machine with git and npm installed.

Follow the following steps to run out program

1. Clone the following project from github

git clone https://github.com/kepta/os_fs_project.git

2. Once the repository has been cloned, open the directory using

cd os_fs_project

3. Once inside the directory, install npm

sudo install npm

4.After npm has been installed, just run the program

npm start

Just go to your browser and open http://localhost:8080/

Now you can scroll down and can interact with the file system using the command line.

Installation 17
Operating Systems Project Report

Conclusion
In this project we have implemented a simple UI based file system using java script which
can be opened in any browser. We have modeled our file system based on UNIX v7 file
system which uses inodes.

A further improvement in this project can be incorporation of more system calls and
increasing the disk space which was assumed to be 16 MB.

Conclusion 18

You might also like