[PATCH] inotify: report rounded-up event size to user space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 06, 2009 at 09:42:58PM +0800, Kay Sievers wrote:
> On Mon, May 4, 2009 at 15:30, Wu Fengguang <fengguang.wu@xxxxxxxxx> wrote:
> 
> > I tried remove every udev rules in /etc/udev/ and /lib/udev, the /etc/group
> > accesses disappeared in strace, but udevd is still busy.
> 
> > ppoll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=3, events=POLLIN}], 3, NULL, [], 8) = 1 ([{fd=3, revents=POLLIN}])
> > ioctl(3, FIONREAD, [39])                = 0
> > read(3, 0x62ad60, 39)                   = -1 EINVAL (Invalid argument)
> 
> Seems, you have issues with inotify on your nfs mount?
> 
> Inotify wakes up udevd to tell something in the rules directory has
> changed, but inotify seems not to return anything useful, but keeps
> waking us up. That causes an endless loop of parsing rules files.

Thanks for the tip. The failed inotify read() is caused by the size *roundup*
behavior introduced by the -mm commit 3b46cf7d5f3ca(Reimplement inotify_user
using fsnotify).  Which says:

+               /*
+                * We need to pad the filename so as to properly align an
+                * array of inotify_event structures.  Because the structure is
+                * small and the common case is a small filename, we just round
+                * up to the next multiple of the structure's sizeof.  This is
+                * simple and safe for all architectures.
+                */

The udev madness originates from these kernel testing failures:

[  756.569243] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.600103] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.630265] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.670862] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.701845] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.732899] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.763126] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.794829] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.824985] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.856760] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  761.608521] __ratelimit: 210 callbacks suppressed

Which are printed by the following patch:

--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
 static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
 					    size_t count)
 {
 	size_t event_size = sizeof(struct inotify_event);
 	struct fsnotify_event *event;
 
 	if (fsnotify_notify_queue_is_empty(group))
 		return NULL;
 
 	event = fsnotify_peek_notify_event(group);
 
 	event_size += roundup(event->name_len, event_size);
 
-	if (event_size > count)
+	if (event_size > count) {
+		if (printk_ratelimit())
+			printk("get_one_event: event_size=%d > count=%d, name_len=%d, name=%s\n",
+					(int)event_size, (int)count, (int)event->name_len, event->file_name);
 		return ERR_PTR(-EINVAL);
+	}


It can be fixed by reporting the rounded up value to user space.

Thanks,
Fengguang
---
inotify: report rounded-up event size to user space

Fix a udev madness problem, which falls into an endless loop:

(1) ppoll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=3, events=POLLIN}], 3, NULL, [], 8) = 1 ([{fd=3, revents=POLLIN}])
(2) ioctl(3, FIONREAD, [39])                = 0
(3) read(3, 0x62ad60, 39)                   = -1 EINVAL (Invalid argument)

In (2) we reported a small len, while in (3) we insist on a rounded up len,
leading to a failed inotify read(), which will be retried endlessly by udev.

[  756.569243] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.600103] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.630265] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.670862] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.701845] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.732899] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.763126] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.794829] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.824985] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  756.856760] get_one_event: event_size=48 > count=38, name_len=22, name=61-dev-root-link.rules
[  761.608521] __ratelimit: 210 callbacks suppressed

Signed-off-by: Wu Fengguang <fengguang.wu@xxxxxxxxx>
---
 fs/notify/inotify/inotify_user.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- linux.orig/fs/notify/inotify/inotify_user.c
+++ linux/fs/notify/inotify/inotify_user.c
@@ -318,7 +318,9 @@ static long inotify_ioctl(struct file *f
 		mutex_lock(&group->notification_mutex);
 		list_for_each_entry(holder, &group->notification_list, event_list) {
 			event = holder->event;
-			send_len += sizeof(struct inotify_event) + event->name_len;
+			send_len += sizeof(struct inotify_event);
+			send_len += roundup(event->name_len,
+					sizeof(struct inotify_event));
 		}
 		mutex_unlock(&group->notification_mutex);
 		ret = put_user(send_len, (int __user *) p);
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux