inotify 0.23 errno 28 (ENOSPC)

From: Bryan Wilkerson
Date: Tue May 24 2005 - 11:54:04 EST


Hi,

I read an earlier thread where you said that it was
possible to manually walk a tree and add all
directories to an inotify watch descriptor. I wrote
some code to do this and the ioctl call fails on my
machine after adding 9,977 directories with ENOSPC.

I've attached a small repro case. Just point it at
the base of a large dir tree (e.g. inotify-r ~) to
use.

My kernel is 2.6.12-rc3 with the inotify 0.23 patch.
Let me know if you need more information.

Please cc my e-mail addr in all replies.

Thanks,

-bryan
/* this just demonstrates adding a large number of directories
to inotify
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <dirent.h>


#include "inotify.h"

int dirsWatched = 0;
int fd;

static void fatal_error(char *fmt, ...) __attribute__((noreturn));
static void fatal_error(char *fmt, ...)
{
fprintf(stderr, "\n\nFATAL ERROR:%d:%s: ", errno, strerror(errno));
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n\nDirs successfully added to watch: %d\n", dirsWatched);
exit(errno);
}


int add_dir(const char *path)
{
struct inotify_watch_request iwr;
iwr.mask = 0xffffffff;
iwr.fd = open(path, O_RDONLY);
if( iwr.fd <= 0 )
fatal_error("Unable to open directory %s for reading", path);

int wd = ioctl(fd, INOTIFY_WATCH, &iwr);
close(iwr.fd);

if (wd < 0)
fatal_error("Unable to create inotify watch on object: %s", path);
else
dirsWatched++;

struct dirent **namelist;
int i, n;
struct stat statstruct;

n = scandir(path, &namelist, 0, alphasort);
if( n < 0 )
fatal_error("scandir failed");

for( i = 0; i < n; i++ )
{
char fileName[4096];
int len = sprintf(fileName, "%s/%s", path, namelist[i]->d_name);

if( !(strcmp(&fileName[len-2], "/.")==0 || strcmp(&fileName[len-3], "/..")==0) )
{
// most likely cause of not being able to stat is
// permissions which we quietly ignore and assume
// to be benign
if( stat(fileName, &statstruct) == 0 )
{
if( S_ISDIR(statstruct.st_mode) )
{
// recursive add
add_dir(fileName);
}
}
}
free(namelist[i]);
}
free(namelist);
}

int main(int argc, char **argv)
{
if( argc < 2 || strcmp(argv[1], "--help") == 0 )
{
printf( "inotify-r - tests adding a directory recusively to an inotify descriptor\n"
"\n"
"Usage: inotify-r <path>\n");
exit(1);
}
fd = open("/dev/inotify", O_RDONLY);
if (fd < 0)
fatal_error("Unable to open inotify device.");

add_dir(argv[1]);
return 0;
}