diff options
-rw-r--r-- | source3/include/smb.h | 10 | ||||
-rw-r--r-- | source3/param/loadparm.c | 13 | ||||
-rw-r--r-- | source3/smbd/dfree.c | 63 | ||||
-rw-r--r-- | source3/smbd/vfs-wrap.c | 2 |
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; } |