monit-dev
[Top][All Lists]
Advanced

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

filesystem usage patch


From: Martin Pala
Subject: filesystem usage patch
Date: Fri, 03 Jan 2003 11:53:31 +0000
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2) Gecko/20021203

Hi,

there's patch that implements filesystem usage check. Main part is:

int  get_fsusage(char *object, Statfs_T buf)

Result is stored in Statfs_T structure, that is platform independent - the result is intended to be used in Monit's validating function. "object" could be file or directory that is part of given filesystem or block special device that identifies it (filesystem must be mounted).

The resulting structure contains information about blocks and files/inodes usage so it is possible to monitor both parameters.

I tested it and it is working well on linux (debian + redhat) and Solaris 8.

TODO:
- use this filesystem interface in the test and make it configurable (extent parser, cevlet, etc.)
- documentation
- BSD port (i don't have any BSD machine)

I'm going to the holidays tomorow for a week and i will not have any internet connection. I have some work to do on that week => i can continue on it after next week as i'll be back (or it will be super if there will be someone who can look on it :)

May i sync it to the CVS?

Cheers,
Martin
diff -Naur monit/configure.ac monit.cvs-20030103/configure.ac
--- monit/configure.ac  Fri Dec 13 16:42:13 2002
+++ monit.cvs-20030103/configure.ac     Fri Jan  3 11:04:28 2003
@@ -48,7 +48,7 @@
 AC_HEADER_SYS_WAIT
 AC_HEADER_STAT
 AC_HEADER_TIME
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h string.h 
strings.h sys/ioctl.h unistd.h sys/socket.h syslog.h sys/loadavg.h asm/param.h 
limits.h stropts.h getopt.h sys/filio.h string.h sys/time.h errno.h])
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h string.h 
strings.h sys/ioctl.h unistd.h sys/socket.h syslog.h sys/loadavg.h asm/param.h 
limits.h stropts.h getopt.h sys/filio.h string.h sys/time.h errno.h sys/vfs.h 
sys/statvfs.h mntent.h sys/mnttab.h])
 
 # Check for types.
 AC_TYPE_MODE_T
@@ -82,6 +82,8 @@
 AC_FUNC_MALLOC
 AC_FUNC_STAT
 AC_FUNC_STRFTIME
+AC_CHECK_FUNCS(statfs)
+AC_CHECK_FUNCS(statvfs)
 
 # Find the right directory to put the root-mode PID file in
 AC_MSG_CHECKING([pid file location])
@@ -97,6 +99,14 @@
          [Define to the pid storage directory.])
 AC_MSG_RESULT([$piddir])
 
+# Test mounted filesystem description file
+if test -f "/etc/mtab"
+then
+  AC_DEFINE([HAVE_MTAB], 1, [Define to 1 if you have /etc/mtab])
+elif test -f "/etc/mnttab"; then
+  AC_DEFINE([HAVE_MNTTAB], 1, [Define to 1 if you have /etc/mnttab])
+fi
+
 # Backward compatibility until we get ride of arch settings
 if test `uname` = "SunOS" 
 then
diff -Naur monit/files.c monit.cvs-20030103/files.c
--- monit/files.c       Mon Dec 30 09:43:47 2002
+++ monit.cvs-20030103/files.c  Fri Jan  3 11:33:22 2003
@@ -31,10 +31,6 @@
 #include <strings.h>
 #endif
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
@@ -43,9 +39,39 @@
 #include <sys/stat.h>
 #endif
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#endif
+
+#ifdef HAVE_SYS_MNTTAB_H
+# include <sys/mnttab.h>
+#endif
+
+
 #include "monitor.h"
 
 
+#if defined HAVE_STATVFS
+#define statfs statvfs
+#endif
+
+
 /**
  *  Utilities used for managing files used by monit.
  *
@@ -368,5 +394,144 @@
 
   return TRUE;
 
+}
+
+
+/**
+ * This function validates if given object is valid for filesystem
+ * informations statistics. Valid objects are file or directory that
+ * is part of requested filesystem or block special device. In the
+ * case of file or directory the result is original object, in the
+ * case of block special device mountpoint is returned. In any case,
+ * filesystem must be mounted.
+ * @param object Identifies appropriate device object
+ * @param path String to store result
+ * @param path_length Defines max. length of the resulting string
+ * @return NULL in the case of failure otherwise pointer to
+ * resulting path
+ */
+char *get_device(char *path, unsigned path_length, char *object) { 
+
+  struct stat buf;
+
+  ASSERT(path && object);
+
+  if(stat(object, &buf) != 0) {
+    log("%s: Cannot stat '%s' -- %s\n", prog, object, STRERROR);
+    return NULL;
+  }
+
+  if(S_ISREG(buf.st_mode) || S_ISDIR(buf.st_mode)) {
+
+    memset(path, '\0', path_length);
+    return strncpy(path, object, path_length-1);
+
+  } else if(S_ISBLK(buf.st_mode)) {
+
+    FILE *mntfd;
+
+    #ifdef HAVE_MTAB
+
+    struct mntent *mnt;
+
+    if((mntfd= setmntent("/etc/mtab", "r")) == NULL) {
+      log("%s: Cannot open /etc/mtab file", prog);
+      return NULL;
+    }
+
+    /* Last match is significant */
+    while((mnt= getmntent(mntfd)) != NULL) {
+
+      if(is(object, mnt->mnt_fsname)) {
+        memset(path, '\0', path_length);
+        strncpy(path, mnt->mnt_dir, path_length-1);
+      }
+
+    }
+
+    endmntent(mntfd);
+
+    #elif defined HAVE_MNTTAB
+
+    struct mnttab mnt;
+
+    if((mntfd= fopen("/etc/mnttab", "r")) == NULL) {
+      log("%s: Cannot open /etc/mnttab file", prog);
+      return NULL;
+    }
+
+    /* Last match is significant */
+    while(getmntent(mntfd, &mnt) == 0) {
+
+      if(is(object, mnt.mnt_special)) {
+        memset(path, '\0', path_length);
+        strncpy(path, mnt.mnt_mountp, path_length-1);
+      }
+
+    }
+
+    fclose(mntfd);
+
+    #else
+
+    log("%s: Unsupported mounted filesystem information method", prog);
+    return NULL;
+
+    #endif
+
+    return path;
+
+  }
+
+  log("%s: Not file, directory or block special device: '%s'", prog, object);
+
+  return NULL;
+
+}
+
+
+/**
+ * Filesystem usage statistics
+ * @param object Identifies requested device
+ * @param buf Information structure where resulting data will be stored
+ * @return TRUE if informations were succesfully read otherwise FALSE
+ */
+int get_fsusage(char *object, Statfs_T buf) { 
+
+  #if (defined HAVE_STATFS) || (defined HAVE_STATVFS)
+
+  struct statfs usage;
+
+  #else
+
+  log("%s: Unsupported filesystem informations gathering method\n", prog);
+
+  return FALSE;
+
+  #endif
+
+  char path[STRLEN];
+
+  ASSERT(object);
+
+  if(!get_device(path, STRLEN, object)) {
+    log("%s: Error looking for filesystem '%s'\n", prog, object);
+    return FALSE;
+  }
+
+  if(statfs(path, &usage) != 0) {
+    log("%s: Error getting usage statistics for device '%s' -- %s\n", prog, 
object, STRERROR);
+    return FALSE;
+  }
+
+  buf->f_bsize=           usage.f_bsize;
+  buf->f_blocks=          usage.f_blocks;
+  buf->f_blocksfree=      usage.f_bavail;
+  buf->f_blocksfreetotal= usage.f_bfree;
+  buf->f_files=           usage.f_files;
+  buf->f_filesfree=       usage.f_ffree;
+
+  return TRUE;
+
 }
 
diff -Naur monit/monitor.h monit.cvs-20030103/monitor.h
--- monit/monitor.h     Fri Jan  3 09:41:25 2003
+++ monit.cvs-20030103/monitor.h        Fri Jan  3 11:04:28 2003
@@ -269,6 +269,18 @@
   int length;                         /**< The length of the arguments array */
 } *Command_T;
 
+
+/** Defines filesystem device data */
+typedef struct mystatfs {
+  long    f_bsize;                                   /** Transfer block size */
+  long    f_blocks;                      /** Total data blocks in filesystem */
+  long    f_blocksfree;           /** Free blocks available to non-superuser */
+  long    f_blocksfreetotal;                   /** Free blocks in filesystem */
+  long    f_files;                        /** Total file nodes in filesystem */
+  long    f_filesfree;                     /** Free file nodes in filesystem */
+} *Statfs_T;
+
+
 /** Defines process data */
 typedef struct myprocess {
   char *name;                                  /**< Process descriptive name */
@@ -385,5 +397,7 @@
 void  redirect_stdfd();
 pid_t getpgid(pid_t);
 int   check_file(char *, char *, int);
+char *get_device(char *, unsigned, char *);
+int   get_fsusage(char *, Statfs_T);
 
 #endif

reply via email to

[Prev in Thread] Current Thread [Next in Thread]