mirror of
https://github.com/samba-team/samba.git
synced 2025-06-19 23:17:05 +03:00
smbd: get a valid file stat to disk_quotas
Most calls to disk_quotas originate at a state with an open file descriptor. Pass the file's stat info down to disk_quota, so that we can avoid extra stat's and the related error handling. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12145 Signed-off-by: Uri Simchoni <uri@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
3e6ea02d42
commit
bd2ec88dca
@ -847,9 +847,8 @@ static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_str
|
|||||||
"error %d. Falling back to slow manual allocation\n", errno));
|
"error %d. Falling back to slow manual allocation\n", errno));
|
||||||
|
|
||||||
/* available disk space is enough or not? */
|
/* available disk space is enough or not? */
|
||||||
space_avail = get_dfree_info(fsp->conn,
|
space_avail =
|
||||||
fsp->fsp_name->base_name,
|
get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
|
||||||
&bsize, &dfree, &dsize);
|
|
||||||
/* space_avail is 1k blocks */
|
/* space_avail is 1k blocks */
|
||||||
if (space_avail == (uint64_t)-1 ||
|
if (space_avail == (uint64_t)-1 ||
|
||||||
((uint64_t)space_to_write/1024 > space_avail) ) {
|
((uint64_t)space_to_write/1024 > space_avail) ) {
|
||||||
|
@ -1978,9 +1978,8 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
|
|||||||
"error %d. Falling back to slow manual allocation\n", errno));
|
"error %d. Falling back to slow manual allocation\n", errno));
|
||||||
|
|
||||||
/* available disk space is enough or not? */
|
/* available disk space is enough or not? */
|
||||||
space_avail = get_dfree_info(fsp->conn,
|
space_avail =
|
||||||
fsp->fsp_name->base_name,
|
get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
|
||||||
&bsize, &dfree, &dsize);
|
|
||||||
/* space_avail is 1k blocks */
|
/* space_avail is 1k blocks */
|
||||||
if (space_avail == (uint64_t)-1 ||
|
if (space_avail == (uint64_t)-1 ||
|
||||||
((uint64_t)space_to_write/1024 > space_avail) ) {
|
((uint64_t)space_to_write/1024 > space_avail) ) {
|
||||||
|
@ -50,7 +50,7 @@ static void disk_norm(uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
|||||||
Return number of 1K blocks available on a path and total number.
|
Return number of 1K blocks available on a path and total number.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint64_t sys_disk_free(connection_struct *conn, const char *path,
|
uint64_t sys_disk_free(connection_struct *conn, struct smb_filename *fname,
|
||||||
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
||||||
{
|
{
|
||||||
uint64_t dfree_retval;
|
uint64_t dfree_retval;
|
||||||
@ -59,6 +59,7 @@ uint64_t sys_disk_free(connection_struct *conn, const char *path,
|
|||||||
uint64_t dsize_q = 0;
|
uint64_t dsize_q = 0;
|
||||||
const char *dfree_command;
|
const char *dfree_command;
|
||||||
static bool dfree_broken = false;
|
static bool dfree_broken = false;
|
||||||
|
const char *path = fname->base_name;
|
||||||
|
|
||||||
(*dfree) = (*dsize) = 0;
|
(*dfree) = (*dsize) = 0;
|
||||||
(*bsize) = 512;
|
(*bsize) = 512;
|
||||||
@ -124,7 +125,7 @@ uint64_t sys_disk_free(connection_struct *conn, const char *path,
|
|||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disk_quotas(conn, path, &bsize_q, &dfree_q, &dsize_q)) {
|
if (disk_quotas(conn, fname, &bsize_q, &dfree_q, &dsize_q)) {
|
||||||
uint64_t min_bsize = MIN(*bsize, bsize_q);
|
uint64_t min_bsize = MIN(*bsize, bsize_q);
|
||||||
|
|
||||||
(*dfree) = (*dfree) * (*bsize) / min_bsize;
|
(*dfree) = (*dfree) * (*bsize) / min_bsize;
|
||||||
@ -168,18 +169,15 @@ dfree_done:
|
|||||||
Potentially returned cached dfree info.
|
Potentially returned cached dfree info.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint64_t get_dfree_info(connection_struct *conn,
|
uint64_t get_dfree_info(connection_struct *conn, struct smb_filename *fname,
|
||||||
const char *path,
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
||||||
uint64_t *bsize,
|
|
||||||
uint64_t *dfree,
|
|
||||||
uint64_t *dsize)
|
|
||||||
{
|
{
|
||||||
int dfree_cache_time = lp_dfree_cache_time(SNUM(conn));
|
int dfree_cache_time = lp_dfree_cache_time(SNUM(conn));
|
||||||
struct dfree_cached_info *dfc = conn->dfree_info;
|
struct dfree_cached_info *dfc = conn->dfree_info;
|
||||||
uint64_t dfree_ret;
|
uint64_t dfree_ret;
|
||||||
|
|
||||||
if (!dfree_cache_time) {
|
if (!dfree_cache_time) {
|
||||||
return sys_disk_free(conn, path, bsize, dfree, dsize);
|
return sys_disk_free(conn, fname, bsize, dfree, dsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dfc && (conn->lastused - dfc->last_dfree_time < dfree_cache_time)) {
|
if (dfc && (conn->lastused - dfc->last_dfree_time < dfree_cache_time)) {
|
||||||
@ -190,7 +188,7 @@ uint64_t get_dfree_info(connection_struct *conn,
|
|||||||
return dfc->dfree_ret;
|
return dfc->dfree_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
dfree_ret = sys_disk_free(conn, path, bsize, dfree, dsize);
|
dfree_ret = sys_disk_free(conn, fname, bsize, dfree, dsize);
|
||||||
|
|
||||||
if (dfree_ret == (uint64_t)-1) {
|
if (dfree_ret == (uint64_t)-1) {
|
||||||
/* Don't cache bad data. */
|
/* Don't cache bad data. */
|
||||||
|
@ -172,13 +172,10 @@ bool connections_snum_used(struct smbd_server_connection *unused, int snum);
|
|||||||
|
|
||||||
/* The following definitions come from smbd/dfree.c */
|
/* The following definitions come from smbd/dfree.c */
|
||||||
|
|
||||||
uint64_t sys_disk_free(connection_struct *conn, const char *path,
|
uint64_t sys_disk_free(connection_struct *conn, struct smb_filename *fname,
|
||||||
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
|
||||||
|
uint64_t get_dfree_info(connection_struct *conn, struct smb_filename *fname,
|
||||||
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
|
||||||
uint64_t get_dfree_info(connection_struct *conn,
|
|
||||||
const char *path,
|
|
||||||
uint64_t *bsize,
|
|
||||||
uint64_t *dfree,
|
|
||||||
uint64_t *dsize);
|
|
||||||
|
|
||||||
/* The following definitions come from smbd/dir.c */
|
/* The following definitions come from smbd/dir.c */
|
||||||
|
|
||||||
@ -855,8 +852,8 @@ bool fork_echo_handler(struct smbXsrv_connection *xconn);
|
|||||||
|
|
||||||
/* The following definitions come from smbd/quotas.c */
|
/* The following definitions come from smbd/quotas.c */
|
||||||
|
|
||||||
bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
|
||||||
uint64_t *dfree, uint64_t *dsize);
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
|
||||||
|
|
||||||
/* The following definitions come from smbd/reply.c */
|
/* The following definitions come from smbd/reply.c */
|
||||||
|
|
||||||
|
@ -216,8 +216,8 @@ try to get the disk space from disk quotas (SunOS & Solaris2 version)
|
|||||||
Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
|
Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
|
||||||
uint64_t *dfree, uint64_t *dsize)
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
||||||
{
|
{
|
||||||
uid_t euser_id;
|
uid_t euser_id;
|
||||||
int ret;
|
int ret;
|
||||||
@ -230,14 +230,11 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
|||||||
SMB_STRUCT_STAT sbuf;
|
SMB_STRUCT_STAT sbuf;
|
||||||
SMB_DEV_T devno;
|
SMB_DEV_T devno;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
const char *path = fname->base_name;
|
||||||
|
|
||||||
euser_id = geteuid();
|
euser_id = geteuid();
|
||||||
|
|
||||||
if (sys_stat(path, &sbuf, false) == -1) {
|
devno = fname->st.st_ex_dev;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
devno = sbuf.st_ex_dev ;
|
|
||||||
DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
|
DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
|
||||||
path, (unsigned int)devno));
|
path, (unsigned int)devno));
|
||||||
if ((fd = fopen(MNTTAB, "r")) == NULL) {
|
if ((fd = fopen(MNTTAB, "r")) == NULL) {
|
||||||
@ -362,15 +359,16 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
|||||||
try to get the disk space from disk quotas - default version
|
try to get the disk space from disk quotas - default version
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
|
||||||
uint64_t *dfree, uint64_t *dsize)
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct dqblk D;
|
struct dqblk D;
|
||||||
uid_t euser_id;
|
uid_t euser_id;
|
||||||
|
const char *path = fname->base_name;
|
||||||
#if !defined(AIX)
|
#if !defined(AIX)
|
||||||
char dev_disk[256];
|
char dev_disk[256];
|
||||||
SMB_STRUCT_STAT S;
|
SMB_STRUCT_STAT S = fname->st;
|
||||||
|
|
||||||
/* find the block device file */
|
/* find the block device file */
|
||||||
|
|
||||||
@ -463,8 +461,8 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
|||||||
|
|
||||||
#else /* WITH_QUOTAS */
|
#else /* WITH_QUOTAS */
|
||||||
|
|
||||||
bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
|
||||||
uint64_t *dfree, uint64_t *dsize)
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
||||||
{
|
{
|
||||||
(*bsize) = 512; /* This value should be ignored */
|
(*bsize) = 512; /* This value should be ignored */
|
||||||
|
|
||||||
@ -482,8 +480,8 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
|||||||
/* wrapper to the new sys_quota interface
|
/* wrapper to the new sys_quota interface
|
||||||
this file should be removed later
|
this file should be removed later
|
||||||
*/
|
*/
|
||||||
bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
|
||||||
uint64_t *dfree, uint64_t *dsize)
|
uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
SMB_DISK_QUOTA D;
|
SMB_DISK_QUOTA D;
|
||||||
@ -496,7 +494,8 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
|||||||
*/
|
*/
|
||||||
ZERO_STRUCT(D);
|
ZERO_STRUCT(D);
|
||||||
id.uid = -1;
|
id.uid = -1;
|
||||||
r = SMB_VFS_GET_QUOTA(conn, path, SMB_USER_FS_QUOTA_TYPE, id, &D);
|
r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_USER_FS_QUOTA_TYPE,
|
||||||
|
id, &D);
|
||||||
if (r == -1 && errno != ENOSYS) {
|
if (r == -1 && errno != ENOSYS) {
|
||||||
goto try_group_quota;
|
goto try_group_quota;
|
||||||
}
|
}
|
||||||
@ -507,7 +506,8 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
|
|||||||
ZERO_STRUCT(D);
|
ZERO_STRUCT(D);
|
||||||
id.uid = geteuid();
|
id.uid = geteuid();
|
||||||
|
|
||||||
r = SMB_VFS_GET_QUOTA(conn, path, SMB_USER_QUOTA_TYPE, id, &D);
|
r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_USER_QUOTA_TYPE, id,
|
||||||
|
&D);
|
||||||
|
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
goto try_group_quota;
|
goto try_group_quota;
|
||||||
@ -543,7 +543,8 @@ try_group_quota:
|
|||||||
*/
|
*/
|
||||||
ZERO_STRUCT(D);
|
ZERO_STRUCT(D);
|
||||||
id.gid = -1;
|
id.gid = -1;
|
||||||
r = SMB_VFS_GET_QUOTA(conn, path, SMB_GROUP_FS_QUOTA_TYPE, id, &D);
|
r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_GROUP_FS_QUOTA_TYPE,
|
||||||
|
id, &D);
|
||||||
if (r == -1 && errno != ENOSYS) {
|
if (r == -1 && errno != ENOSYS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -554,7 +555,8 @@ try_group_quota:
|
|||||||
id.gid = getegid();
|
id.gid = getegid();
|
||||||
|
|
||||||
ZERO_STRUCT(D);
|
ZERO_STRUCT(D);
|
||||||
r = SMB_VFS_GET_QUOTA(conn, path, SMB_GROUP_QUOTA_TYPE, id, &D);
|
r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_GROUP_QUOTA_TYPE, id,
|
||||||
|
&D);
|
||||||
|
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
return False;
|
return False;
|
||||||
|
@ -1573,9 +1573,20 @@ void reply_dskattr(struct smb_request *req)
|
|||||||
connection_struct *conn = req->conn;
|
connection_struct *conn = req->conn;
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
uint64_t dfree,dsize,bsize;
|
uint64_t dfree,dsize,bsize;
|
||||||
|
struct smb_filename smb_fname;
|
||||||
START_PROFILE(SMBdskattr);
|
START_PROFILE(SMBdskattr);
|
||||||
|
|
||||||
ret = get_dfree_info(conn, ".", &bsize, &dfree, &dsize);
|
ZERO_STRUCT(smb_fname);
|
||||||
|
smb_fname.base_name = discard_const_p(char, ".");
|
||||||
|
|
||||||
|
if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
|
||||||
|
reply_nterror(req, map_nt_error_from_unix(errno));
|
||||||
|
DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
|
||||||
|
END_PROFILE(SMBdskattr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
|
||||||
if (ret == (uint64_t)-1) {
|
if (ret == (uint64_t)-1) {
|
||||||
reply_nterror(req, map_nt_error_from_unix(errno));
|
reply_nterror(req, map_nt_error_from_unix(errno));
|
||||||
END_PROFILE(SMBdskattr);
|
END_PROFILE(SMBdskattr);
|
||||||
|
@ -3438,8 +3438,8 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
|
|||||||
{
|
{
|
||||||
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
|
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
|
||||||
data_len = 18;
|
data_len = 18;
|
||||||
df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
|
df_ret = get_dfree_info(conn, &smb_fname, &bsize,
|
||||||
&dsize);
|
&dfree, &dsize);
|
||||||
if (df_ret == (uint64_t)-1) {
|
if (df_ret == (uint64_t)-1) {
|
||||||
return map_nt_error_from_unix(errno);
|
return map_nt_error_from_unix(errno);
|
||||||
}
|
}
|
||||||
@ -3589,8 +3589,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
|
|||||||
{
|
{
|
||||||
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
|
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
|
||||||
data_len = 24;
|
data_len = 24;
|
||||||
df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
|
df_ret = get_dfree_info(conn, &smb_fname, &bsize,
|
||||||
&dsize);
|
&dfree, &dsize);
|
||||||
if (df_ret == (uint64_t)-1) {
|
if (df_ret == (uint64_t)-1) {
|
||||||
return map_nt_error_from_unix(errno);
|
return map_nt_error_from_unix(errno);
|
||||||
}
|
}
|
||||||
@ -3623,8 +3623,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
|
|||||||
{
|
{
|
||||||
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
|
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
|
||||||
data_len = 32;
|
data_len = 32;
|
||||||
df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
|
df_ret = get_dfree_info(conn, &smb_fname, &bsize,
|
||||||
&dsize);
|
&dfree, &dsize);
|
||||||
if (df_ret == (uint64_t)-1) {
|
if (df_ret == (uint64_t)-1) {
|
||||||
return map_nt_error_from_unix(errno);
|
return map_nt_error_from_unix(errno);
|
||||||
}
|
}
|
||||||
|
@ -623,8 +623,8 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
|
|||||||
|
|
||||||
len -= fsp->fsp_name->st.st_ex_size;
|
len -= fsp->fsp_name->st.st_ex_size;
|
||||||
len /= 1024; /* Len is now number of 1k blocks needed. */
|
len /= 1024; /* Len is now number of 1k blocks needed. */
|
||||||
space_avail = get_dfree_info(conn, fsp->fsp_name->base_name,
|
space_avail =
|
||||||
&bsize, &dfree, &dsize);
|
get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
|
||||||
if (space_avail == (uint64_t)-1) {
|
if (space_avail == (uint64_t)-1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user