Inotify

File system Event Notification

John McCutchan

July 2005

Inotify

Designed as a replacement for dnotify

Dnotify requires opening one fd per watched directory

Dnotify can only watch directories

Dnotify uses signals for event delivery

Inotify

Inotify overcomes those problems

Requires only 1 open fd

Notifies you when a watched path is unmounted

Can watch directories and files

Delivers events over read(2)

Can use select/poll to integrate into a main loop.

Inotify

Inotify has a large event vocabulary, and provides usefull information including:

Name of sub file/dir

Is the event about a directory

Inotify

Events that files can receive:

Deleted

Accessed

Modified

Opened

Closed Writable

Closed Non-Writable

Metadata changed

Inotify

Events that directories can receive:

Sub file was moved from

Sub file was moved to

Sub file was deleted

Sub file was created

Sub file was modified

Sub file was accessed

Sub file was opened

Sub file was closed

Sub file attributes changed

Events will include sub file name and a flag telling you

if that sub file was a directory.

Inotify

Special events:

Unmount

Queue Overflow

Special Watch Flags:

One Shot

Inotify

Inotify concepts:

Inotify instance:

Event queue

Watches

Inotify watch:

Watch descriptor

Inotify

Inotify configurables:

/proc/sys/fs/inotify:

max_queued_events [default = 8192]

max_user_instances [default = 128]

max_user_watches [default = 8192]

Inotify

Using inotify:

Open inotify instance

Add watches

Read events

Cleanup

Inotify

Opening an inotify instance:

int ii_fd = inotify_init ();

if (ii_fd < 0)

error

This will fail if user has too many open

inotify instances

Inotify

Adding Watches:

int wd = inotify_add_watch (ii_fd, path, mask);

if (wd < 0)

error

This will fail if user has too many watches

Removing watches:

if (inotify_rm_watch (ii_fd, wd) < 0)

error

This will fail if wd is invalid

Inotify

Reading events:

u8 buffer[LARGE];

size r;

r = read (ii_fd, &buffer[0], LARGE);

if (r < 0)

error

READ EVENTS IN LARGE CHUNKS!

size queue_size;

ioctl(ii_fd, FIONREAD, &queue_size);

Inotify

The event structure:

struct inotify_event {

s32 wd;

u32 mask;

u32 cookie;

u32 len;

char name[0];

}

Inotify

Parsing the event buffer:

size buffer_i = 0;

size event_size = 0;

while (buffer_i < r) {

struct inotify_event *event = &buffer[buffer_i];

event_size = sizeof (struct inotify_event) + event->len;

// do something with event

buffer_i += event_size;

}

Inotify

Cleanup:

close (ii_fd);

Inotify

Properly handling move events

Event cookie ties FROM and TO events

No guarantee that you will get both events

FROM always comes before TO

Inotify

Properly handling move events

if (event.mask & MOVED_TO)

if (moved_table.find (event.cookie)

// have a pair of MOVED_FROM & MOVED_TO

else

// treat MOVED_TO as CREATE

if (event.mask & MOVED_FROM)

moved_table.insert (event.cookie, event, time);

foreach move in moved_table {

if (move.time + MAX_TIME >= time)

moved_table.remove (move);

}

MAX_TIME = 512 ms

Inotify

Recursively watching:

recursive_watch (path) {

wd = inotify_add_watch ()

wd.handler += recursive_event_handler;

foreach dir in path {

recursive_watch (dir);

}

}

recursive_event_handler (event) {

if (!(event.mask & IN_ISDIR))

return;

path = event.path + event.name;

recursive_watch (path);

}

Inotify

Who's using it?

Beagle

Gamin

Muine

Samba soon

Who's shipping it?

Linus

Ubuntu

Gentoo

Novell

Inotify

Questions & Answers

2005-07-16T13:57:19