summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h10
-rw-r--r--source3/param/loadparm.c13
-rw-r--r--source3/smbd/dfree.c63
-rw-r--r--source3/smbd/vfs-wrap.c2
4 files changed, 72 insertions, 16 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index e3d151f9ed..6511f10365 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -508,6 +508,14 @@ typedef struct
#include "smb_acls.h"
#include "vfs.h"
+struct dfree_cached_info {
+ time_t last_dfree_time;
+ SMB_BIG_UINT dfree_ret;
+ SMB_BIG_UINT bsize;
+ SMB_BIG_UINT dfree;
+ SMB_BIG_UINT dsize;
+};
+
struct dptr_struct;
typedef struct connection_struct
@@ -559,7 +567,7 @@ typedef struct connection_struct
name_compare_entry *veto_list; /* Per-share list of files to veto (never show). */
name_compare_entry *veto_oplock_list; /* Per-share list of files to refuse oplocks on. */
name_compare_entry *aio_write_behind_list; /* Per-share list of files to use aio write behind on. */
-
+ struct dfree_cached_info *dfree_info;
} connection_struct;
struct current_user
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index d99336ea97..cecd1d0f98 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -109,7 +109,6 @@ typedef struct
char *szPidDir;
char *szRootdir;
char *szDefaultService;
- char *szDfree;
char *szGetQuota;
char *szSetQuota;
char *szMsgCommand;
@@ -358,6 +357,7 @@ typedef struct
char **szVfsObjects;
char *szMSDfsProxy;
char *szAioWriteBehind;
+ char *szDfree;
int iMinPrintSpace;
int iMaxPrintJobs;
int iMaxReportedPrintJobs;
@@ -376,6 +376,7 @@ typedef struct
int iOplockContentionLimit;
int iCSCPolicy;
int iBlock_size;
+ int iDfreeCacheTime;
BOOL bPreexecClose;
BOOL bRootpreexecClose;
int iCaseSensitive;
@@ -492,6 +493,7 @@ static service sDefault = {
NULL, /* vfs objects */
NULL, /* szMSDfsProxy */
NULL, /* szAioWriteBehind */
+ NULL, /* szDfree */
0, /* iMinPrintSpace */
1000, /* iMaxPrintJobs */
0, /* iMaxReportedPrintJobs */
@@ -509,7 +511,8 @@ static service sDefault = {
DEFAULT_PRINTING, /* iPrinting */
2, /* iOplockContentionLimit */
0, /* iCSCPolicy */
- 1024, /* iBlock_size */
+ 1024, /* iBlock_size */
+ 0, /* iDfreeCacheTime */
False, /* bPreexecClose */
False, /* bRootpreexecClose */
Auto, /* case sensitive */
@@ -1180,7 +1183,8 @@ static struct parm_struct parm_table[] = {
{"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED},
{"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED},
{"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED},
- {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, FLAG_ADVANCED},
+ {"dfree cache time", P_STRING, P_LOCAL, &sDefault.iDfreeCacheTime, NULL, NULL, FLAG_ADVANCED},
+ {"dfree command", P_STRING, P_LOCAL, &sDefault.szDfree, NULL, NULL, FLAG_ADVANCED},
{"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED},
{"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, NULL, NULL, FLAG_ADVANCED},
{"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED},
@@ -1721,7 +1725,6 @@ FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
-FN_GLOBAL_STRING(lp_dfree_command, &Globals.szDfree)
FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
@@ -1933,6 +1936,7 @@ FN_LOCAL_STRING(lp_hide_files, szHideFiles)
FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
+FN_LOCAL_STRING(lp_dfree_command, szDfree)
FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
@@ -2007,6 +2011,7 @@ FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
+FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index 81a48b94fc..dad7d917e8 100644
--- a/source3/smbd/dfree.c
+++ b/source3/smbd/dfree.c
@@ -21,8 +21,9 @@
#include "includes.h"
/****************************************************************************
-normalise for DOS usage
+ Normalise for DOS usage.
****************************************************************************/
+
static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
{
/* check if the disk is beyond the max disk size */
@@ -59,17 +60,17 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,
/****************************************************************************
- return number of 1K blocks available on a path and total number
+ Return number of 1K blocks available on a path and total number.
****************************************************************************/
-static SMB_BIG_UINT disk_free(const char *path, BOOL small_query,
+SMB_BIG_UINT sys_disk_free(connection_struct *conn, const char *path, BOOL small_query,
SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
{
int dfree_retval;
SMB_BIG_UINT dfree_q = 0;
SMB_BIG_UINT bsize_q = 0;
SMB_BIG_UINT dsize_q = 0;
- char *dfree_command;
+ const char *dfree_command;
(*dfree) = (*dsize) = 0;
(*bsize) = 512;
@@ -78,7 +79,7 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query,
* If external disk calculation specified, use it.
*/
- dfree_command = lp_dfree_command();
+ dfree_command = lp_dfree_command(SNUM(conn));
if (dfree_command && *dfree_command) {
const char *p;
char **lines;
@@ -162,12 +163,54 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query,
return(dfree_retval);
}
-
/****************************************************************************
-wrap it to get filenames right
+ Potentially returned cached dfree info.
****************************************************************************/
-SMB_BIG_UINT sys_disk_free(const char *path, BOOL small_query,
- SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
+
+SMB_BIG_UINT get_dfree_info(connection_struct *conn,
+ const char *path,
+ BOOL small_query,
+ SMB_BIG_UINT *bsize,
+ SMB_BIG_UINT *dfree,
+ SMB_BIG_UINT *dsize)
{
- return disk_free(path,small_query, bsize,dfree,dsize);
+ int dfree_cache_time = lp_dfree_cache_time(SNUM(conn));
+ struct dfree_cached_info *dfc = conn->dfree_info;
+ SMB_BIG_UINT dfree_ret;
+
+ if (!dfree_cache_time) {
+ return SMB_VFS_DISK_FREE(conn,path,small_query,bsize,dfree,dsize);
+ }
+
+ if (dfc && (conn->lastused - dfc->last_dfree_time < dfree_cache_time)) {
+ /* Return cached info. */
+ *bsize = dfc->bsize;
+ *dfree = dfc->dfree;
+ *dsize = dfc->dsize;
+ return dfc->dfree_ret;
+ }
+
+ dfree_ret = SMB_VFS_DISK_FREE(conn,path,small_query,bsize,dfree,dsize);
+
+ if (dfree_ret == (SMB_BIG_UINT)-1) {
+ /* Don't cache bad data. */
+ return dfree_ret;
+ }
+
+ /* No cached info or time to refresh. */
+ if (!dfc) {
+ dfc = TALLOC_P(conn->mem_ctx, struct dfree_cached_info);
+ if (!dfc) {
+ return dfree_ret;
+ }
+ conn->dfree_info = dfc;
+ }
+
+ dfc->bsize = *bsize;
+ dfc->dfree = *dfree;
+ dfc->dsize = *dsize;
+ dfc->dfree_ret = dfree_ret;
+ dfc->last_dfree_time = conn->lastused;
+
+ return dfree_ret;
}
diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c
index 9ae1592a8e..c203af0c55 100644
--- a/source3/smbd/vfs-wrap.c
+++ b/source3/smbd/vfs-wrap.c
@@ -46,7 +46,7 @@ SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *con
{
SMB_BIG_UINT result;
- result = sys_disk_free(path, small_query, bsize, dfree, dsize);
+ result = sys_disk_free(conn, path, small_query, bsize, dfree, dsize);
return result;
}