Index: smbd/vfs-wrap.c =================================================================== --- smbd/vfs-wrap.c (revision 11187) +++ smbd/vfs-wrap.c (working copy) @@ -46,7 +46,7 @@ { 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; } Index: smbd/dfree.c =================================================================== --- smbd/dfree.c (revision 11187) +++ smbd/dfree.c (working copy) @@ -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 @@ /**************************************************************************** - 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 @@ * 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 @@ 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; } Index: param/loadparm.c =================================================================== --- param/loadparm.c (revision 11187) +++ param/loadparm.c (working copy) @@ -109,7 +109,6 @@ char *szPidDir; char *szRootdir; char *szDefaultService; - char *szDfree; char *szGetQuota; char *szSetQuota; char *szMsgCommand; @@ -358,6 +357,7 @@ char **szVfsObjects; char *szMSDfsProxy; char *szAioWriteBehind; + char *szDfree; int iMinPrintSpace; int iMaxPrintJobs; int iMaxReportedPrintJobs; @@ -376,6 +376,7 @@ int iOplockContentionLimit; int iCSCPolicy; int iBlock_size; + int iDfreeCacheTime; BOOL bPreexecClose; BOOL bRootpreexecClose; int iCaseSensitive; @@ -492,6 +493,7 @@ NULL, /* vfs objects */ NULL, /* szMSDfsProxy */ NULL, /* szAioWriteBehind */ + NULL, /* szDfree */ 0, /* iMinPrintSpace */ 1000, /* iMaxPrintJobs */ 0, /* iMaxReportedPrintJobs */ @@ -509,7 +511,8 @@ 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 @@ {"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_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_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_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) Index: include/smb.h =================================================================== --- include/smb.h (revision 11187) +++ include/smb.h (working copy) @@ -508,6 +508,14 @@ #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 @@ 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