Skip to content

Commit

Permalink
Add option for deny watching of subfiles for certain filesystem types
Browse files Browse the repository at this point in the history
In many cases (depending on inotify_watch_add() options) libinotify-kqueue
opens all files in watched directory that can be inappropriate on certain
filesystems like network or mtpfs due to large overhead of open() operation.
That is why skip-subfiles configure option is introduced. If this option
was enabled at configure time, libinotify-kqueue checks filesystem type on
inotify_watch_add() invocation and compares with blacklist to deceide
if it necessary to watch for subfiles or not.
That disables notifications of subfiles content or attribute modifications
but still allow to track their creation, deletion and renaming.

E.g: to prohibit of opening subfiles on NFS and MTP-fs(mounted with fuse) use

./configure --enable-skip-subfiles=fusefs,nfs
  • Loading branch information
wulf7 committed Jul 11, 2017
1 parent d99d810 commit ec36553
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
29 changes: 29 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -409,4 +409,33 @@ AS_IF([test "x$enable_native_semaphores" != "xno"], [
])


AC_ARG_ENABLE([skip-subfiles],
AS_HELP_STRING([--enable-skip-subfiles=fstype@<:@,fstype@:>@], [List of filesystem types where opening of subfiles is not performed]),
[
AC_CHECK_MEMBER([struct statfs.f_fstypename],
[
AC_DEFINE([STATFS_HAVE_F_FSTYPENAME],[1],[Define to 1 if struct statfs have f_fstypename field])
],
[
AC_CHECK_MEMBER([struct statvfs.f_fstypename],
[
AC_DEFINE([STATVFS_HAVE_F_FSTYPENAME],[1],[Define to 1 if struct statvfs have f_fstypename field])
],
[
AC_MSG_ERROR(No means for detecting filesystem type found. Remove --enable-skip-subfiles option!)
],
[
@%:@include <sys/statvfs.h>
])
],
[
@%:@include <sys/param.h>
@%:@include <sys/mount.h>
])
subfiles_fs_list=`echo "\"$enable_skip_subfiles\"" | $SED -e 's/,/", "/g'`
AC_DEFINE_UNQUOTED([SKIP_SUBFILES],[$subfiles_fs_list],[List of filesystem types where opening of subfiles is not performed])
]
)


AC_OUTPUT
57 changes: 57 additions & 0 deletions inotify-watch.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
#include "compat.h"

#include <sys/types.h>
#ifdef STATFS_HAVE_F_FSTYPENAME
#include <sys/mount.h> /* fstatfs */
#endif
#ifdef STATVFS_HAVE_F_FSTYPENAME
#include <sys/statvfs.h> /* fstatvfs */
#endif
#include <sys/stat.h> /* fstat */

#include <assert.h> /* assert */
Expand All @@ -39,6 +45,48 @@
#include "watch-set.h"
#include "watch.h"

#ifdef SKIP_SUBFILES
static const char *skip_fs_types[] = { SKIP_SUBFILES };

/**
* Check if watch descriptor belongs a filesystem
* where opening of subfiles is inwanted.
*
* @param[in] fd A file descriptor of a watched entry.
* @return 1 if watching for subfiles is unwanted, 0 otherwise.
**/
static int
iwatch_want_skip_subfiles (int fd)
{
#ifdef STATFS_HAVE_F_FSTYPENAME
struct statfs st;
#else
struct statvfs st;
#endif
size_t i;
int ret;

memset (&st, 0, sizeof (st));
#ifdef STATFS_HAVE_F_FSTYPENAME
ret = fstatfs (fd, &st);
#else
ret = fstatvfs (fd, &st);
#endif
if (ret == -1) {
perror_msg ("fstatfs failed on %d");
return 0;
}

for (i = 0; i < nitems (skip_fs_types); i++) {
if (strcmp (st.f_fstypename, skip_fs_types[i]) == 0) {
return 1;
}
}

return 0;
}
#endif

/**
* Preform minimal initialization required for opening watch descriptor
*
Expand Down Expand Up @@ -117,6 +165,9 @@ iwatch_init (worker *wrk, int fd, uint32_t flags)
closedir (dir);
#else
iw->dir = dir;
#endif
#ifdef SKIP_SUBFILES
iw->skip_subfiles = iwatch_want_skip_subfiles (fd);
#endif
}

Expand Down Expand Up @@ -183,6 +234,12 @@ iwatch_add_subwatch (i_watch *iw, dep_item *di)
return NULL;
}

#ifdef SKIP_SUBFILES
if (iw->skip_subfiles) {
goto lstat;
}
#endif

watch *w = watch_set_find (&iw->watches, di->inode);
if (w != NULL) {
di->type = w->flags & S_IFMT;
Expand Down
3 changes: 3 additions & 0 deletions inotify-watch.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ struct i_watch {
#endif
worker *wrk; /* pointer to a parent worker structure */
int is_closed; /* inotify watch is stopped but not freed yet */
#ifdef SKIP_SUBFILES
int skip_subfiles; /* Fs is not safe to start subwatches */
#endif
uint32_t flags; /* flags in the inotify format */
ino_t inode; /* inode number of watched inode */
dev_t dev; /* device number of watched inode */
Expand Down

0 comments on commit ec36553

Please sign in to comment.