1 of 27

ECS 150: Operating systems

Directories

© Sam King, 2024

Based on material from Joël Porquet-Lupine

CC BY-NC-SA 4.0 International License

2 of 27

Roadmap

Today: Directory implementation

Monday: Bringing it all together: Case study with FFS

Next week we’ll talk about APIs

Following week:

  • Sam’s advice + AMA
  • Final review

3 of 27

Reads that cross disk boundaries. Copy data from two disk blocks into one buffer

buffer

pos = 5000, copy size = 4096, block size = 4096

4 of 27

Calculate which inode.direct entry to use

buffer

19

6

8

Inode.direct array

idx=1

pos = 5000, copy size = 4096, block size = 4096

idx = floor(pos / block size)

5 of 27

Read the disk block for idx=1

buffer

19

6

8

Inode.direct array

idx=1

block

disk

readDiskBlock blockNum=6

pos = 5000, copy size = 4096, block size = 4096

6 of 27

Copy the data from the disk block to the beginning of the buffer

buffer

19

6

8

Inode.direct array

idx=1

block

disk

readDiskBlock blockNum=6

4096-offset

offset

offset = pos % block size

pos = 5000, copy size = 4096, block size = 4096

7 of 27

Find the next disk block we need to read to fill in the rest of the buffer

buffer

19

6

8

Inode.direct array

idx=2

pos = 5000, copy size = 4096, block size = 4096

8 of 27

Reads the next block from disk

buffer

19

6

8

Inode.direct array

idx=2

block

disk

readDiskBlock blockNum=19

pos = 5000, copy size = 4096, block size = 4096

9 of 27

Copy the data from the beginning of the block to the end of the buffer

buffer

19

6

8

Inode.direct array

idx=2

block

disk

readDiskBlock blockNum=19

pos = 5000, copy size = 4096, block size = 4096

10 of 27

Assume a.txt fileSize == 3*4096, implement write

inodeNum = lookup(0, “a.txt”)

write(inodeNum, buffer, 1, 5000)

Assume you have an inodeTable that is an array with all of your inodes and ignore error checking

Break into groups and sketch a solution

typedef struct {

int type;

int size; // in bytes

int direct[DIRECT_PTRS];

} inode_t;

11 of 27

Sketch of the solution

// ignore error checking

int write(int inodeNum, void *buffer, int sizeInBytes=1,

int posInBytes=5000) {

// Figure out which entry in our inode.direct to lookup the disk block.

// Convert bytes to blocks and get the disk block number.

// Read the block of data from the disk

// Copy from buffer to the block

// Write the block back to disk

}

12 of 27

Writing beyond the end of the file might require allocating new disk blocks

When can you write data without allocating a new block?

13 of 27

14 of 27

Design considerations: Workload

File size and storage space

15 of 27

Design considerations: Workload

File size and storage space

Most files are small

Large files account for most of the storage

16 of 27

Design considerations: Workload

How many files does “Chrome” open if you click on it and close it right away?

17 of 27

Design considerations: Workload

18 of 27

Design considerations: Workload

File access pattern and usage

  • Most files are read/written sequentially (e.g., config files, executables)
  • Some files are read/written randomly (e.g., database files, swap files)
  • Some files have pre-defined size at creation (e.g., downloaded files)
  • Some files start small and grow over time (e.g., system logs)

19 of 27

File systems are all about data structures and algorithms

20 of 27

Data structures

Directories

  • Map filenames to file numbers (to find metadata)

File metadata (i.e., inode)

Index structure

  • Part of a file's metadata
  • Map data blocks of file

Free space map

  • Manage the list of free disk blocks
  • Allow files to grow/shrink

21 of 27

Directories

A directory is simply a file

  • List of mappings from filenames to file numbers
  • Each mapping is a directory entry <name, file number>

Only directly accessible by OS

  • Ensure integrity of mapping
  • Accessible for processes via syscalls
  • e.g., opendir()/readdir()
  • In Project 4, your ds3ls utility will need

to use LocalFileSystem::read

22 of 27

a.img from Project 4

xxd output, showing the directory entries for /a/b

23 of 27

a.img from Project 4

c.txt name and file (inode) number

24 of 27

a.img from Project 4

You can also see “.” and “..” preceding c.txt

25 of 27

Directory implementation: Linear layout

  • Array of entries, free space is at the end
  • Track number of elements using the file size
  • E.g., Project 4

.

830

..

158

music

320

work

219

foo.txt

871

free

-

free

-

free

-

Pro: Simple

Con: Linear scan to find an entry

Con: Deleting an entry will cause you to rewrite all data

26 of 27

Directory implementation: Linear layout

  • Array of entries, free space can be anywhere
  • E.g., MS-FAT

.

830

..

158

music

320

work

219

foo.txt

871

free

-1

free

-1

free

-1

Pro: Simple

Con: Linear scan to find an entry

Con: Managing data when deleting can be some work

27 of 27

Directory implementation: Trees

Tree of entries

E.g., XFS and NTFS

Pro: Fast file lookup O(log n)

Con: Complex implementation