[vhffs-dev] [934] autotoolized quota, rewrote quota stuff, wrote quota cache backend but it is not used yet

[ Thread Index | Date Index | More vhffs.org/vhffs-dev Archives ]


Revision: 934
Author:   gradator
Date:     2007-09-21 12:20:48 +0000 (Fri, 21 Sep 2007)

Log Message:
-----------
autotoolized quota, rewrote quota stuff, wrote quota cache backend but it is not used yet

Modified Paths:
--------------
    trunk/vhffs-fs/config.h.in
    trunk/vhffs-fs/configure.ac
    trunk/vhffs-fs/vhffsfs.c


Modified: trunk/vhffs-fs/config.h.in
===================================================================
--- trunk/vhffs-fs/config.h.in	2007-09-20 23:21:24 UTC (rev 933)
+++ trunk/vhffs-fs/config.h.in	2007-09-21 12:20:48 UTC (rev 934)
@@ -176,12 +176,33 @@
 /* ??? */
 #undef VHFFSFS_CACHE_QUERY_TIMEOUT
 
+/* ??? */
+#undef VHFFSFS_CHECKQUOTA_CACHE_REFRESH
+
+/* ??? */
+#undef VHFFSFS_CHECKQUOTA_CACHE_TIMEOUT
+
 /* VHFFS-fs config file */
 #undef VHFFSFS_CONFIG
 
-/* Enable caching facilities */
+/* Enable queries cache facility */
 #undef WITH_CACHE
 
+/* Enable queries cache facility debugging */
+#undef WITH_CACHE_DEBUG
+
+/* Enable quota check */
+#undef WITH_CHECKQUOTA
+
+/* Enable quota cache */
+#undef WITH_CHECKQUOTA_CACHE
+
+/* Enable quota cache debugging */
+#undef WITH_CHECKQUOTA_CACHE_DEBUG
+
+/* Enable quota through RPC */
+#undef WITH_CHECKQUOTA_RPC
+
 /* Required for fuse to works correctly */
 #undef _FILE_OFFSET_BITS
 

Modified: trunk/vhffs-fs/configure.ac
===================================================================
--- trunk/vhffs-fs/configure.ac	2007-09-20 23:21:24 UTC (rev 933)
+++ trunk/vhffs-fs/configure.ac	2007-09-21 12:20:48 UTC (rev 934)
@@ -13,14 +13,22 @@
 # Checks for programs.
 AC_PROG_CC
 
-AC_ARG_ENABLE(cache,
-    AC_HELP_STRING([--enable-cache],
-        [Enable caching (see --with-cache-query-timeout and --with-cache-query-flush)
-            [default=yes]]), enable_cache=$enableval, enable_cache=yes)
+# Cache stuff
+AC_ARG_ENABLE(cache-query,
+    AC_HELP_STRING([--enable-cache-query],
+        [Enable caching of SQL queries (see --with-cache-query-timeout , --with-cache-query-flush and --enable-cache-query-debug)
+            [default=yes]]), enable_cache_query=$enableval, enable_cache_query=yes)
 
-# Cache stuff
-if test "$enable_cache" = yes ; then
-    AC_DEFINE([WITH_CACHE], [1], [Enable caching facilities])
+AC_ARG_ENABLE(cache-query-debug,
+    AC_HELP_STRING([--enable-cache-query-debug],
+        [Enable debug of queries cache
+            [default=no]]), enable_cache_query_debug=$enableval, enable_cache_query_debug=no)
+
+if test "$enable_cache_query" = yes ; then
+    AC_DEFINE([WITH_CACHE], [1], [Enable queries cache facility])
+    if test "$enable_cache_query_debug" = yes ; then
+        AC_DEFINE([WITH_CACHE_DEBUG], [1], [Enable queries cache facility debugging])
+    fi
     AC_ARG_WITH([--with-cache-query-timeout],
         AC_HELP_STRING([--with-cache-query-timeout],
             [???? [default=600]]), 
@@ -33,6 +41,52 @@
         AC_DEFINE([VHFFSFS_CACHE_QUERY_FLUSH_EVERY], 1800, [???]))
 fi
 
+
+# Check quota stuff
+AC_ARG_ENABLE(check-quota,
+    AC_HELP_STRING([--enable-check-quota],
+        [Enable check of quota (see --enable-check-quota-rpc and --enable-check-quota-cache)
+            [default=yes]]), enable_checkquota=$enableval, enable_checkquota=yes)
+
+AC_ARG_ENABLE(check-quota-rpc,
+    AC_HELP_STRING([--enable-check-quota-rpc],
+        [Enable check of quota through RPC
+            [default=yes]]), enable_checkquota_rpc=$enableval, enable_checkquota_rpc=yes)
+
+AC_ARG_ENABLE(check-quota-cache,
+    AC_HELP_STRING([--enable-check-quota-cache],
+        [Enable quota cache (see --enable-check-quota-cache-debug , --with-check-quota-cache-timeout , --with-check-quota-cache-flush )
+            [default=yes]]), enable_checkquota_cache=$enableval, enable_checkquota_cache=yes)
+
+AC_ARG_ENABLE(check-quota-cache-debug,
+    AC_HELP_STRING([--enable-check-quota-cache-debug],
+        [Enable quota cache debugging
+            [default=no]]), enable_checkquota_cache_debug=$enableval, enable_checkquota_cache_debug=no)
+
+if test "$enable_checkquota" = yes ; then
+    AC_DEFINE([WITH_CHECKQUOTA], [1], [Enable quota check])
+    if test "$enable_checkquota_rpc" = yes ; then
+        AC_DEFINE([WITH_CHECKQUOTA_RPC], [1], [Enable quota through RPC])
+    fi
+    if test "$enable_checkquota_cache" = yes ; then
+       AC_DEFINE([WITH_CHECKQUOTA_CACHE], [1], [Enable quota cache])
+       if test "$check-quota-cache-debug" = yes ; then
+           AC_DEFINE([WITH_CHECKQUOTA_CACHE_DEBUG], [1], [Enable quota cache debugging])
+       fi
+       AC_ARG_WITH([check-quota-cache-timeout],
+           AC_HELP_STRING([--with-check-quota-cache-timeout],
+               [???? [default=10]]), 
+           AC_DEFINE([VHFFSFS_CHECKQUOTA_CACHE_TIMEOUT], $withval, [???]),
+           AC_DEFINE([VHFFSFS_CHECKQUOTA_CACHE_TIMEOUT], 30, [???]))
+       AC_ARG_WITH([check-quota-cache-flush],
+           AC_HELP_STRING([--with-check-quota-cache-flush],
+               [???? [default=1800]]),
+           AC_DEFINE([VHFFSFS_CHECKQUOTA_CACHE_REFRESH], $withval, [???]),
+           AC_DEFINE([VHFFSFS_CHECKQUOTA_CACHE_REFRESH], 1800, [???]))
+    fi
+fi
+
+
 # fuse stuff
 AC_ARG_WITH(fuse-version,
     AC_HELP_STRING([--with-fuse-version],
@@ -78,7 +132,7 @@
 AC_CHECK_HEADERS(fuse.h,,, [#define _FILE_OFFSET_BITS 64])
 AC_CHECK_HEADERS([fcntl.h inttypes.h postgresql/libpq-fe.h pthread.h signal.h stdint.h stdio.h unistd.h], 
     [], [AC_MSG_ERROR([Missing headers, bailing out])])
-if test "$enable_cache" = yes ; then
+if test "$enable_cache_query" = yes || test "$enable_checkquota_cache" = yes ; then
     PKG_CHECK_MODULES(GLIB2, [glib-2.0 >= 2.0.2])
     CFLAGS="$CFLAGS $GLIB2_CFLAGS"
     LIBS="$LIBS $GLIB2_LIBS"

Modified: trunk/vhffs-fs/vhffsfs.c
===================================================================
--- trunk/vhffs-fs/vhffsfs.c	2007-09-20 23:21:24 UTC (rev 933)
+++ trunk/vhffs-fs/vhffsfs.c	2007-09-21 12:20:48 UTC (rev 934)
@@ -9,11 +9,6 @@
 #define VHFFSFS_MAXCONNDB 5
 #define VHFFSFS_EMPTYDIR "/tmp/emptydir"
 
-#define WITH_CACHE_DEBUG 1
-
-#define WITH_CHECKQUOTA 1
-#define WITH_CHECKQUOTA_RPC 1
-
 #define _GNU_SOURCE
 
 #if HAVE_CONFIG_H
@@ -49,7 +44,7 @@
 #include <pthread.h>
 #include <signal.h>
 
-#ifdef WITH_CACHE
+#if defined(WITH_CACHE) || defined(WITH_CHECKQUOTA_CACHE)
 #include <glib.h>
 #endif
 
@@ -66,7 +61,6 @@
 #include "md5.h"
 
 #ifdef WITH_CACHE
-
 typedef struct {
 	char *query;
 	PGresult *result;
@@ -75,6 +69,15 @@
 } vhffsfs_cache_query;
 #endif
 
+#ifdef WITH_CHECKQUOTA_CACHE
+typedef struct {
+	gid_t gid;
+	struct dqblk *dq;
+	time_t arrival;
+	int ref;
+} vhffsfs_cache_quota;
+#endif
+
 struct vhffsfs {
 	pthread_mutex_t pg_lock[VHFFSFS_MAXCONNDB];
 	PGconn *pg_conn[VHFFSFS_MAXCONNDB];
@@ -107,12 +110,18 @@
 	char *repositoriesrpcserver;
 	char *repositoriesrpcpath;
 #endif
+#ifdef WITH_CHECKQUOTA_CACHE
+	GHashTable *quotacacheused;
+	GPtrArray* quotacachekeys;
+	pthread_mutex_t quotacachelock;
+	int quotacachethreadstarted;
 #endif
+#endif
 };
 
 static struct vhffsfs vhffsfs;
 
-#ifdef WITH_CACHE
+#if defined(WITH_CACHE) || defined(WITH_CHECKQUOTA_CACHE)
 time_t vhffsfs_cache_arrival()  {
 	struct timeval tv;
 	gettimeofday(&tv, NULL);
@@ -125,7 +134,9 @@
 	if(tv.tv_sec - arrival >= timeout) return 1;
 	return 0;
 }
+#endif
 
+#ifdef WITH_CACHE
 static inline void vhffsfs_cache_lock()  {
 	pthread_mutex_lock(&vhffsfs.cachelock);
 }
@@ -221,51 +232,51 @@
 
 static void *vhffsfs_cache_flush(void *data_)
 {
-    (void) data_;
+	(void) data_;
 
-    while(1) {
-	GPtrArray *keys;
-	int i;
+	while(1) {
+		GPtrArray *keys;
+		int i;
 
-	sleep(VHFFSFS_CACHE_QUERY_FLUSH_EVERY);
+		sleep(VHFFSFS_CACHE_QUERY_FLUSH_EVERY);
 
-	keys = g_ptr_array_sized_new(4096);
+		keys = g_ptr_array_sized_new(4096);
 
-	//printf("FLUSH CACHE\n");
+		//printf("FLUSH CACHE\n");
 
-	// copy keys
-	vhffsfs_cache_lock();
-	for(i = 0 ; i < vhffsfs.cachekeys->len ; i++)  {
-		g_ptr_array_add(keys, strdup(vhffsfs.cachekeys->pdata[i]));
-	}
-	vhffsfs_cache_unlock();
+		// copy keys
+		vhffsfs_cache_lock();
+		for(i = 0 ; i < vhffsfs.cachekeys->len ; i++)  {
+			g_ptr_array_add(keys, strdup(vhffsfs.cachekeys->pdata[i]));
+		}
+		vhffsfs_cache_unlock();
 
-	// sleep a bit to not lock the cache too much
-	sleep(1);
+		// sleep a bit to not lock the cache too much
+		sleep(1);
 
-	for(i = 0 ; i < keys->len ; i++)  {
-		char *query = keys->pdata[i];
-		vhffsfs_cache_query *vcq;
+		for(i = 0 ; i < keys->len ; i++)  {
+			char *query = keys->pdata[i];
+			vhffsfs_cache_query *vcq;
 
-		vhffsfs_cache_lock();
-		vcq = g_hash_table_lookup(vhffsfs.cachequeries, query);
-		if(vcq && vhffsfs_cache_timeout(vcq->arrival, VHFFSFS_CACHE_QUERY_TIMEOUT))  {
+			vhffsfs_cache_lock();
+			vcq = g_hash_table_lookup(vhffsfs.cachequeries, query);
+			if(vcq && vhffsfs_cache_timeout(vcq->arrival, VHFFSFS_CACHE_QUERY_TIMEOUT))  {
 #ifdef WITH_CACHE_DEBUG
-			fprintf(stdout, "CACHE: TIMEOUT: '%s'\n", query);
+				fprintf(stdout, "CACHE: TIMEOUT: '%s'\n", query);
 #endif
-			vhffsfs_cache_unlock();
-			vhffsfs_cache_del(query);
+				vhffsfs_cache_unlock();
+				vhffsfs_cache_del(query);
+			}
+			else vhffsfs_cache_unlock();
+
+			free(query);
+			//sleep a bit to not lock the cache too much
+			usleep(100000);
 		}
-		else vhffsfs_cache_unlock();
 
-		free(query);
-		//sleep a bit to not lock the cache too much
-		usleep(100000);
+		g_ptr_array_free(keys, TRUE);
 	}
-
-	g_ptr_array_free(keys, TRUE);
-    }
-    return NULL;
+	return NULL;
 }
 
 
@@ -747,27 +758,206 @@
 
 
 #ifdef WITH_CHECKQUOTA
-/* return 0 if the gid is not over quota, 1 if over quota, else return -errno value */
-int vhffsfs_checkquotagid_blockdev(char *blockdev, int gid)  {
+#ifdef WITH_CHECKQUOTA_CACHE
+static inline void vhffsfs_checkquota_cache_lock()  {
+	pthread_mutex_lock(&vhffsfs.quotacachelock);
+}
 
-	struct dqblk dq;
-	if(!blockdev || !gid)  return -EINVAL;
+static inline void vhffsfs_checkquota_cache_unlock()  {
+	pthread_mutex_unlock(&vhffsfs.quotacachelock);
+}
 
-	if(quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), blockdev, gid, (caddr_t)&dq)) {
-		return -errno;
-	} else {
-		if(dq.dqb_curspace >> 10 > dq.dqb_bhardlimit  ||  dq.dqb_curinodes > dq.dqb_ihardlimit)  return 1;
+struct dqblk *vhffsfs_checkquota_cache_add(gid_t gid, struct dqblk *dq)  {
+	vhffsfs_cache_quota *vcq;
+	vhffsfs_checkquota_cache_lock();
+	vcq = g_hash_table_lookup(vhffsfs.quotacacheused, GINT_TO_POINTER(gid));
+	if(vcq) {
+		vcq->ref++;
+		vhffsfs_checkquota_cache_unlock();
+		free(dq);
+		return vcq->dq;
 	}
+#ifdef WITH_CHECKQUOTA_CACHE_DEBUG
+	printf("QUOTACACHE: ADDING: %d\n", gid);
+#endif
+	vcq = malloc(sizeof(vhffsfs_cache_quota));
+	vcq->gid = gid;
+	vcq->dq = dq;
+	vcq->arrival = vhffsfs_cache_arrival();
+	vcq->ref = 1;
+	g_hash_table_insert(vhffsfs.quotacacheused, GINT_TO_POINTER(vcq->gid), vcq);
+	g_ptr_array_add(vhffsfs.quotacachekeys, GINT_TO_POINTER(vcq->gid));
+	vhffsfs_checkquota_cache_unlock();
+	return vcq->dq;
+}
+
+void vhffsfs_checkquota_cache_del(gid_t gid)  {
+	vhffsfs_cache_quota *vcq;
+	vhffsfs_checkquota_cache_lock();
+	vcq = g_hash_table_lookup(vhffsfs.quotacacheused, GINT_TO_POINTER(gid));
+	// non existing or still referenced
+	if(!vcq || vcq->ref > 0) {
+		vhffsfs_checkquota_cache_unlock();
+		return;
+	}
+#ifdef WITH_CHECKQUOTA_CACHE_DEBUG
+	printf("CACHE: DELETING: %d\n", gid);
+#endif
+	g_ptr_array_remove_fast(vhffsfs.quotacachekeys, GINT_TO_POINTER(vcq->gid));
+	g_hash_table_remove(vhffsfs.quotacacheused, GINT_TO_POINTER(vcq->gid));
+	free(vcq->dq);
+	free(vcq);
+	vhffsfs_checkquota_cache_unlock();
+}
+
+struct dqblk *vhffsfs_checkquota_cache_lookup(gid_t gid)  {
+	vhffsfs_checkquota_cache_lock();
+	vhffsfs_cache_quota *vcq = g_hash_table_lookup(vhffsfs.quotacacheused, GINT_TO_POINTER(gid));
+	if(vcq) {
+		// timeout
+		if(vhffsfs_cache_timeout(vcq->arrival, VHFFSFS_CHECKQUOTA_CACHE_TIMEOUT)) {
+#ifdef WITH_CHECKQUOTA_CACHE_DEBUG
+			fprintf(stdout, "CACHE: TIMEOUT: %d\n", gid);
+#endif
+			vhffsfs_checkquota_cache_unlock();
+			vhffsfs_checkquota_cache_del(gid);
+			return NULL;
+		}
+		// cache hit
+#ifdef WITH_CHECKQUOTA_CACHE_DEBUG
+		fprintf(stdout, "CACHE: HIT: %d\n", gid);
+#endif
+		vcq->ref++;
+		vhffsfs_checkquota_cache_unlock();
+		return vcq->dq;
+	}
+	// cache miss
+#ifdef WITH_CHECKQUOTA_CACHE_DEBUG
+	fprintf(stdout, "CACHE: MISS: %d\n", gid);
+#endif
+	vhffsfs_checkquota_cache_unlock();
+	return NULL;
+}
+
+void vhffsfs_checkquota_cache_unref(gid_t gid)  {
+	vhffsfs_checkquota_cache_lock();
+	vhffsfs_cache_quota *vcq = g_hash_table_lookup(vhffsfs.quotacacheused, GINT_TO_POINTER(gid));
+	if(vcq && vcq->ref > 0) vcq->ref--;
+	else {
+		if(!vcq) fprintf(stderr, "CACHE: CORRUPT: '%d': NOT IN TABLE\n", gid);
+		else fprintf(stderr, "CACHE: CORRUPT: '%d': REF IS ALREADY SET TO 0\n", gid);
+	}
+	vhffsfs_checkquota_cache_unlock();
+}
+
+
+static void *vhffsfs_checkquota_cache_flush(void *data_)
+{
+	(void) data_;
+
+	while(1) {
+		GPtrArray *keys;
+		int i;
+
+		sleep(VHFFSFS_CHECKQUOTA_CACHE_REFRESH);
+
+		keys = g_ptr_array_sized_new(4096);
+
+		//printf("FLUSH CACHE\n");
+
+		// copy keys
+		vhffsfs_checkquota_cache_lock();
+		for(i = 0 ; i < vhffsfs.quotacachekeys->len ; i++)  {
+			g_ptr_array_add(keys, vhffsfs.quotacachekeys->pdata[i]);
+		}
+		vhffsfs_checkquota_cache_unlock();
+
+		// sleep a bit to not lock the cache too much
+		sleep(1);
+
+		for(i = 0 ; i < keys->len ; i++)  {
+			gid_t gid = GPOINTER_TO_INT(keys->pdata[i]);
+			vhffsfs_cache_quota *vcq;
+
+			vhffsfs_checkquota_cache_lock();
+			vcq = g_hash_table_lookup(vhffsfs.quotacacheused, GINT_TO_POINTER(gid));
+			if(vcq && vhffsfs_cache_timeout(vcq->arrival, VHFFSFS_CHECKQUOTA_CACHE_TIMEOUT))  {
+#ifdef WITH_CHECKQUOTA_CACHE_DEBUG
+				fprintf(stdout, "CACHE: TIMEOUT: %d\n", gid);
+#endif
+				vhffsfs_checkquota_cache_unlock();
+				vhffsfs_checkquota_cache_del(gid);
+			}
+			else vhffsfs_checkquota_cache_unlock();
+
+			//sleep a bit to not lock the cache too much
+			usleep(100000);
+		}
+
+		g_ptr_array_free(keys, TRUE);
+	}
+	return NULL;
+}
+
+
+static int vhffsfs_checkquota_start_cache_flush_thread(void)
+{
+	int err;
+	pthread_t thread_id;
+	sigset_t oldset;
+	sigset_t newset;
+
+	if(vhffsfs.quotacachethreadstarted) return 0;
+
+	sigemptyset(&newset);
+	sigaddset(&newset, SIGTERM);
+	sigaddset(&newset, SIGINT);
+	sigaddset(&newset, SIGHUP);
+	sigaddset(&newset, SIGQUIT);
+	pthread_sigmask(SIG_BLOCK, &newset, &oldset);
+	err = pthread_create(&thread_id, NULL, vhffsfs_checkquota_cache_flush, NULL);
+	if(err) {
+		fprintf(stderr, "Failed to create thread: %s\n", strerror(err));
+		return -EIO;
+	}
+	pthread_detach(thread_id);
+	pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+	vhffsfs.quotacachethreadstarted = 1;
 	return 0;
 }
+#endif
 
+
+/* return an allocated dqblk struct or NULL if something failed (errno is set) */
+struct dqblk *vhffsfs_checkquotagid_blockdev(char *blockdev, int gid)  {
+
+	struct dqblk *dq;
+	if(!blockdev || !gid)  {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	dq = malloc(sizeof(struct dqblk));
+	if( quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), blockdev, gid, (caddr_t)dq) ) {
+		free(dq);
+		return NULL;
+	}
+	dq.dqb_curspace >>= 10;
+	return dq;
+}
+
+
 #ifdef WITH_CHECKQUOTA_RPC
-/* return 0 if the gid is not over quota */
+/* return an allocated dqblk struct or NULL if something failed (errno is set) */
 int vhffsfs_checkquotagid_rpc(char *rpcserver, char *path, int gid)  {
 
 	CLIENT *clnt;
+	struct dqblk *dq;
 
-	if(!rpcserver || !path || !gid)  return -EINVAL;
+	if(!rpcserver || !path || !gid)  {
+		errno = EINVAL;
+		return NULL;
+	}
 
 	if( (clnt = clnt_create(rpcserver, RQUOTAPROG, EXT_RQUOTAVERS, "udp"))  !=  NULL)  {
 
@@ -797,27 +987,41 @@
 		if(res == RPC_SUCCESS && clnt_res.status == Q_OK)  {
 
 			struct rquota *n = &clnt_res.getquota_rslt_u.gqr_rquota;
-			if(!n)  return -EIO;
+			if(!n) {
+				errno = EIO;
+				return NULL;
+			}
 
 			/* printf("QUOTA -> GID: %d, HARDB: %d, SOFTB: %d, CURB: %d\n", gid, n->rq_bhardlimit, n->rq_bsoftlimit, n->rq_curblocks );
 			 * printf("QUOTA -> GID: %d, HARDF: %d, SOFTF: %d, CURF: %d\n", gid, n->rq_fhardlimit, n->rq_fsoftlimit, n->rq_curfiles );
 			 */
 
-			if(n->rq_curblocks > n->rq_bhardlimit  ||  n->rq_curfiles > n->rq_fhardlimit)  return 1;
-	
-			/* printf("QUOTA -> OK !\n"); */
+			dq = malloc(sizeof(struct dqblk));
+			dq->dqb_bhardlimit = n->rq_bhardlimit;
+			dq->dqb_bsoftlimit = n->rq_bsoftlimit;
+			dq->dqb_curspace = n->rq_curblocks;
+			dq->dqb_ihardlimit = n->rq_fhardlimit;
+			dq->dqb_isoftlimit = n->rq_fsoftlimit;
+			dq->dqb_curinodes = n->rq_curfiles;
+			dq->dqb_btime = n->rq_btimeleft;
+			dq->dqb_itime = n->rq_ftimeleft;
+			dq->dqb_valid = 0;
+			return dq;
 		}
-		else return -EIO;
+
+		errno = EIO;
+		return NULL;
 	}
-	else return -EIO;
-	return 0;
+
+	errno = EIO;
+	return NULL;
 }
 #endif
 
 /* return 0 if the gid is not over quota, 1 if over quota, -errno in case of error */
 int vhffsfs_checkquota_gid_with_realpath(char *realpath, int gid)  {
 	int mode = 0;  /* 0 = do nothing, 1 = data, 2 = repository */
-	int res = 0;
+	struct dqblk *dq = NULL;
 
 	if(!realpath) return -EINVAL;
 	if(!vhffsfs.dataprefixpath) return 0;
@@ -844,41 +1048,36 @@
 		}
 	}
 
-	/*
-	printf("DAIBEUG, realpath = %s\n", realpath);
-	printf("DAIBEUG, dataprefixpath = %s\n", vhffsfs.dataprefixpath);
-	printf("DAIBEUG, repositoriesprefixpath = %s\n", vhffsfs.repositoriesprefixpath);
-	printf("DAIBEUG, mode = %d\n", mode);
-	*/
-
 	/* data */
 	if(mode == 1)  {
 		if(vhffsfs.datablockdev)  {
-			res = vhffsfs_checkquotagid_blockdev(vhffsfs.datablockdev, gid);
+			dq = vhffsfs_checkquotagid_blockdev(vhffsfs.datablockdev, gid);
 		}
 #ifdef WITH_CHECKQUOTA_RPC
 		else if(vhffsfs.datarpcserver && vhffsfs.datarpcpath)  {
-			res = vhffsfs_checkquotagid_rpc(vhffsfs.datarpcserver, vhffsfs.datarpcpath, gid);
+			dq = vhffsfs_checkquotagid_rpc(vhffsfs.datarpcserver, vhffsfs.datarpcpath, gid);
 		}
 #endif
 	}
 	/* repository */
 	else if(mode == 2 )  {
 		if(vhffsfs.repositoriesblockdev)  {
-			res = vhffsfs_checkquotagid_blockdev(vhffsfs.repositoriesblockdev, gid);
+			dq = vhffsfs_checkquotagid_blockdev(vhffsfs.repositoriesblockdev, gid);
 		}
 #ifdef WITH_CHECKQUOTA_RPC
 		else if(vhffsfs.repositoriesrpcserver && vhffsfs.repositoriesrpcpath)  {
-			res = vhffsfs_checkquotagid_rpc(vhffsfs.repositoriesrpcserver, vhffsfs.repositoriesrpcpath, gid);
+			dq = vhffsfs_checkquotagid_rpc(vhffsfs.repositoriesrpcserver, vhffsfs.repositoriesrpcpath, gid);
 		}
 #endif		
 	}
 
-	if(res < 0)  {
-		printf("vhffsfs: quota: %s\n", strerror(-res));
-		res = 0;
+	if(!dq) {
+		printf("vhffsfs: quota: %s\n", strerror(errno));
+		return 0;
 	}
-	return res;
+
+	if(dq.dqb_curspace > dq.dqb_bhardlimit  ||  dq.dqb_curinodes > dq.dqb_ihardlimit)  return 1;
+	return 0;
 }
 #endif
 
@@ -889,6 +1088,10 @@
 	// create cache flush thread
 	vhffsfs_start_cache_flush_thread();
 #endif
+#ifdef WITH_CHECKQUOTA_CACHE
+	// create cache flush thread for quota
+	vhffsfs_checkquota_start_cache_flush_thread();
+#endif
 	return NULL;
 }
 
@@ -1648,7 +1851,12 @@
 	pthread_mutex_init(&vhffsfs.cachelock, NULL);
 	vhffsfs.cachethreadstarted = 0;
 #endif
-
+#ifdef WITH_CHECKQUOTA_CACHE
+	vhffsfs.quotacacheused = g_hash_table_new(g_int_hash, g_int_equal);
+	vhffsfs.quotacachekeys = g_ptr_array_sized_new(4096);
+	pthread_mutex_init(&vhffsfs.quotacachelock, NULL);
+	vhffsfs.quotacachethreadstarted = 0;
+#endif
 	vhffsfs_readconfig(VHFFSFS_CONFIG);
 
 	// generate dbconninfo


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/