Kernel Korner - Intro to inotify

Applications that watch thousands of files for changes, or that need to know when a storage device gets disconnected, need a clean, fast solution to the file change notification problem. Here it is.
But I Don't Want to Read!

Having to sit blocked on a read() system call does not sound very appealing, unless your application is heavily threaded—in which case, hey, just one more thread! Thankfully, the inotify file descriptor can be polled or selected on, allowing inotify to be multiplexed along with other I/O and optionally integrated into an application's mainloop.

Here is an example of monitoring the inotify file descriptor with select():


struct timeval time;
fd_set rfds;
int ret;

/* timeout after five seconds */
time.tv_sec = 5;
time.tv_usec = 0;

/* zero-out the fd_set */
FD_ZERO (&rfds);

/*
 * add the inotify fd to the fd_set -- of course,
 * your application will probably want to add
 * other file descriptors here, too
 */
FD_SET (fd, &rfds);

ret = select (fd + 1, &rfds, NULL, NULL, &time);
if (ret < 0)
        perror ("select");
else if (!ret)
        /* timed out! */
else if (FD_ISSET (fd, &rfds)
        /* inotify events are available! */

You can follow a similar approach with pselect(), poll() or epoll()—take your pick.

Events

The mask field in the inotify_event structure describes the event that occurred. In addition to the events listed earlier, Table 3 shows events that are also sent, as applicable.

Table 3. Events That Cover General Changes

NameDescription
IN_UNMOUNTThe backing filesystem was unmounted.
IN_Q_OVERFLOWThe inotify queue overflowed.
IN_IGNOREDThe watch was automatically removed, because the file was deleted or its filesystem was unmounted.

Additionally, the bit IN_ISDIR is set telling the application if the event occurred against a directory. This is more than just a convenience—consider the case of a deleted file.

Because flags such as IN_ISDIR are present in the bitmask, it never should be compared to a possible event directly. Instead, the bits should be tested individually. For example:


if (event->mask & IN_DELETE) {
        if (event->mask & IN_ISDIR)
                printf ("Directory deleted!\n");
        else
                printf ("File deleted!\n");
}

Modifying Watches

A watch is modified by calling inotify_add_watch() with an updated event mask. If the watch already exists, the mask is simply updated and the original watch descriptor is returned.

Removing Watches

Watches are removed with the inotify_rm_watch() system call:

int inotify_rm_watch (int fd, int wd);

A call to inotify_rm_watch() removes the watch associated with the watch descriptor wd from the inotify instance associated with the file descriptor fd. The call returns zero on success and negative one on failure, in which case errno is set as appropriate.

Usage, as usual, is simple:


int ret;

ret = inotify_rm_watch (fd, wd);
if (ret)
        perror ("inotify_rm_watch");

Shutting inotify Down

To destroy any existing watches, pending events and the inotify instance itself, invoke the close() system call on the inotify instance's file descriptor. For example:


int ret;

ret = close (fd);
if (ret)
        perror ("close");

One-Shot Support

If the IN_ONESHOT value is OR'ed into the event mask at watch addition, the watch is atomically removed during generation of the first event. Subsequent events will not be generated against the file until the watch is added back. This behavior is desired by some applications, for example, Samba, where one-shot support mimics the behavior of the file change notification system on Microsoft Windows.

Usage is, naturally, simple:


int wd;

wd = inotify_add_watch (fd,
                "/home/rlove/Desktop",
                IN_MODIFY | IN_ONESHOT);

if (wd < 0)
        perror ("inotify_add_watch");

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

support on 64-bit machines

vishalj's picture

Do i need to make some changes to get it working on 64 bit machines .

read() length, alignment

Anonymous's picture

fyi, something that wasn't clear in the article is the requirements on the read() call.

I was playing with inotify, and I tried to call read an event in 2 parts:
struct inotify_event evt_hdr;
ssize_t nr = read(fd, &evt_hdr, sizeof(evt_hdr));

read() returned EINVAL
( at least on 2.6.23.17-88.fc7 )

When I restructured the code to read the entire event,
(similar to the article example) it works.

It would seem also that the read buffer must have proper alignment for a
struct inotify_event as well, so just declaring a char buffer on the stack
for the read() destination isn't necessarily going to work, either.

otherwise, nice article, nice feature!
Thanks

Inotify does not work

Inotify user's picture

I have registered Inotify to a file for listening IN_MODIFY | IN_DELETE | IN_DELETE_SELF. But it does not work when I fwrite() to the file. This doest not happen always.

Seems to be a bug in iNotify

changes

Anonymous's picture

Seems changes are coming, not primary in inotify and the old dnotify, but in the whole system of fs/notify.
After a long search I think there is a guy called Eric Paris (RedHat) that is currently in charge of notify structures in kernel.
He is actively commiting to the kernel git repository, which can be followed always at http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git.

As Eric Paris claims he is preparing the whole thing for upcoming "fanotify" system, which will be more powerfull, sending the possibility to decide which file accessse should be granted to the userspace (if I got right the idea).

http://lwn.net/Articles/311350/
http://lwn.net/Articles/339253/

Which is of course fantastic, but for many cases we dont need this power, and the inotify does the job at right level. I just needed a little add-on to provide the uid in inotify_event, but now it seems we will have to wait for the fanotify to be introduced first, and after to be decided the future of inotify ...

Inotify

aveugle's picture

Is there any possibility to obtain the uid of the trigger for certain inotify_event?

P.S. in general - is inotify a living project or it is shut-down?

how to check for status of the inotify

Anonymous's picture

i have a problem and hope i get a response from you.
i have a script that will create an sql file to the watch directory of my inotify. upon detection, my C program then executes the sql statment using OCI functions. is there any way i can throw back the result/status to my script if the execution was successful or not?

i have a problem and hope i

Anonymous's picture

i have a problem and hope i get a response from you.

currently, my C program with the inotify is already running. this C program will wait base on its watch directory.

i then have a script that will create an sql file to the watch directory of my inotify. upon detection, my C program then executes the sql statment using OCI functions. is there any way i can throw back the result/status to my script if the execution was successful or not?

*** note: my script did not call my C program which is already running from the start

Not able to notify changes apart from /tmp

Anonymous's picture

Hi,

I am facing some different behaviour using inotify for notifying file changes.

I added file notification for some file in /tmp directory with IN_MODIFY flag.
when i modified contents in this file, i am able to read the notifications of this change and the mask value for this notification is IN_MODIFY(2).

If i use same file with same source code in other directory(ex : /home), iam getting mask value as IN_IGNORED flag(3276. After this any modifications to the file, i am not getting any notifications.

This is some strange behaviour.

Kernel : 2.6.15-1.2054_FC5

Thank you for this, it was

Anonymous's picture

Thank you for this, it was very useful.

One annoyance for someone coming across this: while I created the inotify using
IN_MODIFY | IN_CREATE | IN_DELETE

When the file was deleted, it returned only IN_IGNORED (because the file was deleted, the inotify was removed), not IN_DELETED

inotify for /proc

madhav's picture

Hi,
There is a problem in my application. I am trying to monitor /proc for process creation/deletion, but i am not able to monitor the /proc directory in particular. The inotify will monitor all the sub directories in the /proc and other directories, but not in /proc, i.e. for process creation/deletion. i am using linux kernel-2.6.20-hardened. There was a bug previously reported in v2.6.16 regarding this issue, but i think it is fixed in further versions. if not please may i know so i will be able to patch it myself.
Please help..
Waiting for the reply

How to install inotify

Anonymous's picture

Hi..
can u pls send me the full procedure to download as wel as how to install inotify... it s very userful for me ...

Thanks

Refer this on how to install

AG's picture

Refer this on how to install and how to use for various scenarios. http://inotify.aiken.cz/?section=inotify&page=faq&lang=en

Monitoring whole directory tree

Anonymous's picture

Can you please help me?
I want to monitor the whole directory tree, using inotify.
I have done monitoring directory which notify me changes in file within that perticular directory, creation of directories into it, butI am unable to get the changes done within its subdirectories.
Please help me for this.

How would one get the user associated with an event.....

rdifalco's picture

If I wanted to write a utility that would list each time a file I was interested in was modified and by who, how would I do that? Could I do that with inotify? I'm guessing no.

INOTIFY a very helpful tool

Ioan PREDESCU's picture

I tested INOTIFY in conjunction with POSIX queues (mq_open…) on my CentOS 4.3 – 2.6.18 and it seems to work OK, I am really impressed by this ‘new’ feature:

Just a small ‘observation’ as the code piece from below is going to drastically decrease the performances (stack is exhausted as ‘event’ is an in loop declaration) :-)) :

while (i < len) {
struct inotify_event *event;
…………………

Thanks to INOTIFY creators and contributors,
John

you're flat out wrong about the stack exhausted <EOM>

Anonymous's picture

Code Feedback from gcc and a.out

Anonymous's picture

Thanks for posting this information and the examples. Was very stuck trying to convert to inotify without this article, and now have a working program thanks to your help. Feedback on this article accumulated from the process:

  • Unbalanced parenthesis in the #define for BUF_LEN
  • In that same code snippet, the while loop is conditional, based on (!len). That loop needs to be invoked when len is true and non-negative. As originally posted, the loop isn't invoked when an event is received from the read().
  • IN_CREATE is missing from Table 1, although it is referenced earlier in the article.

Thanks! inotify ROCKS!

wrong /proc path

Anonymous's picture

As of 2.6.17, it is NOT

/proc/sys/filesystem/inotify/max_user_watches

but

/proc/sys/fs/inotify/max_user_watches

Nice and helpful article

Manoj Awasthi's picture

Thanks for the same.

Special files

Alberto's picture

Hello!

Is inotify supposed to work on special files in /sys ?

I tried monitoring normal files and it works great, but when i try to monitor files on sysfs, strace shows that the executable is blocked on the read() call.

Thanks!
Alberto

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState