From fla_2@hotmail.com Fri Aug 1 21:27:48 2003 Received: with ECARTIS (v1.0.0; list fam); Fri, 01 Aug 2003 21:27:56 -0700 (PDT) Received: from hotmail.com (sea2-f59.sea2.hotmail.com [207.68.165.59]) by oss.sgi.com (8.12.9/8.12.9) with SMTP id h724RlFl007476 for ; Fri, 1 Aug 2003 21:27:48 -0700 Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC; Fri, 1 Aug 2003 21:27:42 -0700 Received: from 207.35.253.219 by sea2fd.sea2.hotmail.msn.com with HTTP; Sat, 02 Aug 2003 04:27:41 GMT X-Originating-IP: [207.35.253.219] X-Originating-Email: [fla_2@hotmail.com] From: "Francois L'Archeveque" To: fam@oss.sgi.com Subject: xtab verification bug report and fix Date: Sat, 02 Aug 2003 04:27:41 +0000 Mime-Version: 1.0 Content-Type: text/plain; format=flowed Message-ID: X-OriginalArrivalTime: 02 Aug 2003 04:27:42.0259 (UTC) FILETIME=[6A023830:01C358AE] X-archive-position: 143 X-ecartis-version: Ecartis v1.0.0 Sender: fam-bounce@oss.sgi.com Errors-to: fam-bounce@oss.sgi.com X-original-sender: fla_2@hotmail.com Precedence: bulk X-list: fam Hello, There is a bug in fam's xtab verification. Requests may be denied to hosts that actually have mounted the exported filesystem in question. This was detected with the fam included with IRIX 6.5.16f, 6.5.19f and with fam-2.6.10 which was compiled from the latest release source code. file: fam/Interest.c++ method: void Interest::verify_exported_to_host() The static data returned by gethostbyaddr and pointed to by *hent gets overwritten by the later call to gethostbyname so during the next iteration through the loop, the *hent dereferencing gives unpredictable results. This is solved by using the reentrant gethostbyname_r in the place of gethostbyname. Below are the actual differences in the code that fixed the problem. I hope that this or a similar fix can be included into a release version soon as the workaround of setting xtab_verification = false in the config file bypasses an important security feature. Thanks, fla. -- Francois L'Archeveque >diff Interest.c++ Interest.c++.keep 409,417c409 < < // use the reentrant version of gethostbyname to avoid overwriting < // the static data returned by gethostbyaddr above. < hostent client_hostent; < static char hostent_buf[2048]; < int client_error = 0; < < hostent *chent = gethostbyname_r(cs, &client_hostent, hostent_buf, < sizeof(hostent_buf), &client_error); --- > hostent *chent = gethostbyname(cs); _________________________________________________________________ Protect your PC - get McAfee.com VirusScan Online http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963 From alexl@redhat.com Tue Aug 5 04:00:22 2003 Received: with ECARTIS (v1.0.0; list fam); Tue, 05 Aug 2003 04:00:31 -0700 (PDT) Received: from devserv.devel.redhat.com (pix-525-pool.redhat.com [66.187.233.200]) by oss.sgi.com (8.12.9/8.12.9) with SMTP id h75B0KFl025469 for ; Tue, 5 Aug 2003 04:00:21 -0700 Received: from localhost (sebastian-int.corp.redhat.com [172.16.52.221]) by devserv.devel.redhat.com (8.11.6/8.11.0) with ESMTP id h75B0FS10932 for ; Tue, 5 Aug 2003 07:00:17 -0400 Subject: new dnotify patch From: Alexander Larsson To: "fam@oss.sgi.com" Content-Type: multipart/mixed; boundary="=-CWaXFqTgxZEYjFWtsUXH" Message-Id: <1060081211.2257.24.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.3.92 (Preview Release) Date: 05 Aug 2003 13:00:11 +0200 X-archive-position: 144 X-ecartis-version: Ecartis v1.0.0 Sender: fam-bounce@oss.sgi.com Errors-to: fam-bounce@oss.sgi.com X-original-sender: alexl@redhat.com Precedence: bulk X-list: fam --=-CWaXFqTgxZEYjFWtsUXH Content-Type: text/plain Content-Transfer-Encoding: 7bit Here is a new version of the dnotify patch. This one fixes a performance problem described in: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=99364 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Alexander Larsson Red Hat, Inc alexl@redhat.com alla@lysator.liu.se He's an underprivileged day-dreaming shaman in drag. She's a chain-smoking wisecracking stripper living homeless in New York's sewers. They fight crime! --=-CWaXFqTgxZEYjFWtsUXH Content-Disposition: attachment; filename=fam-2.6.8-dnotify2.patch Content-Type: text/x-patch; name=fam-2.6.8-dnotify2.patch; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit --- fam-2.6.7/acconfig.h.dnotify Tue Dec 18 02:03:36 2001 +++ fam-2.6.7/acconfig.h Sun Apr 7 18:57:41 2002 @@ -17,6 +17,9 @@ /* Define if the system has imon and IMONIOC_ ioctl flags. */ #undef HAVE_IMON +/* Define if the system has the dnotify fcntl and it's gonna be used. */ +#undef USE_DNOTIFY + /* Define if the system has the struct revokdi and the IMONIOC_REVOKDI ** ioctl flag. (IRIX 5.3 doesn't.) */ --- fam-2.6.7/configure.in.dnotify Thu Dec 20 23:18:48 2001 +++ fam-2.6.7/configure.in Sun Apr 7 18:57:41 2002 @@ -96,6 +99,24 @@ dnl AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h syslog.h unistd.h) dnl +dnl Test for the linux dnotify fcntl +dnl +AC_MSG_CHECKING([for dnotify fcntl support]) +fam_save_cppflags="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" +AC_TRY_COMPILE([ +#define _GNU_SOURCE +#include +#include +], +[ int fd = 1; + fcntl (fd, F_NOTIFY, (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)|DN_MULTISHOT); +], have_dnotify=yes, have_dnotify=no) +use_dnotify=false +CPPFLAGS="$pango_save_cppflags" +AC_MSG_RESULT($have_dnotify) + +dnl dnl See if imon is available; if so, is it IRIX or Linux? dnl if test `uname` = 'IRIX' || test `uname` = 'IRIX64'; then @@ -118,11 +139,17 @@ if test "$have_imon" != "yes"; then have_imon=no AC_DEFINE(HAVE_IMON, 0) + if test "$have_dnotify" = "yes"; then + AC_DEFINE(USE_DNOTIFY) + use_dnotify=true + fi IMON_FUNCS=IMonNone fi +AM_CONDITIONAL(USE_DNOTIFY, $use_dnotify) AC_SUBST(IMON_FUNCS) echo "Using imon support module $IMON_FUNCS" + AC_CHECK_HEADER(sys/statvfs.h, [AC_DEFINE(HAVE_STATVFS, 1) have_statvfs="yes"], [AC_DEFINE(HAVE_STATVFS, 0) have_statvfs="no"]) AC_CHECK_HEADER(sys/syssgi.h, AC_DEFINE(HAVE_SYSSGI, 1), AC_DEFINE(HAVE_SYSSGI, 0)) AC_CHECK_HEADER(sys/fs/nfs_clnt.h, AC_DEFINE(HAVE_SYS_FS_NFS_CLNT_H, 1), AC_DEFINE(HAVE_SYS_FS_NFS_CLNT_H, 0)) @@ -572,7 +599,7 @@ dnl dnl fam is a good deal less interesting without imon. dnl -if test "$have_imon" != 'yes'; then +if test "$have_imon" != 'yes' -a "$have_dnotify" != 'yes'; then cat << EOF ****************************************************************** --- fam-2.6.7/fam/DNotify.c++.dnotify Sun Apr 7 18:57:41 2002 +++ fam-2.6.7/fam/DNotify.c++ Sun Apr 7 18:57:50 2002 @@ -0,0 +1,579 @@ +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it would be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any +// license provided herein, whether implied or otherwise, is limited to +// this program in accordance with the express provisions of the GNU +// General Public License. Patent licenses, if any, provided herein do not +// apply to combinations of this program with other product or programs, or +// any other product whatsoever. This program is distributed without any +// warranty that the program is delivered free of the rightful claim of any +// third person by way of infringement or the like. See the GNU General +// Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write the Free Software Foundation, Inc., 59 +// Temple Place - Suite 330, Boston MA 02111-1307, USA. + +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "DNotify.h" + +#include "Interest.h" +#include "Log.h" +#include "Scheduler.h" +#include "alloc.h" + + +int DNotify::pipe_write_fd = -2; +int DNotify::pipe_read_fd = -2; +volatile sig_atomic_t DNotify::queue_overflowed = 0; +volatile sig_atomic_t DNotify::queue_changed = 0; +int DNotify::change_queue[QUEUESIZE]; +volatile int DNotify::queue_head = 0; // Only modified by read handler +volatile int DNotify::queue_tail = 0; // Only modified by signal handler +DNotify::EventHandler DNotify::ehandler; + +DNotify::DirWatch *DNotify::dir_hash[DIR_HASHSIZE]; +DNotify::FileWatch *DNotify::file_hash[FILE_HASHSIZE]; + +struct DNotify::FileWatch +{ + DirWatch *dir_watch; + dev_t file_dev; + ino_t file_ino; + FileWatch *next; // The DirWatch.watches list + FileWatch *hash_link; +}; + +struct DNotify::DirWatch +{ + int fd; + dev_t dir_dev; + ino_t dir_ino; + + DirWatch *hash_link; + FileWatch *watches; +}; + +struct DNotify::ChangeEventData +{ + dev_t file_dev; + ino_t file_ino; +}; + +DNotify::DNotify(EventHandler h) +{ + assert(ehandler == NULL); + ehandler = h; +} + +DNotify::~DNotify() +{ + if (pipe_read_fd >= 0) + { + // Tell the scheduler. + + (void) Scheduler::remove_read_handler(pipe_read_fd); + + // Close the pipe. + + if (close(pipe_read_fd) < 0) + Log::perror("can't pipe read end"); + else + Log::debug("closed pipe read end"); + + if (close(pipe_write_fd) < 0) + Log::perror("can't pipe write end"); + else + Log::debug("closed pipe write end"); + pipe_read_fd = -1; + } + ehandler = NULL; +} + +void +DNotify::overflow_signal_handler(int sig, siginfo_t *si, void *data) +{ + char c = 'x'; + + { + char *str = "*************** overflow sigqueue ***********************\n"; + write (STDERR_FILENO, str, strlen(str)); + } + + if (!queue_overflowed) + { + queue_overflowed = 1; + // Trigger the read handler + write(pipe_write_fd, &c, 1); + } +} + +void +DNotify::signal_handler(int sig, siginfo_t *si, void *data) +{ + int left; + char c = 'x'; + + if (queue_head <= queue_tail) + left = (QUEUESIZE + queue_head) - queue_tail; + else + left = queue_head - queue_tail; + + // Must leave at least one item unused to see difference + // Betweeen empty and full + if (left <= 1) + { + queue_overflowed = 1; + { + char *str = "*************** overflow famqueue ****************\n"; + write (STDERR_FILENO, str, strlen(str)); + } + } + else + { + change_queue[queue_tail] = si->si_fd; + queue_tail = (queue_tail + 1) % QUEUESIZE; + } + + if (!queue_changed) + { + queue_changed = 1; + // Trigger the read handler + write(pipe_write_fd, &c, 1); + } +} + +bool +DNotify::is_active() +{ + if (pipe_read_fd == -2) + { + int filedes[2]; + int res; + + res = pipe (filedes); + if (res >= 0) + { Log::debug("opened pipe"); + pipe_read_fd = filedes[0]; + pipe_write_fd = filedes[1]; + + // Setup signal handler: + struct sigaction act; + + act.sa_sigaction = signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGRTMIN, &act, NULL); + + // When the RT queue overflows we get a SIGIO + act.sa_sigaction = overflow_signal_handler; + sigemptyset(&act.sa_mask); + sigaction(SIGIO, &act, NULL); + + (void) Scheduler::install_read_handler(pipe_read_fd, read_handler, NULL); + } + } + return pipe_read_fd >= 0; +} + +DNotify::DirWatch * +DNotify::lookup_dirwatch (int fd) +{ + DirWatch **p; + DirWatch *w; + + p = dir_hashchain (fd); + + while (*p) + { + w = *p; + + if (w->fd == fd) + return w; + + p = &w->hash_link; + } + + return *p; +} + +// This colud be made faster by using another hash table. +// But it's not that bad, since it is only used by express/revoke +DNotify::DirWatch * +DNotify::lookup_dirwatch (dev_t dir_dev, ino_t dir_ino) +{ + DirWatch *p; + int i; + + for (i=0;idir_dev == dir_dev && p->dir_ino == dir_ino) + return p; + + p = p->hash_link; + } + } + + return NULL; +} + +DNotify::FileWatch * +DNotify::lookup_filewatch (dev_t dev, ino_t ino) +{ + FileWatch **p; + FileWatch *w; + + p = file_hashchain (dev, ino); + + while (*p) + { + w = *p; + + if (w->file_dev == dev && w->file_ino == ino) + return w; + + p = &w->hash_link; + } + + return *p; +} + +// Make sure w is not already in the hash table before calling +// this function. +void +DNotify::hash_dirwatch(DirWatch *w) +{ + DirWatch **p; + p = dir_hashchain (w->fd); + w->hash_link = *p; + *p = w; +} + +// Make sure w is not already in the hash table before calling +// this function. +void +DNotify::hash_filewatch(FileWatch *w) +{ + FileWatch **p; + p = file_hashchain (w->file_dev, w->file_ino); + w->hash_link = *p; + *p = w; +} + +void +DNotify::unhash_dirwatch(DirWatch *w) +{ + DirWatch **p; + + p = dir_hashchain (w->fd); + + while (*p) + { + if (*p == w) + { + *p = w->hash_link; + break; + } + p = &(*p)->hash_link; + } + w->hash_link = NULL; +} + +void +DNotify::unhash_filewatch(FileWatch *w) +{ + FileWatch **p; + + p = file_hashchain (w->file_dev, w->file_ino); + + while (*p) + { + if (*p == w) + { + *p = w->hash_link; + break; + } + p = &(*p)->hash_link; + } + w->hash_link = NULL; +} + +DNotify::Status +DNotify::watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino) +{ + struct stat stat; + dev_t dir_dev; + ino_t dir_ino; + DirWatch *dwatch; + FileWatch *fw; + + if (lstat (notify_dir, &stat) == -1) + return BAD; + + dwatch = lookup_dirwatch(stat.st_dev, stat.st_ino); + if (!dwatch) + { + Log::debug ("New DirWatch for %s (%x %x)\n", + notify_dir, (int)stat.st_dev, (int)stat.st_ino); + dwatch = new DirWatch; + dwatch->watches = NULL; + dwatch->hash_link = NULL; + dwatch->dir_dev = stat.st_dev; + dwatch->dir_ino = stat.st_ino; + + dwatch->fd = open(notify_dir, O_RDONLY); + fcntl (dwatch->fd, F_SETSIG, SIGRTMIN); + fcntl (dwatch->fd, F_NOTIFY, + (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB) | DN_MULTISHOT); + hash_dirwatch (dwatch); + } + + fw = lookup_filewatch (file_dev, file_ino); + if (fw && fw->dir_watch == dwatch) + return OK; + + // No old FileWatch, need to add one: + Log::debug("New FileWatch for %x %x\n", (int)file_dev, (int)file_ino); + fw = new FileWatch; + fw->next = dwatch->watches; + dwatch->watches = fw; + fw->file_dev = file_dev; + fw->file_ino = file_ino; + fw->dir_watch = dwatch; + hash_filewatch(fw); + return OK; +} + +char * +dirname_dup (const char *name) +{ + char *copy = strdup(name); + char *res = dirname(copy); + res = strdup(res); + free (copy); + return res; +} + +DNotify::Status +DNotify::express(const char *name, struct stat *status) +{ + struct stat stat; + char *notify_dir; + int res; + Status s; + dev_t dev; + ino_t ino; + + Log::debug("express() name: %s\n", name); + + if (!is_active()) + return BAD; + + if (::lstat (name, &stat) == -1) + return BAD; + + dev = stat.st_dev; + ino = stat.st_ino; + + if ((stat.st_mode & S_IFMT) != S_IFDIR) + notify_dir = dirname_dup (name); + else + notify_dir = (char *)name; + + s = watch_dir (notify_dir, dev, ino); + if (notify_dir != name) + free (notify_dir); + if (s) + return s; + + // Check for a race condition; if someone removed or changed the + // file at the same time that we are expressing interest in it, + // revoke the interest so we don't get notifications about changes + // to a recycled inode that we don't otherwise care about. + // + struct stat st; + if (status == NULL) { + status = &st; + } + if (::lstat(name, status) == -1) { + Log::perror("stat on \"%s\" failed", name); + revoke(name, stat.st_dev, stat.st_ino); + return BAD; + } + if (status->st_dev != stat.st_dev + || status->st_ino != stat.st_ino) { + Log::error("File \"%s\" changed between express and stat", + name); + revoke(name, stat.st_dev, stat.st_ino); + return BAD; + } + + Log::debug("told dnotify to monitor \"%s\" = dev %d/%d, ino %d", name, + major(status->st_dev), minor(status->st_dev), + status->st_ino); + return OK; +} + +DNotify::Status +DNotify::revoke(const char *name, dev_t dev, ino_t ino) +{ + FileWatch *fwatch; + DirWatch *dwatch; + + Log::debug("revoke() name: %s, dev: %x, ino: %x\n", name, dev, ino); + + if (!is_active()) + return BAD; + + // Lookup FileWatch by dev:ino, and its DirWatch. + fwatch = lookup_filewatch (dev, ino); + if (fwatch == NULL) + return BAD; + + dwatch = fwatch->dir_watch; + + // delete FileWatch, if last FileWatch: close fd, delete DirWatch + Log::debug ("Destroying FileWatch for (%x %x)\n", + (int)fwatch->file_dev, (int)fwatch->file_ino); + FileWatch **p; + for (p=&dwatch->watches; *p; p=&(*p)->next) + { + if (*p == fwatch) + { + *p = (*p)->next; + break; + } + } + unhash_filewatch(fwatch); + delete fwatch; + if (dwatch->watches == NULL) + { + Log::debug ("Destroying DirWatch for (%x %x)\n", + (int)dwatch->dir_dev, (int)dwatch->dir_ino); + close(dwatch->fd); + unhash_dirwatch(dwatch); + delete dwatch; + } + + return OK; +} + + +void +DNotify::all_watches_changed(void) +{ + int i; + FileWatch *fw; + + for (i=0; ifile_dev, fw->file_ino, CHANGE); + + fw = fw->hash_link; + } + } +} + + +void +DNotify::read_handler(int fd, void *) +{ + static char readbuf[5000]; + DirWatch *dw; + FileWatch *fw; + int snap_queue_tail; + int last_fd; + + int rc = read(fd, readbuf, sizeof readbuf); + queue_changed = 0; + if (rc < 0) + Log::perror("pipe read"); + else if (queue_overflowed) + { + // There is a *slight* race condition here. Between reading + // the queue_overflow flag and resetting it. But it doesn't + // matter, since I'm gonna handle the overflow after reseting + // anyway. + queue_overflowed = false; + + // We're soon gonna check all watches anyway, so + // get rid of the current queue + queue_head = queue_tail; + + all_watches_changed (); + } + else + { + // Don't read events that happen later than + // the initial read. (Otherwise skipping fd's + // might miss some changes). + snap_queue_tail = queue_tail; + last_fd = -1; + while (queue_head != snap_queue_tail) + { + fd = change_queue[queue_head]; + queue_head = (queue_head + 1) % QUEUESIZE; + + // Skip multiple changes to the same fd + if (fd != last_fd) + { + dw = lookup_dirwatch (fd); + if (dw) + { + int n_watches, i; + ChangeEventData *data; + + Log::debug("dnotify said dev %d/%d, ino %ld changed", + major(dw->dir_dev), minor(dw->dir_dev), dw->dir_ino); + + n_watches = 0; + for (fw=dw->watches; fw; fw=fw->next) + n_watches++; + + data = new ChangeEventData[n_watches]; + + i = 0; + for (fw=dw->watches; fw; fw=fw->next) + { + data[i].file_dev = fw->file_dev; + data[i].file_ino = fw->file_ino; + i++; + } + + for (i = 0; i < n_watches; i++) + { + (*ehandler)(data[i].file_dev, data[i].file_ino, CHANGE); + } + + delete[] data; + } + } + last_fd = fd; + } + } +} + --- fam-2.6.7/fam/DNotify.h.dnotify Sun Apr 7 18:57:41 2002 +++ fam-2.6.7/fam/DNotify.h Sun Apr 7 18:57:47 2002 @@ -0,0 +1,98 @@ +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it would be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any +// license provided herein, whether implied or otherwise, is limited to +// this program in accordance with the express provisions of the GNU +// General Public License. Patent licenses, if any, provided herein do not +// apply to combinations of this program with other product or programs, or +// any other product whatsoever. This program is distributed without any +// warranty that the program is delivered free of the rightful claim of any +// third person by way of infringement or the like. See the GNU General +// Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write the Free Software Foundation, Inc., 59 +// Temple Place - Suite 330, Boston MA 02111-1307, USA. + +#ifndef DNotify_included +#define DNotify_included + +#include "config.h" +#include "Monitor.h" +#include + +// DNotify is an object encapsulating the dnotify linux fcntl. +// It "emulates" the IMon interface. +// There can only be one instantiation of the DNotify object. +// +// The user of this object uses express() and revoke() to +// express/revoke interest in a file. There is also +// a callback, the EventHandler. When an dnotify event comes in, +// the EventHandler is called. +// +// The user of the DNotify object is the Interest class. + +class DNotify : public Monitor { +public: + DNotify(EventHandler h); + ~DNotify(); + + static bool is_active(); + + virtual Status express(const char *name, struct stat *stat_return); + virtual Status revoke(const char *name, dev_t dev, ino_t ino); + +private: + struct FileWatch; + struct DirWatch; + struct ChangeEventData; + + // Class Variables + enum { QUEUESIZE = 1024 }; + static int pipe_write_fd; + static int pipe_read_fd; + static int change_queue[QUEUESIZE]; + static volatile sig_atomic_t DNotify::queue_overflowed; + static volatile sig_atomic_t DNotify::queue_changed; + static volatile int queue_head; // Only modified by read handler + static volatile int queue_tail; // Only modified by signal handler + static EventHandler ehandler; + static void overflow_signal_handler(int sig, siginfo_t *si, void *data); + static void signal_handler(int sig, siginfo_t *si, void *data); + static void read_handler(int fd, void *closure); + + enum { DIR_HASHSIZE = 367 }; + static DirWatch *dir_hash[DIR_HASHSIZE]; + enum { FILE_HASHSIZE = 823 }; + static FileWatch *file_hash[FILE_HASHSIZE]; + + static DirWatch **dir_hashchain(int fd) + { return &dir_hash[(unsigned) (fd) % DIR_HASHSIZE]; } + static FileWatch **file_hashchain(dev_t d, ino_t i) + { return &file_hash[(unsigned) (d+i) % FILE_HASHSIZE]; } + + static DirWatch *lookup_dirwatch (int fd); + static DirWatch *lookup_dirwatch (dev_t dir_dev, ino_t dir_ino); + static FileWatch *lookup_filewatch (dev_t file_dev, ino_t file_ino); + static void hash_dirwatch(DirWatch *w); + static void hash_filewatch(FileWatch *w); + static void unhash_dirwatch(DirWatch *w); + static void unhash_filewatch(FileWatch *w); + static Status watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino); + + static void all_watches_changed(void); + + DNotify(const DNotify&); // Do not copy + DNotify & operator = (const DNotify&); // or assign. +}; + +#endif /* !IMon_included */ + + --- fam-2.6.7/fam/IMon.h.dnotify Tue Dec 18 02:03:37 2001 +++ fam-2.6.7/fam/IMon.h Sun Apr 7 18:57:41 2002 @@ -24,10 +24,7 @@ #define IMon_included #include "config.h" -#include -#include - -#include "Boolean.h" +#include "Monitor.h" struct stat; @@ -41,25 +38,18 @@ // // The user of the IMon object is the Interest class. -class IMon { +class IMon : public Monitor { public: - - enum Status { OK = 0, BAD = -1 }; - enum Event { EXEC, EXIT, CHANGE }; - - typedef void (*EventHandler)(dev_t, ino_t, int event); - IMon(EventHandler h); ~IMon(); static bool is_active(); - Status express(const char *name, struct stat *stat_return); - Status revoke(const char *name, dev_t dev, ino_t ino); + virtual Status express(const char *name, struct stat *stat_return); + virtual Status revoke(const char *name, dev_t dev, ino_t ino); private: - // Class Variables static int imonfd; --- fam-2.6.7/fam/Interest.c++.dnotify Wed Dec 19 23:59:20 2001 +++ fam-2.6.7/fam/Interest.c++ Sun Apr 7 18:57:41 2002 @@ -41,12 +41,21 @@ #include "Event.h" #include "FileSystem.h" #include "IMon.h" +#include "DNotify.h" #include "Log.h" #include "Pollster.h" #include "timeval.h" Interest *Interest::hashtable[]; -IMon Interest::imon(imon_handler); + +#ifdef USE_DNOTIFY +static DNotify dnotify(Interest::monitor_handler); +Monitor * Interest::monitor = &dnotify; +#else +static IMon imon(Interest::monitor_handler); +Monitor * Interest::monitor = &imon; +#endif + bool Interest::xtab_verification = true; Interest::Interest(const char *name, FileSystem *fs, in_addr host, ExportVerification ev) @@ -58,11 +67,11 @@ myhost(host), mypath_exported_to_host(ev == NO_VERIFY_EXPORTED) { - memset(&old_stat, 0, sizeof(old_stat)); - IMon::Status s = IMon::BAD; - - s = imon.express(name, &old_stat); - if (s != IMon::OK) + memset(&old_stat, 0, sizeof(old_stat)); + + Monitor::Status s = Monitor::BAD; + s = monitor->express(name, &old_stat); + if (s != Monitor::OK) { int rc = lstat(name, &old_stat); if (rc < 0) { Log::info("can't lstat %s", name); @@ -99,7 +108,7 @@ } #endif - if (exported_to_host()) fs->ll_monitor(this, s == IMon::OK); + if (exported_to_host()) fs->ll_monitor(this, s == Monitor::OK); } Interest::~Interest() @@ -127,7 +136,7 @@ pp = &p->hashlink; // move to next element } if (!found_same) - (void) imon.revoke(name(), dev, ino); + (void) monitor->revoke(name(), dev, ino); } } @@ -146,7 +155,7 @@ // Express interest. IMon::Status s = IMon::BAD; - s = imon.express(name(), NULL); + s = monitor->express(name(), NULL); if (s != IMon::OK) { return true; } @@ -247,23 +256,23 @@ } void -Interest::imon_handler(dev_t device, ino_t inumber, int event) +Interest::monitor_handler(dev_t device, ino_t inumber, int event) { assert(device || inumber); for (Interest *p = *hashchain(device, inumber), *next = p; p; p = next) { next = p->hashlink; if (p->ino == inumber && p->dev == device) - { if (event == IMon::EXEC) + { if (event == Monitor::EXEC) { p->cur_exec_state = EXECUTING; (void) p->report_exec_state(); } - else if (event == IMon::EXIT) + else if (event == Monitor::EXIT) { p->cur_exec_state = NOT_EXECUTING; (void) p->report_exec_state(); } else - { assert(event == IMon::CHANGE); + { assert(event == Monitor::CHANGE); p->scan(); } } --- fam-2.6.7/fam/Interest.h.dnotify Tue Dec 18 02:03:37 2001 +++ fam-2.6.7/fam/Interest.h Sun Apr 7 18:57:41 2002 @@ -32,7 +32,7 @@ class Event; class FileSystem; -class IMon; +class Monitor; struct stat; // Interest -- abstract base class for filesystem entities of interest. @@ -74,7 +74,7 @@ // Public Class Method - static void imon_handler(dev_t, ino_t, int event); + static void monitor_handler(dev_t, ino_t, int event); static void enable_xtab_verification(bool enable); @@ -121,7 +121,7 @@ // Class Variables - static IMon imon; + static Monitor *monitor; static Interest *hashtable[HASHSIZE]; static bool xtab_verification; --- fam-2.6.7/fam/Makefile.am.dnotify Tue Dec 18 02:03:37 2001 +++ fam-2.6.7/fam/Makefile.am Sun Apr 7 18:57:41 2002 @@ -3,6 +3,12 @@ bin_PROGRAMS = fam sysconf_DATA = fam.conf +if USE_DNOTIFY +DNOTIFY_FILES = DNotify.c++ +else +DNOTIFY_FILES = +endif + fam_SOURCES = \ Activity.c++ \ Activity.h \ @@ -20,6 +26,7 @@ Directory.h \ DirectoryScanner.c++ \ DirectoryScanner.h \ + DNotify.h \ Event.c++ \ Event.h \ File.c++ \ @@ -48,6 +55,7 @@ NFSFileSystem.h \ NetConnection.c++ \ NetConnection.h \ + Monitor.h \ Pollster.c++ \ Pollster.h \ Request.h \ @@ -72,9 +80,10 @@ main.c++ \ timeval.c++ \ timeval.h \ - @IMON_FUNCS@.c++ + @IMON_FUNCS@.c++ \ + $(DNOTIFY_FILES) -EXTRA_fam_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ +EXTRA_fam_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ DNotify.c++ fam_LDADD = -lrpcsvc $(top_srcdir)/support/libsupport.a --- fam-2.6.7/fam/Monitor.h.dnotify Sun Apr 7 18:57:41 2002 +++ fam-2.6.7/fam/Monitor.h Sun Apr 7 18:57:41 2002 @@ -0,0 +1,57 @@ +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it would be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any +// license provided herein, whether implied or otherwise, is limited to +// this program in accordance with the express provisions of the GNU +// General Public License. Patent licenses, if any, provided herein do not +// apply to combinations of this program with other product or programs, or +// any other product whatsoever. This program is distributed without any +// warranty that the program is delivered free of the rightful claim of any +// third person by way of infringement or the like. See the GNU General +// Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write the Free Software Foundation, Inc., 59 +// Temple Place - Suite 330, Boston MA 02111-1307, USA. + +#ifndef Monitor_included +#define Monitor_included + +#include "config.h" +#include +#include + +struct stat; + +// Monitor is an abstract baseclass for differend file monitoring +// systems. The original system used was IMon, and the Montor API +// is heavily influenced by that. +// There can only be one instantiation of the Monitor object. +// +// The user of this object uses express() and revoke() to +// express/revoke interest in a file to imon. There is also +// a callback, the EventHandler. When an event comes in, +// the EventHandler is called. +// +// The main implementers of the Monitor class is IMon and DNotify + +class Monitor { +public: + + enum Status { OK = 0, BAD = -1 }; + enum Event { EXEC, EXIT, CHANGE }; + + typedef void (*EventHandler)(dev_t, ino_t, int event); + + virtual Status express(const char *name, struct stat *stat_return) = 0; + virtual Status revoke(const char *name, dev_t dev, ino_t ino) = 0; +}; + +#endif /* !Monitor_included */ --- fam-2.6.7/include/BTree.h.dnotify Tue Dec 18 02:03:38 2001 +++ fam-2.6.7/include/BTree.h Sun Apr 7 18:57:41 2002 @@ -271,7 +271,7 @@ n += that->n + 1; link[n] = that->link[that->n]; that->n = 0; - that->link[0] = NULL; + that->link[0] = 0; } /////////////////////////////////////////////////////////////////////////////// @@ -280,7 +280,7 @@ template BTree::BTree() - : root(NULL), npairs(0) + : root(0), npairs(0) { assert(!(fanout % 2)); } @@ -407,7 +407,7 @@ BTree::Closure BTree::insert(Node *p, const Key& key, const Value& value) { - if (!p) return Closure(key, value, NULL); + if (!p) return Closure(key, value, 0); // If you're running Purify on a client linking with libfam, and it says // that line is causing a 3-byte UMR for BTree::insert() in // FAMNextEvent() ("Reading 8 bytes from 0x... on the stack (3 bytes at @@ -475,7 +475,7 @@ case UNDER: if (root->n == 0) { Node *nr = root->link[0]; - root->link[0] = NULL; // don't delete subtree + root->link[0] = 0; // don't delete subtree delete root; root = nr; } @@ -507,8 +507,8 @@ Node *cp = p->link[i]; assert(cp); - Node *rp = i < p->n ? p->link[i + 1] : NULL; - Node *lp = i > 0 ? p->link[i - 1] : NULL; + Node *rp = i < p->n ? p->link[i + 1] : 0; + Node *lp = i > 0 ? p->link[i - 1] : 0; assert(!rp || rp->n >= fanout / 2); assert(!lp || lp->n >= fanout / 2); --=-CWaXFqTgxZEYjFWtsUXH-- From andreas.lundin.2435@student.uu.se Mon Aug 11 06:44:10 2003 Received: with ECARTIS (v1.0.0; list fam); Mon, 11 Aug 2003 06:44:17 -0700 (PDT) Received: from elanus.its.uu.se (Elanus.its.UU.SE [130.238.4.143]) by oss.sgi.com (8.12.9/8.12.9) with SMTP id h7BDi8Fl029891 for ; Mon, 11 Aug 2003 06:44:09 -0700 Received: from elanus (localhost [127.0.0.1]) by localhost (Postfix) with SMTP id A36994965 for ; Mon, 11 Aug 2003 15:44:05 +0200 (DFT) Received: from elanus.its.uu.se(127.0.0.1) by elanus.its.uu.se via virus-scan id s21071; Mon, 11 Aug 03 15:43:56 +0200 Received: from enterprise (unknown [10.11.33.18]) by elanus.its.uu.se (Postfix) with ESMTP id 251E74BFB for ; Mon, 11 Aug 2003 15:41:40 +0200 (DFT) Content-Type: text/plain; charset="us-ascii" From: Andreas Lundin To: fam@oss.sgi.com Subject: Problems with fam and samba Date: Mon, 11 Aug 2003 15:58:13 +0200 User-Agent: KMail/1.4.2 MIME-Version: 1.0 Message-Id: <200308111558.13293.anlu2435@student.uu.se> Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by oss.sgi.com id h7BDi8Fl029891 X-archive-position: 145 X-ecartis-version: Ecartis v1.0.0 Sender: fam-bounce@oss.sgi.com Errors-to: fam-bounce@oss.sgi.com X-original-sender: andreas.lundin.2435@student.uu.se Precedence: bulk X-list: fam Hi, I'm having some odd problems with fam. On my linux system I have mounted some partitions that are shared by a Win2k machine on my LAN. With any GUI filemanager using fam I can create files and directories, but I can't delete directories, only files. If I try to delete a directory, it just doesn't work. If I try to delete a directory containing files, the files will be deleted but not the directory. I've tried different GUI filemanagers and the only one that returns an informative error message is nautilus which tells me the directory is "busy", so I guess fam somehow thinks the directory is used by some other process. If I turn of fam, or use the console, I can delete the directories without problems. Also, the problem is only on samba shares, this problem doesn't appear in my regular linux file system or on the local windows partitions I have mounted. So it seems to be a problem related to fam or samba (or maybe rather smbmount). I have tried fam 2.6.7, 2.6.9 and 2.6.10 on two different machine and all with the same error. Is this a known problem, or am I making some glaring error? Thanks, //Andreas From steleman@nyc.rr.com Wed Aug 13 20:49:07 2003 Received: with ECARTIS (v1.0.0; list fam); Wed, 13 Aug 2003 20:49:14 -0700 (PDT) Received: from nycsmtp4out-eri0.rdc-nyc.rr.com (nycsmtp4out-eri0.rdc-nyc.rr.com [24.29.99.227]) by oss.sgi.com (8.12.9/8.12.9) with SMTP id h7E3n3Fl032348 for ; Wed, 13 Aug 2003 20:49:06 -0700 Received: from darthvader.nyc.rr.com (66-108-232-60.nyc.rr.com [66.108.232.60]) by nycsmtp4out-eri0.rdc-nyc.rr.com (8.12.1/Road Runner SMTP Server 1.0) with ESMTP id h7E3n2w4014943 for ; Wed, 13 Aug 2003 23:49:02 -0400 (EDT) Content-Type: text/plain; charset="iso-8859-15" From: Stefan Teleman Reply-To: steleman@nyc.rr.com Organization: Disorganized Subject: hello Date: Wed, 13 Aug 2003 23:48:19 -0400 User-Agent: KMail/1.4.3 To: fam@oss.sgi.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-Id: <200308132348.19991.steleman@nyc.rr.com> X-archive-position: 146 X-ecartis-version: Ecartis v1.0.0 Sender: fam-bounce@oss.sgi.com Errors-to: fam-bounce@oss.sgi.com X-original-sender: steleman@nyc.rr.com Precedence: bulk X-list: fam Hi! Please allow me to introduce myself: i am one of the maintainers of KDE Solaris. Rolf Nolden suggested i contact you regarding FAM. Earlier this past May i have ported FAM 2.6.9 to Solaris 8 with the Sun Forte 7 compiler (filesystem polling mode). FAM is used in KDE, and, as part of the upcoming KDE release, i wanted to provide FAM support in KDE. I am currently in the middle of writing a /dev/poll interface for Solaris, but it's not ready yet. I have been using FAM in KDE ever since May, and it is very stable. Several people (including Rolf) have expressed interest in this FAM Solaris port. I was just wondering if my port would be of interest to the FAM community. I can make the sources, binaries and a Sun pkg available. Please let me know. --Stefan -- Stefan Teleman 'Nobody Expects the Spanish Inquisition' steleman@nyc.rr.com -Monty Python From jorgland@sol.wh-hms.uni-ulm.de Sat Aug 30 08:03:03 2003 Received: with ECARTIS (v1.0.0; list fam); Sat, 30 Aug 2003 08:03:37 -0700 (PDT) Received: from sol.wh-hms.uni-ulm.de (sol.wh-hms.uni-ulm.de [134.60.220.1]) by oss.sgi.com (8.12.9/8.12.5) with SMTP id h7UF31WZ003303 for ; Sat, 30 Aug 2003 08:03:02 -0700 Received: (qmail 3083 invoked by uid 3342); 30 Aug 2003 15:03:01 -0000 Date: Sat, 30 Aug 2003 17:03:01 +0200 From: Joerg Wendland To: fam@oss.sgi.com Cc: owner-fam@oss.sgi.com Subject: searching for the FAM maintainer Message-ID: <20030830150301.GE9625@sol.wh-hms.uni-ulm.de> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="2B/JsCI69OhZNC5r" Content-Disposition: inline User-Agent: Mutt/1.5.3i X-archive-position: 147 X-ecartis-version: Ecartis v1.0.0 Sender: fam-bounce@oss.sgi.com Errors-to: fam-bounce@oss.sgi.com X-original-sender: joergland@debian.org Precedence: bulk X-list: fam --2B/JsCI69OhZNC5r Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hello list, list-owner, I am the maintainer of FAM Debian packages. Mail to the upstream maintainer Michael Wardle bounces with "no such mailbox". Is he still active as FAM maintainer or who does this job now? I have a pile of patches and ideas for further development of FAM and want to coordinate with upstream. Thanks, Joerg --=20 Joerg "joergland" Wendland GPG: 51CF8417 FP: 79C0 7671 AFC7 315E 657A F318 57A3 7FBD 51CF 8417 --2B/JsCI69OhZNC5r Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQE/ULylV6N/vVHPhBcRAmziAJ0dVYUIm58lF4EbEYRr798spekbvACgk9S0 tpPMrqglbtSNrXLHsZ6W2z4= =gWfj -----END PGP SIGNATURE----- --2B/JsCI69OhZNC5r--