2004-10-15 02:48:41

by John McCutchan

[permalink] [raw]
Subject: [RFC][PATCH] inotify 0.14

Hello,

Here is release 0.14.0 of inotify. Attached is a patch to 2.6.8.1

--New in this version--
-fix compiling without inotify (rml)
-zero out kevent structure (rml)
-setattr_mask -> setattr_mask_dnotify (rml)
-setattr_mask_inotify moved to inotify.c (rml)
-fixup setattr_mask return values (rml)
-always define wd as s32 (rml)
-fix dentry leak bug (rml)
-misc cleanups (rml,me)
-implement security when attempting to watch something (me)
-got rid of debug code (me)
-merged setattr_mask_inotify/dnotify (me)


John McCutchan

Release notes:

--Why Not dnotify and Why inotify (By Robert Love)--

Everyone seems quick to deride the blunder known as "dnotify" and
applaud a
replacement, any replacement, man anything but that current mess, but in
the
name of fairness I present my treatise on why dnotify is what one might
call
not good:

* dnotify requires the opening of one fd per each directory that you
intend to
watch.
o The file descriptor pins the directory, disallowing the backing
device to be unmounted, which absolutely wrecks havoc with removable
media.
o Watching many directories results in many open file descriptors,
possibly hitting a per-process fd limit.
* dnotify is directory-based. You only learn about changes to
directories.
Sure, a change to a file in a directory affects the directory, but you
are
then forced to keep a cache of stat structures around to compare
things in
order to find out which file.
* dnotify's interface to user-space is awful.
o dnotify uses signals to communicate with user-space.
o Specifically, dnotify uses SIGIO.
o But then you can pick a different signal! So by "signals," I really
meant you need to use real-time signals if you want to queue the
events.
* dnotify basically ignores any problems that would arise in the VFS
from hard
links.
* Rumor is that the "d" in "dnotify" does not stand for "directory" but
for
"suck."

A suitable replacement is "inotify." And now, my tract on what inotify
brings
to the table:

* inotify's interface is a device node, not SIGIO.
o You open only a single fd, to the device node. No more pinning
directories or opening a million file descriptors.
o Usage is nice: open the device, issue simple commands via ioctl(),
and then block on the device. It returns events when, well, there are
events to be returned.
o You can select() on the device node and so it integrates with main
loops like coffee mixed with vanilla milkshake.
* inotify has an event that says "the filesystem that the item you were
watching is on was unmounted" (this is particularly cool).
* inotify can watch directories or files.
* The "i" in inotify does not stand for "suck" but for "inode" -- the
logical
choice since inotify is inode-based.


--COMPLEXITY--

I have been asked what the complexity of inotify is. Inotify has
2 path codes where complexity could be an issue:

Adding a watch to a device
This code has to check if the inode is already being watched
by the device, this is O(1) since the maximum number of
devices is limited to 8.


Removing a watch from a device
This code has to do a search of all watches on the device to
find the watch descriptor that is being asked to remove.
This involves a linear search, but should not really be an issue
because it is limited to 8192 entries. If this does turn in to
a concern, I would replace the list of watches on the device
with a sorted binary tree, so that the search could be done
very quickly.

In the near future this will be based on idr, and the complexity
will be O(logn)


The calls to inotify from the VFS code has a complexity of O(1) so
inotify does not affect the speed of VFS operations.

--MEMORY USAGE--

The inotify data structures are light weight:

inotify watch is 40 bytes
inotify device is 68 bytes
inotify event is 272 bytes

So assuming a device has 8192 watches, the structures are only going
to consume 320KB of memory. With a maximum number of 8 devices allowed
to exist at a time, this is still only 2.5 MB

Each device can also have 256 events queued at a time, which sums to
68KB per device. And only .5 MB if all devices are opened and have
a full event queue.

So approximately 3 MB of memory are used in the rare case of
everything open and full.

Each inotify watch pins the inode of a directory/file in memory,
the size of an inode is different per file system but lets assume
that it is 512 byes.

So assuming the maximum number of global watches are active, this would
pin down 32 MB of inodes in the inode cache. Again not a problem
on a modern system.

On smaller systems, the maximum watches / events could be lowered
to provide a smaller foot print.

Keep in mind that this is an absolute worst case memory analysis.
In reality it will most likely cost approximately 5MB.

--HOWTO USE--
Inotify is a character device that when opened offers 2 IOCTL's.
(It actually has 4 but the other 2 are used for debugging)

INOTIFY_WATCH:
Which takes a path and event mask and returns a unique
(to the instance of the driver) integer (wd [watch descriptor]
from here on) that is a 1:1 mapping to the path passed.
What happens is inotify gets the inode (and ref's the inode)
for the path and adds a inotify_watch structure to the inodes
list of watches. If this instance of the driver is already
watching the path, the event mask will be updated and
the original wd will be returned.

INOTIFY_IGNORE:
Which takes an integer (that you got from INOTIFY_WATCH)
representing a wd that you are not interested in watching
anymore. This will:

send an IGNORE event to the device
remove the inotify_watch structure from the device and
from the inode and unref the inode.

After you are watching 1 or more paths, you can read from the fd
and get events. The events are struct inotify_event. If you are
watching a directory and something happens to a file in the directory
the event will contain the filename (just the filename not the full
path).

-- EVENTS --
IN_ACCESS - Sent when file is accessed.
IN_MODIFY - Sent when file is modified.
IN_ATTRIB - Sent when file is chmod'ed.
IN_CLOSE_WRITE - Sent when file is closed and was opened for writing.
IN_CLOSE_NOWRITE - Sent when file is closed but was not opened for
writing.
IN_CLOSE - either of the two above events.
IN_OPEN - Sent when file is opened.
IN_MOVED_FROM - Sent to the source folder of a move.
IN_MOVED_TO - Sent to the destination folder of a move.
IN_DELETE_SUBDIR - Sent when a sub directory is deleted. (When watching
parent)
IN_DELETE_FILE - Sent when a file is deleted. (When watching parent)
IN_CREATE_SUBDIR - Sent when a sub directory is created. (When watching
parent)
IN_CREATE_FILE - Sent when a file is created. (When watching parent)
IN_DELETE_SELF - Sent when file is deleted.
IN_UNMOUNT - Sent when the filesystem is being unmounted.
IN_Q_OVERFLOW - Sent when your event queue has over flowed.

The MOVED_FROM/MOVED_TO events are always sent in pairs.
MOVED_FROM/MOVED_TO
is also sent when a file is renamed. The cookie field in the event pairs
up MOVED_FROM/MOVED_TO events. These two events are not guaranteed to be
successive in the event stream. You must rely on the cookie to pair
them up. (Note, the cookie is not sent yet.)

If you aren't watching the source and destination folders in a MOVE.
You will only get MOVED_TO or MOVED_FROM. In this case, MOVED_TO
is equivelent to a CREATE and MOVED_FROM is equivelent to a DELETE.

--KERNEL CHANGES--
inotify char device driver.

Adding calls to inotify_inode_queue_event and
inotify_dentry_parent_queue_event from VFS operations.
Dnotify has the same function calls. The complexity of the VFS
operations is not affected because inotify_*_queue_event is O(1).


Adding a call to inotify_super_block_umount from
generic_shutdown_superblock

inotify_super_block_umount consists of this:
find all of the inodes that are on the super block being shut down,
sends each watch on each inode the UNMOUNT and IGNORED event
removes the watch structures from each instance of the device driver
and each inode.
unref's the inode.


Attachments:
inotify-0.14.patch (46.69 kB)

2004-10-17 23:46:39

by V13

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Friday 15 October 2004 05:44, John McCutchan wrote:
> Hello,
>
> Here is release 0.14.0 of inotify. Attached is a patch to 2.6.8.1

AFAICS this patch adds inotify and removes dnotify. I believe that the
addition of inotify to 2.6 series (if it is going to happen) should leave
dnotify intact since there may be programs that rely on it (kde for example).

<<V13>>

2004-10-17 23:51:50

by Robert Love

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Mon, 2004-10-18 at 02:46 +0300, V13 wrote:

> AFAICS this patch adds inotify and removes dnotify. I believe that the
> addition of inotify to 2.6 series (if it is going to happen) should leave
> dnotify intact since there may be programs that rely on it (kde for example).

It should make dnotify a configuration option, controlled via
CONFIG_DNOTIFY.

Robert Love


2004-10-17 23:52:39

by John McCutchan

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Sun, 2004-10-17 at 19:46, V13 wrote:
> On Friday 15 October 2004 05:44, John McCutchan wrote:
> > Hello,
> >
> > Here is release 0.14.0 of inotify. Attached is a patch to 2.6.8.1
>
> AFAICS this patch adds inotify and removes dnotify. I believe that the
> addition of inotify to 2.6 series (if it is going to happen) should leave
> dnotify intact since there may be programs that rely on it (kde for example).

This patch makes both inotify and dnotify conditional features. It does
not remove dnotify.

John

2004-10-18 01:28:26

by Stephen Rothwell

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Sun, 17 Oct 2004 19:52:09 -0400 Robert Love <[email protected]> wrote:
>
> It should make dnotify a configuration option, controlled via
> CONFIG_DNOTIFY.

But you have removed the sysctl that allows enabling and disabling of
dnotify at run time. And you create setattr_mask_dnotify for which I can
find no caller. And make gratuitous changes to the current dnotify code.
(I point this last out as it just increases the size of the patch for no
purpose.)

--
Cheers,
Stephen Rothwell [email protected]
http://www.canb.auug.org.au/~sfr/


Attachments:
(No filename) (561.00 B)
(No filename) (189.00 B)
Download all attachments

2004-10-18 01:32:43

by Stephen Rothwell

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Mon, 18 Oct 2004 11:28:07 +1000 Stephen Rothwell <[email protected]>
wrote:
>
> And you create setattr_mask_dnotify for which I can find no caller.

Similarly setattr_mask_inotify appears to have no callers (I assume it is
left over from a previous version).

--
Cheers,
Stephen Rothwell [email protected]
http://www.canb.auug.org.au/~sfr/


Attachments:
(No filename) (369.00 B)
(No filename) (189.00 B)
Download all attachments

2004-10-18 02:18:39

by John McCutchan

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Sun, 2004-10-17 at 21:32, Stephen Rothwell wrote:
> On Mon, 18 Oct 2004 11:28:07 +1000 Stephen Rothwell <[email protected]>
> wrote:
> >
> > And you create setattr_mask_dnotify for which I can find no caller.
>
> Similarly setattr_mask_inotify appears to have no callers (I assume it is
> left over from a previous version).

Yes it is. setattr_mask () computes both dnotify and inotify masks.

John

2004-10-18 02:22:08

by John McCutchan

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Sun, 2004-10-17 at 21:28, Stephen Rothwell wrote:
> On Sun, 17 Oct 2004 19:52:09 -0400 Robert Love <[email protected]> wrote:
> >
> > It should make dnotify a configuration option, controlled via
> > CONFIG_DNOTIFY.
>
> But you have removed the sysctl that allows enabling and disabling of
> dnotify at run time. And you create setattr_mask_dnotify for which I can
> find no caller. And make gratuitous changes to the current dnotify code.
> (I point this last out as it just increases the size of the patch for no
> purpose.)

There may be bugs with how dnotify was made optional. I will accept a
patch that fixes this :)

It is debatable whether or not the inotify patch should carry this
dnotify config patch as well. I don't see it being that large of a
burden on maintaining or using the patch that includes the dnotify
config changes.

John

2004-10-18 07:00:31

by Stephen Rothwell

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

Hi John,

On Sun, 17 Oct 2004 22:20:43 -0400 John McCutchan <[email protected]> wrote:
>
> It is debatable whether or not the inotify patch should carry this
> dnotify config patch as well. I don't see it being that large of a
> burden on maintaining or using the patch that includes the dnotify
> config changes.

You should probably submit the patch making dnotify optional as a
completely separate patch as it is logically s separate issue.

--
Cheers,
Stephen Rothwell [email protected]
http://www.canb.auug.org.au/~sfr/


Attachments:
(No filename) (552.00 B)
(No filename) (189.00 B)
Download all attachments

2004-10-18 16:50:05

by Robert Love

[permalink] [raw]
Subject: Re: [RFC][PATCH] inotify 0.14

On Mon, 2004-10-18 at 17:00 +1000, Stephen Rothwell wrote:

> You should probably submit the patch making dnotify optional as a
> completely separate patch as it is logically s separate issue.

I agree. I've submitted it before, I'll submit it again.

Robert Love