[PATCH] correct dfree reporting when inherit owner is enabled

Jeremy Allison jra at samba.org
Fri Aug 12 22:42:18 UTC 2016


On Fri, Aug 12, 2016 at 04:49:02PM +0300, Uri Simchoni wrote:
> Hi,
> 
> The following patch set corrects the free disk reporting when "inherit
> owner" is enabled.
> 
> In SMB2, the GETINFO_FS query is made relative to a path. That means
> that different results as to disk size and free space can be returned,
> depending on the path.
> 
> When "inherit owner" is enabled, new files get the owner of the parent
> directory's owner, and hence consume that owner's quota. Therefore the
> relevant quota for the free disk calculation is the quota of the
> directory owner.
> 
> I once submitted this to the list as a new feature with a new parameter,
> but I think this is actually the correct behavior generally, and can be
> filed as a bugfix.
> 
> Review appreciated,
> Uri.

Wow. Impressive cleanup - great work Uri ! Reviewed-by: Jeremy Allison <jra at samba.org>.

I'll push as soon as my existing autobuild finishes (or feel free to
push yourself) !

> From f28e0759c90abfdafce555cec916a8b4967d0285 Mon Sep 17 00:00:00 2001
> From: Uri Simchoni <uri at samba.org>
> Date: Wed, 27 Jan 2016 08:12:20 +0200
> Subject: [PATCH 1/5] quotas: small cleanup
> 
> Remove an internal function from proto.h
> 
> Signed-off-by: Uri Simchoni <uri at samba.org>
> ---
>  source3/smbd/proto.h | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
> index 26fec95..162dbe4 100644
> --- a/source3/smbd/proto.h
> +++ b/source3/smbd/proto.h
> @@ -856,7 +856,6 @@ bool fork_echo_handler(struct smbXsrv_connection *xconn);
>  
>  bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
>  		 uint64_t *dfree, uint64_t *dsize);
> -bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
>  
>  /* The following definitions come from smbd/reply.c  */
>  
> -- 
> 2.5.5
> 
> 
> From a35d00dacbceeb372b9e7132c61dff5c5d5d04a4 Mon Sep 17 00:00:00 2001
> From: Uri Simchoni <uri at samba.org>
> Date: Thu, 14 Jan 2016 00:09:36 +0200
> Subject: [PATCH 2/5] 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 at samba.org>
> ---
>  source3/modules/vfs_ceph.c    |  5 ++---
>  source3/modules/vfs_default.c |  5 ++---
>  source3/smbd/dfree.c          | 16 +++++++---------
>  source3/smbd/proto.h          | 15 ++++++---------
>  source3/smbd/quotas.c         | 38 ++++++++++++++++++++------------------
>  source3/smbd/reply.c          | 13 ++++++++++++-
>  source3/smbd/trans2.c         | 12 ++++++------
>  source3/smbd/vfs.c            |  4 ++--
>  8 files changed, 57 insertions(+), 51 deletions(-)
> 
> diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c
> index 8e11dab..59e9b9c 100644
> --- a/source3/modules/vfs_ceph.c
> +++ b/source3/modules/vfs_ceph.c
> @@ -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));
>  
>  	/* available disk space is enough or not? */
> -	space_avail = get_dfree_info(fsp->conn,
> -				     fsp->fsp_name->base_name,
> -				     &bsize, &dfree, &dsize);
> +	space_avail =
> +	    get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
>  	/* space_avail is 1k blocks */
>  	if (space_avail == (uint64_t)-1 ||
>  			((uint64_t)space_to_write/1024 > space_avail) ) {
> diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
> index de5a4a3..5227e95 100644
> --- a/source3/modules/vfs_default.c
> +++ b/source3/modules/vfs_default.c
> @@ -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));
>  
>  	/* available disk space is enough or not? */
> -	space_avail = get_dfree_info(fsp->conn,
> -				     fsp->fsp_name->base_name,
> -				     &bsize, &dfree, &dsize);
> +	space_avail =
> +	    get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
>  	/* space_avail is 1k blocks */
>  	if (space_avail == (uint64_t)-1 ||
>  			((uint64_t)space_to_write/1024 > space_avail) ) {
> diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
> index fc52e51..7e58daa 100644
> --- a/source3/smbd/dfree.c
> +++ b/source3/smbd/dfree.c
> @@ -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.
>  ****************************************************************************/
>  
> -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 dfree_retval;
> @@ -59,6 +59,7 @@ uint64_t sys_disk_free(connection_struct *conn, const char *path,
>  	uint64_t dsize_q = 0;
>  	const char *dfree_command;
>  	static bool dfree_broken = false;
> +	const char *path = fname->base_name;
>  
>  	(*dfree) = (*dsize) = 0;
>  	(*bsize) = 512;
> @@ -124,7 +125,7 @@ uint64_t sys_disk_free(connection_struct *conn, const char *path,
>  		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);
>  
>  		(*dfree) = (*dfree) * (*bsize) / min_bsize;
> @@ -168,18 +169,15 @@ dfree_done:
>   Potentially returned cached dfree info.
>  ****************************************************************************/
>  
> -uint64_t get_dfree_info(connection_struct *conn,
> -			const char *path,
> -			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)
>  {
>  	int dfree_cache_time = lp_dfree_cache_time(SNUM(conn));
>  	struct dfree_cached_info *dfc = conn->dfree_info;
>  	uint64_t dfree_ret;
>  
>  	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)) {
> @@ -190,7 +188,7 @@ uint64_t get_dfree_info(connection_struct *conn,
>  		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) {
>  		/* Don't cache bad data. */
> diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
> index 162dbe4..e591910 100644
> --- a/source3/smbd/proto.h
> +++ b/source3/smbd/proto.h
> @@ -172,13 +172,10 @@ bool connections_snum_used(struct smbd_server_connection *unused, int snum);
>  
>  /* The following definitions come from smbd/dfree.c  */
>  
> -uint64_t sys_disk_free(connection_struct *conn, const char *path,
> -                              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);
> +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);
>  
>  /* The following definitions come from smbd/dir.c  */
>  
> @@ -854,8 +851,8 @@ bool fork_echo_handler(struct smbXsrv_connection *xconn);
>  
>  /* The following definitions come from smbd/quotas.c  */
>  
> -bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
> -		 uint64_t *dfree, uint64_t *dsize);
> +bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
> +		 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
>  
>  /* The following definitions come from smbd/reply.c  */
>  
> diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c
> index 9d3b906..f3a727c 100644
> --- a/source3/smbd/quotas.c
> +++ b/source3/smbd/quotas.c
> @@ -216,8 +216,8 @@ try to get the disk space from disk quotas (SunOS & Solaris2 version)
>  Quota code by Peter Urbanec (amiga at cse.unsw.edu.au).
>  ****************************************************************************/
>  
> -bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
> -		 uint64_t *dfree, uint64_t *dsize)
> +bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
> +		 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
>  {
>  	uid_t euser_id;
>  	int ret;
> @@ -230,14 +230,11 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
>  	SMB_STRUCT_STAT sbuf;
>  	SMB_DEV_T devno;
>  	bool found = false;
> +	const char *path = fname->base_name;
>  
>  	euser_id = geteuid();
>  
> -	if (sys_stat(path, &sbuf, false) == -1) {
> -		return false;
> -	}
> -
> -	devno = sbuf.st_ex_dev ;
> +	devno = fname->st.st_ex_dev;
>  	DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
>  		path, (unsigned int)devno));
>  	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
>  ****************************************************************************/
>  
> -bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
> -		 uint64_t *dfree, uint64_t *dsize)
> +bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
> +		 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
>  {
>    int r;
>    struct dqblk D;
>    uid_t euser_id;
> +  const char *path = fname->base_name;
>  #if !defined(AIX)
>    char dev_disk[256];
> -  SMB_STRUCT_STAT S;
> +  SMB_STRUCT_STAT S = fname->st;
>  
>    /* find the block device file */
>  
> @@ -463,8 +461,8 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
>  
>  #else /* WITH_QUOTAS */
>  
> -bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
> -		 uint64_t *dfree, uint64_t *dsize)
> +bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
> +		 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
>  {
>  	(*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
>     this file should be removed later
>     */
> -bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
> -		 uint64_t *dfree, uint64_t *dsize)
> +bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
> +		 uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
>  {
>  	int r;
>  	SMB_DISK_QUOTA D;
> @@ -496,7 +494,8 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
>  	 */
>  	ZERO_STRUCT(D);
>  	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) {
>  		goto try_group_quota;
>  	}
> @@ -507,7 +506,8 @@ bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
>  	ZERO_STRUCT(D);
>  	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) {
>  		goto try_group_quota;
> @@ -543,7 +543,8 @@ try_group_quota:
>  	 */
>  	ZERO_STRUCT(D);
>  	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) {
>  		return false;
>  	}
> @@ -554,7 +555,8 @@ try_group_quota:
>  	id.gid = getegid();
>  
>  	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) {
>  		return False;
> diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
> index 0b7a4fb..4f1ecb1 100644
> --- a/source3/smbd/reply.c
> +++ b/source3/smbd/reply.c
> @@ -1573,9 +1573,20 @@ void reply_dskattr(struct smb_request *req)
>  	connection_struct *conn = req->conn;
>  	uint64_t ret;
>  	uint64_t dfree,dsize,bsize;
> +	struct smb_filename smb_fname;
>  	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) {
>  		reply_nterror(req, map_nt_error_from_unix(errno));
>  		END_PROFILE(SMBdskattr);
> diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
> index 9c0660b..1775316 100644
> --- a/source3/smbd/trans2.c
> +++ b/source3/smbd/trans2.c
> @@ -3438,8 +3438,8 @@ NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
>  		{
>  			uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
>  			data_len = 18;
> -			df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
> -						&dsize);
> +			df_ret = get_dfree_info(conn, &smb_fname, &bsize,
> +						&dfree, &dsize);
>  			if (df_ret == (uint64_t)-1) {
>  				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;
>  			data_len = 24;
> -			df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
> -						&dsize);
> +			df_ret = get_dfree_info(conn, &smb_fname, &bsize,
> +						&dfree, &dsize);
>  			if (df_ret == (uint64_t)-1) {
>  				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;
>  			data_len = 32;
> -			df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
> -						&dsize);
> +			df_ret = get_dfree_info(conn, &smb_fname, &bsize,
> +						&dfree, &dsize);
>  			if (df_ret == (uint64_t)-1) {
>  				return map_nt_error_from_unix(errno);
>  			}
> diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
> index 605f9ad..45562ee 100644
> --- a/source3/smbd/vfs.c
> +++ b/source3/smbd/vfs.c
> @@ -623,8 +623,8 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
>  
>  	len -= fsp->fsp_name->st.st_ex_size;
>  	len /= 1024; /* Len is now number of 1k blocks needed. */
> -	space_avail = get_dfree_info(conn, fsp->fsp_name->base_name,
> -				     &bsize, &dfree, &dsize);
> +	space_avail =
> +	    get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
>  	if (space_avail == (uint64_t)-1) {
>  		return -1;
>  	}
> -- 
> 2.5.5
> 
> 
> From 7c40ccde4856b9599aca38972eb1fcd6fd8ae6ff Mon Sep 17 00:00:00 2001
> From: Uri Simchoni <uri at samba.org>
> Date: Thu, 11 Aug 2016 23:37:42 +0300
> Subject: [PATCH 3/5] smbd: use owner uid for free disk calculation if owner is
>  inherited
> 
> If "inherit owner" is enabled, then new files created under a
> directory shall consume the quota of the directory's owner, so
> the free disk calculation should take that quota into account,
> not the quota of the user creating the file.
> 
> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12145
> 
> Signed-off-by: Uri Simchoni <uri at samba.org>
> ---
>  source3/smbd/quotas.c | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c
> index f3a727c..2db18cd 100644
> --- a/source3/smbd/quotas.c
> +++ b/source3/smbd/quotas.c
> @@ -506,8 +506,25 @@ bool disk_quotas(connection_struct *conn, struct smb_filename *fname,
>  	ZERO_STRUCT(D);
>  	id.uid = geteuid();
>  
> -	r = SMB_VFS_GET_QUOTA(conn, fname->base_name, SMB_USER_QUOTA_TYPE, id,
> -			      &D);
> +	/* if new files created under this folder get this
> +	 * folder's UID, then available space is governed by
> +	 * the quota of the folder's UID, not the creating user.
> +	 */
> +	if (lp_inherit_owner(SNUM(conn)) != INHERIT_OWNER_NO &&
> +	    id.uid != fname->st.st_ex_uid && id.uid != sec_initial_uid()) {
> +		int save_errno;
> +
> +		id.uid = fname->st.st_ex_uid;
> +		become_root();
> +		r = SMB_VFS_GET_QUOTA(conn, fname->base_name,
> +				      SMB_USER_QUOTA_TYPE, id, &D);
> +		save_errno = errno;
> +		unbecome_root();
> +		errno = save_errno;
> +	} else {
> +		r = SMB_VFS_GET_QUOTA(conn, fname->base_name,
> +				      SMB_USER_QUOTA_TYPE, id, &D);
> +	}
>  
>  	if (r == -1) {
>  		goto try_group_quota;
> -- 
> 2.5.5
> 
> 
> From 9a8e93d0f1c9768477cb67747e7e6b738b8c33e5 Mon Sep 17 00:00:00 2001
> From: Uri Simchoni <uri at samba.org>
> Date: Wed, 20 Jan 2016 21:54:24 +0200
> Subject: [PATCH 4/5] selftest: refactor test_dfree_quota.sh - add share
>  parameter
> 
> Add a share parameter to individual disk-free tests. This will
> allow running tests on shares other than dfq share.
> 
> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12145
> 
> Signed-off-by: Uri Simchoni <uri at samba.org>
> ---
>  source3/script/tests/test_dfree_quota.sh | 47 ++++++++++++++++----------------
>  1 file changed, 24 insertions(+), 23 deletions(-)
> 
> diff --git a/source3/script/tests/test_dfree_quota.sh b/source3/script/tests/test_dfree_quota.sh
> index ab28a07..79b8d7c 100755
> --- a/source3/script/tests/test_dfree_quota.sh
> +++ b/source3/script/tests/test_dfree_quota.sh
> @@ -99,16 +99,17 @@ setup_conf() {
>  
>  test_smbclient_dfree() {
>  	name="$1"
> -	dir="$2"
> -    confs="$3"
> -    expected="$4"
> -	shift
> +    share="$2"
> +    dir="$3"
> +    confs="$4"
> +    expected="$5"
> +    shift
>      shift
>      shift
>      shift
>      subunit_start_test "$name"
>      setup_conf $confs
> -	output=$($VALGRIND $smbclient //$SERVER/dfq -c "cd $dir; l" $@ 2>&1)
> +    output=$($VALGRIND $smbclient //$SERVER/$share -c "cd $dir; l" $@ 2>&1)
>      status=$?
>      if [ "$status" = "0" ]; then
>  		received=$(echo "$output" | awk '/blocks of size/ {print $1, $5, $6}')
> @@ -150,39 +151,39 @@ test_smbcquotas() {
>  }
>  
>  #basic disk-free tests
> -test_smbclient_dfree "Test dfree share root SMB3 no quota" "." "conf1 ." "10 1024. 5" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test dfree subdir SMB3 no quota" "subdir1" "conf1 . conf2 subdir1" "20 1024. 10" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test dfree subdir NT1 no quota" "subdir1" "conf1 . conf2 subdir1" "10 1024. 5" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test large disk" "." "conf3 ." "1125899906842624 1024. 3000" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree share root SMB3 no quota" dfq "." "conf1 ." "10 1024. 5" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree subdir SMB3 no quota" dfq "subdir1" "conf1 . conf2 subdir1" "20 1024. 10" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree subdir NT1 no quota" dfq "subdir1" "conf1 . conf2 subdir1" "10 1024. 5" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test large disk" dfq "." "conf3 ." "1125899906842624 1024. 3000" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  #basic quota test (SMB1 only)
>  test_smbcquotas "Test user quota" confq1 $USERNAME "40960/4096000/3072000" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
>  
>  #quota limit > disk size, remaining quota > disk free
> -test_smbclient_dfree "Test dfree share root df vs quota case 1" "." "confdfq1 ." "80 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree share root df vs quota case 1" dfq "." "confdfq1 ." "80 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  #quota limit > disk size, remaining quota < disk free
> -test_smbclient_dfree "Test dfree share root df vs quota case 2" "." "confdfq2 ." "80 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree share root df vs quota case 2" dfq "." "confdfq2 ." "80 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  #quota limit < disk size, remaining quota > disk free
> -test_smbclient_dfree "Test dfree share root df vs quota case 3" "." "confdfq3 ." "160 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree share root df vs quota case 3" dfq "." "confdfq3 ." "160 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  #quota limit < disk size, remaining quota < disk free
> -test_smbclient_dfree "Test dfree share root df vs quota case 4" "." "confdfq4 ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test dfree subdir df vs quota case 4" "subdir1" "confdfq4 subdir1" "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree share root df vs quota case 4" dfq "." "confdfq4 ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree subdir df vs quota case 4" dfq "subdir1" "confdfq4 subdir1" "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  
>  #quota-->disk free special cases
> -test_smbclient_dfree "Test quota->dfree soft limit" "subdir1" "slimit subdir1" "168 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test quota->dfree hard limit" "subdir1" "hlimit subdir1" "180 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test quota->dfree inode soft limit" "subdir1" "islimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test quota->dfree inode hard limit" "subdir1" "ihlimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test quota->dfree err try group" "subdir1" "trygrp1 subdir1" "240 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> -test_smbclient_dfree "Test quota->dfree no-quota try group" "subdir1" "trygrp2 subdir1" "240 1024. 16" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test quota->dfree soft limit" dfq "subdir1" "slimit subdir1" "168 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test quota->dfree hard limit" dfq "subdir1" "hlimit subdir1" "180 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test quota->dfree inode soft limit" dfq "subdir1" "islimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test quota->dfree inode hard limit" dfq "subdir1" "ihlimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test quota->dfree err try group" dfq "subdir1" "trygrp1 subdir1" "240 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test quota->dfree no-quota try group" dfq "subdir1" "trygrp2 subdir1" "240 1024. 16" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  
>  #block size different in quota and df systems
> -test_smbclient_dfree "Test quota->dfree different block size" "subdir1" "blksize subdir1" "307200 1024. 307200" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test quota->dfree different block size" dfq "subdir1" "blksize subdir1" "307200 1024. 307200" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  
>  #quota configured but not enforced
> -test_smbclient_dfree "Test dfree share root quota not enforced" "." "notenforce ." "320 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree share root quota not enforced" dfq "." "notenforce ." "320 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  
>  #FS quota not implemented (NFS case)
> -test_smbclient_dfree "Test dfree share root FS quota not implemented" "." "nfs ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree share root FS quota not implemented" dfq "." "nfs ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  
>  setup_conf
>  exit $failed
> -- 
> 2.5.5
> 
> 
> From bb38d0488c940aa966ed5bf7ccc6c16a974b9c06 Mon Sep 17 00:00:00 2001
> From: Uri Simchoni <uri at samba.org>
> Date: Thu, 11 Aug 2016 23:54:22 +0300
> Subject: [PATCH 5/5] selftest: add tests for dfree with inherit owner enabled
> 
> BUG: https://bugzilla.samba.org/show_bug.cgi?id=12145
> 
> Signed-off-by: Uri Simchoni <uri at samba.org>
> ---
>  selftest/target/Samba3.pm                | 21 +++++++++++++++---
>  source3/script/tests/test_dfree_quota.sh | 37 ++++++++++++++++++++++++++++++--
>  source3/selftest/tests.py                |  2 +-
>  3 files changed, 54 insertions(+), 6 deletions(-)
> 
> diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
> index a0996a8..8fc3204 100755
> --- a/selftest/target/Samba3.pm
> +++ b/selftest/target/Samba3.pm
> @@ -614,6 +614,7 @@ sub setup_fileserver($$)
>  	push(@dirs, $dfree_share_dir);
>  	push(@dirs, "$dfree_share_dir/subdir1");
>  	push(@dirs, "$dfree_share_dir/subdir2");
> +	push(@dirs, "$dfree_share_dir/subdir3");
>  
>  	my $valid_users_sharedir="$share_dir/valid_users";
>  	push(@dirs,$valid_users_sharedir);
> @@ -1114,7 +1115,6 @@ sub createuser($$$$)
>  	    warn("Unable to set password for $username account\n$cmd");
>  	    return undef;
>  	}
> -	print "DONE\n";
>  }
>  
>  sub provision($$$$$$$$)
> @@ -1344,8 +1344,10 @@ sub provision($$$$$$$$)
>  	my ($gid_nobody, $gid_nogroup, $gid_root, $gid_domusers, $gid_domadmins);
>  	my ($gid_userdup, $gid_everyone);
>  	my ($gid_force_user);
> +	my ($uid_user1);
> +	my ($uid_user2);
>  
> -	if ($unix_uid < 0xffff - 7) {
> +	if ($unix_uid < 0xffff - 10) {
>  		$max_uid = 0xffff;
>  	} else {
>  		$max_uid = $unix_uid;
> @@ -1359,6 +1361,8 @@ sub provision($$$$$$$$)
>  	$uid_pdbtest_wkn = $max_uid - 6;
>  	$uid_force_user = $max_uid - 7;
>  	$uid_smbget = $max_uid - 8;
> +	$uid_user1 = $max_uid - 9;
> +	$uid_user2 = $max_uid - 10;
>  
>  	if ($unix_gids[0] < 0xffff - 8) {
>  		$max_gid = 0xffff;
> @@ -1780,9 +1784,14 @@ sub provision($$$$$$$$)
>  	wide links = yes
>  [dfq]
>  	path = $shrdir/dfree
> -	vfs objects = fake_dfq
> +	vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
>  	admin users = $unix_name
>  	include = $dfqconffile
> +[dfq_owner]
> +	path = $shrdir/dfree
> +	vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
> +	inherit owner = yes
> +	include = $dfqconffile
>  	";
>  	close(CONF);
>  
> @@ -1808,6 +1817,8 @@ userdup:x:$uid_userdup:$gid_userdup:userdup gecos:$prefix_abs:/bin/false
>  pdbtest_wkn:x:$uid_pdbtest_wkn:$gid_everyone:pdbtest_wkn gecos:$prefix_abs:/bin/false
>  force_user:x:$uid_force_user:$gid_force_user:force user gecos:$prefix_abs:/bin/false
>  smbget_user:x:$uid_smbget:$gid_domusers:smbget_user gecos:$prefix_abs:/bin/false
> +user1:x:$uid_user1:$gid_nogroup:user1 gecos:$prefix_abs:/bin/false
> +user2:x:$uid_user2:$gid_nogroup:user2 gecos:$prefix_abs:/bin/false
>  ";
>  	if ($unix_uid != 0) {
>  		print PASSWD "root:x:$uid_root:$gid_root:root gecos:$prefix_abs:/bin/false
> @@ -1882,12 +1893,16 @@ force_user:x:$gid_force_user:
>  	createuser($self, $unix_name, $password, $conffile) || die("Unable to create user");
>  	createuser($self, "force_user", $password, $conffile) || die("Unable to create force_user");
>  	createuser($self, "smbget_user", $password, $conffile) || die("Unable to create smbget_user");
> +	createuser($self, "user1", $password, $conffile) || die("Unable to create user1");
> +	createuser($self, "user2", $password, $conffile) || die("Unable to create user2");
>  
>  	open(DNS_UPDATE_LIST, ">$prefix/dns_update_list") or die("Unable to open $$prefix/dns_update_list");
>  	print DNS_UPDATE_LIST "A $server. $server_ip\n";
>  	print DNS_UPDATE_LIST "AAAA $server. $server_ipv6\n";
>  	close(DNS_UPDATE_LIST);
>  
> +	print "DONE\n";
> +
>  	$ret{SERVER_IP} = $server_ip;
>  	$ret{SERVER_IPV6} = $server_ipv6;
>  	$ret{NMBD_TEST_LOG} = "$prefix/nmbd_test.log";
> diff --git a/source3/script/tests/test_dfree_quota.sh b/source3/script/tests/test_dfree_quota.sh
> index 79b8d7c..6e227c4 100755
> --- a/source3/script/tests/test_dfree_quota.sh
> +++ b/source3/script/tests/test_dfree_quota.sh
> @@ -5,7 +5,7 @@
>  
>  if [ $# -lt 6 ]; then
>  cat <<EOF
> -Usage: test_dfree_quota.sh SERVER DOMAIN USERNAME PASSWORD LOCAL_PATH SMBCLIENT SMBCQUOTAS
> +Usage: test_dfree_quota.sh SERVER DOMAIN USERNAME PASSWORD LOCAL_PATH SMBCLIENT SMBCQUOTAS SMBCACLS
>  EOF
>  exit 1;
>  fi
> @@ -18,7 +18,8 @@ ENVDIR=`dirname $5`
>  WORKDIR=$5/dfree
>  smbclient=$6
>  smbcquotas=$7
> -shift 7
> +smbcacls=$8
> +shift 8
>  failed=0
>  
>  CONFFILE=$ENVDIR/lib/dfq.conf
> @@ -35,6 +36,8 @@ conf_lines() {
>      local gid
>      uid=$(id -u $USERNAME)
>      gid=$(id -g $USERNAME)
> +    uid1=$(id -u user1)
> +    uid2=$(id -u user2)
>  cat <<ABC
>  conf1:df:block size = 512:disk free = 10:disk size = 20
>  conf2:df:block size = 1024:disk free = 10:disk size = 20
> @@ -70,6 +73,9 @@ notenforce:udflt:block size = 4096:qflags = 0
>  nfs:df:block size = 4096:disk free = 10:disk size = 80
>  nfs:u$uid:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 37
>  nfs:udflt:nosys = 1
> +confdfqp:df:block size = 4096:disk free = 10:disk size = 80
> +confdfqp:u$uid1:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 36
> +confdfqp:u$uid2:block size = 4096:hard limit = 41:soft limit = 41:cur blocks = 36
>  ABC
>  }
>  
> @@ -185,5 +191,32 @@ test_smbclient_dfree "Test dfree share root quota not enforced" dfq "." "notenfo
>  #FS quota not implemented (NFS case)
>  test_smbclient_dfree "Test dfree share root FS quota not implemented" dfq "." "nfs ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
>  
> +#test for dfree when owner is inherited
> +#setup two folders with different owners
> +rm -rf $WORKDIR/subdir3/*
> +for d in / subdir3
> +do
> +    $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -D "ACL:$SERVER\user1:ALLOWED/0x0/FULL" //$SERVER/dfq $d > /dev/null 2>&1
> +    $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -a "ACL:$SERVER\user1:ALLOWED/0x0/FULL" //$SERVER/dfq $d || failed=`expr $failed + 1`
> +    $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -D "ACL:$SERVER\user2:ALLOWED/0x0/FULL" //$SERVER/dfq $d > /dev/null 2>&1
> +    $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -a "ACL:$SERVER\user2:ALLOWED/0x0/FULL" //$SERVER/dfq $d || failed=`expr $failed + 1`
> +done
> +
> +$VALGRIND $smbclient //$SERVER/dfq -c "cd subdir3; mkdir user1" -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 > /dev/null 2>&1 || failed=`expr $failed + 1`
> +$VALGRIND $smbclient //$SERVER/dfq -c "cd subdir3; mkdir user2" -Uuser2%$PASSWORD --option=clientmaxprotocol=SMB3 > /dev/null 2>&1 || failed=`expr $failed + 1`
> +#test quotas
> +test_smbclient_dfree "Test dfree without inherit owner - user1 at user1" \
> +    dfq "subdir3/user1" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \
> +    -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree without inherit owner - user1 at user2" \
> +    dfq "subdir3/user2" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \
> +    -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree with inherit owner - user1 at user1" \
> +    dfq_owner "subdir3/user1" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \
> +    -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +test_smbclient_dfree "Test dfree with inherit owner - user1 at user2" \
> +    dfq_owner "subdir3/user2" "confdfqp subdir3/user1 confdfqp subdir3/user2" "164 1024. 20" \
> +    -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
> +
>  setup_conf
>  exit $failed
> diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
> index 23fb37d..0a0cb08 100755
> --- a/source3/selftest/tests.py
> +++ b/source3/selftest/tests.py
> @@ -184,7 +184,7 @@ for env in ["nt4_dc"]:
>  for env in ["fileserver"]:
>      plantestsuite("samba3.blackbox.preserve_case (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_preserve_case.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
>      plantestsuite("samba3.blackbox.dfree_command (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_dfree_command.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
> -    plantestsuite("samba3.blackbox.dfree_quota (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_dfree_quota.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH', smbclient3, smbcquotas])
> +    plantestsuite("samba3.blackbox.dfree_quota (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_dfree_quota.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH', smbclient3, smbcquotas, smbcacls])
>      plantestsuite("samba3.blackbox.valid_users (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_valid_users.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
>      plantestsuite("samba3.blackbox.offline (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_offline.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/offline', smbclient3])
>      plantestsuite("samba3.blackbox.shadow_copy2 (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3])
> -- 
> 2.5.5
> 




More information about the samba-technical mailing list