[PATCHES] s2-sysquota-linux: remove support for old linux quota interfaces

Uri Simchoni uri at samba.org
Tue May 24 19:43:20 UTC 2016


Hi,

This patch set removes support for what seems to be pretty old Linux
quota interfaces. Looks like the "current" quotactl interface has been
supported for some time now, and the "v1" and "v2" interface support can
be dropped.

One thing I didn't clean up was treatment of EDQUOT as a non-error
condition for quotactl() system call. The code assumed that when
querying quota, an EDQUOT errno return means that quotactl has returned
meaningful data. I tried to keep this. However, I did not find
documentation of this in Linux man pages, nor in the current kernel
source code, so I wonder whether we need this.

Review appreciated.
Thanks,
Uri.
-------------- next part --------------
From 9af41731dac862274fdc5a2410fd24b94b1d26e7 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Mon, 23 May 2016 22:07:39 +0300
Subject: [PATCH 1/3] s3-sysquotas-linux: remove support for old interfaces

Remove support for Linux quota interfaces that predate the
2.6.x kernel series. Glibc has been supporting the "current"
quota interface for over 10 years now...

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/include/samba_linux_quota.h | 335 ------------------------------------
 source3/lib/sysquotas_linux.c       | 302 +-------------------------------
 2 files changed, 9 insertions(+), 628 deletions(-)
 delete mode 100644 source3/include/samba_linux_quota.h

diff --git a/source3/include/samba_linux_quota.h b/source3/include/samba_linux_quota.h
deleted file mode 100644
index 51acc20..0000000
--- a/source3/include/samba_linux_quota.h
+++ /dev/null
@@ -1,335 +0,0 @@
-#ifndef _SAMBA_LINUX_QUOTA_H_
-#define _SAMBA_LINUX_QUOTA_H_
-/*
-   Unix SMB/CIFS implementation.
-   Copyright (C) Andrew Tridgell 1994-2002
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
-	This file is needed because Quota support on Linux has
-	been broken since Linus kernel 2.4.x. It will only get
-	better (and this file be removed) when all the distributions
-	ship a glibc with a working quota.h file. This is very
-	bad. JRA.
-
-	Original file came from Christoph Hellwig <hch at infradead.org>.
-	Massaged into one nasty include file (to stop us having to
-	add multiple files into Samba just for Linux braindamage)
-	by JRA.
-*/
-
-#undef QUOTABLOCK_SIZE
-
-#ifndef _QUOTAIO_LINUX_V1
-#define _QUOTAIO_LINUX_V1
-
-/*
- *	Headerfile for old quotafile format
- */
-
-#include <sys/types.h>
-
-#define V1_DQBLK_SIZE_BITS 10
-#define V1_DQBLK_SIZE (1 << V1_DQBLK_SIZE_BITS)	/* Size of one quota block in bytes in old format */
-
-#define V1_DQOFF(__id) ((loff_t) ((__id) * sizeof(struct v1_disk_dqblk)))
-
-/* Structure of quota on disk */
-struct v1_disk_dqblk {
-	u_int32_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
-	u_int32_t dqb_bsoftlimit;	/* preferred limit on disk blks */
-	u_int32_t dqb_curblocks;	/* current block count */
-	u_int32_t dqb_ihardlimit;	/* maximum # allocated inodes */
-	u_int32_t dqb_isoftlimit;	/* preferred limit on inodes */
-	u_int32_t dqb_curinodes;	/* current # allocated inodes */
-	time_t dqb_btime;	/* time limit for excessive disk use */
-	time_t dqb_itime;	/* time limit for excessive files */
-} __attribute__ ((packed));
-
-/* Structure used for communication with kernel */
-struct v1_kern_dqblk {
-	u_int32_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
-	u_int32_t dqb_bsoftlimit;	/* preferred limit on disk blks */
-	u_int32_t dqb_curblocks;	/* current block count */
-	u_int32_t dqb_ihardlimit;	/* maximum # allocated inodes */
-	u_int32_t dqb_isoftlimit;	/* preferred inode limit */
-	u_int32_t dqb_curinodes;	/* current # allocated inodes */
-	time_t dqb_btime;	/* time limit for excessive disk use */
-	time_t dqb_itime;	/* time limit for excessive files */
-};
-
-struct v1_dqstats {
-	u_int32_t lookups;
-	u_int32_t drops;
-	u_int32_t reads;
-	u_int32_t writes;
-	u_int32_t cache_hits;
-	u_int32_t allocated_dquots;
-	u_int32_t free_dquots;
-	u_int32_t syncs;
-};                                                                               
-
-#ifndef Q_V1_GETQUOTA
-#define Q_V1_GETQUOTA  0x300
-#endif
-#ifndef Q_V1_SETQUOTA
-#define Q_V1_SETQUOTA  0x400
-#endif
-
-#endif /* _QUOTAIO_LINUX_V1 */
-
-/*
- *
- *	Header file for disk format of new quotafile format
- *
- */
-
-#ifndef _QUOTAIO_LINUX_V2
-#define _QUOTAIO_LINUX_V2
-
-#include <sys/types.h>
-
-#ifndef _QUOTA_LINUX
-#define _QUOTA_LINUX
-
-#include <sys/types.h>
-
-typedef u_int32_t qid_t;	/* Type in which we store ids in memory */
-typedef u_int64_t qsize_t;	/* Type in which we store size limitations */
-
-#define MAXQUOTAS 2
-#define USRQUOTA  0		/* element used for user quotas */
-#define GRPQUOTA  1		/* element used for group quotas */
-
-/*
- * Definitions for the default names of the quotas files.
- */
-#define INITQFNAMES { \
-	"user",    /* USRQUOTA */ \
-	"group",   /* GRPQUOTA */ \
-	"undefined", \
-}
-
-/*
- * Definitions of magics and versions of current quota files
- */
-#define INITQMAGICS {\
-	0xd9c01f11,	/* USRQUOTA */\
-	0xd9c01927	/* GRPQUOTA */\
-}
-
-/* Size of blocks in which are counted size limits in generic utility parts */
-#define QUOTABLOCK_BITS 10
-#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
-
-/* Conversion routines from and to quota blocks */
-#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
-#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
-#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
-
-/*
- * Command definitions for the 'quotactl' system call.
- * The commands are broken into a main command defined below
- * and a subcommand that is used to convey the type of
- * quota that is being manipulated (see above).
- */
-#define SUBCMDMASK  0x00ff
-#define SUBCMDSHIFT 8
-#define QCMD(cmd, type)  (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
-
-#define Q_6_5_QUOTAON  0x0100	/* enable quotas */
-#define Q_6_5_QUOTAOFF 0x0200	/* disable quotas */
-#define Q_6_5_SYNC     0x0600	/* sync disk copy of a filesystems quotas */
-
-#define Q_SYNC     0x800001	/* sync disk copy of a filesystems quotas */
-#define Q_QUOTAON  0x800002	/* turn quotas on */
-#define Q_QUOTAOFF 0x800003	/* turn quotas off */
-#define Q_GETFMT   0x800004	/* get quota format used on given filesystem */
-#define Q_GETINFO  0x800005	/* get information about quota files */
-#define Q_SETINFO  0x800006	/* set information about quota files */
-#define Q_GETQUOTA 0x800007	/* get user quota structure */
-#define Q_SETQUOTA 0x800008	/* set user quota structure */
-
-/*
- * Quota structure used for communication with userspace via quotactl
- * Following flags are used to specify which fields are valid
- */
-#define QIF_BLIMITS	1
-#define QIF_SPACE	2
-#define QIF_ILIMITS	4
-#define QIF_INODES	8
-#define QIF_BTIME	16
-#define QIF_ITIME	32
-#define QIF_LIMITS	(QIF_BLIMITS | QIF_ILIMITS)
-#define QIF_USAGE	(QIF_SPACE | QIF_INODES)
-#define QIF_TIMES	(QIF_BTIME | QIF_ITIME)
-#define QIF_ALL		(QIF_LIMITS | QIF_USAGE | QIF_TIMES)
-
-struct if_dqblk {
-	u_int64_t dqb_bhardlimit;
-	u_int64_t dqb_bsoftlimit;
-	u_int64_t dqb_curspace;
-	u_int64_t dqb_ihardlimit;
-	u_int64_t dqb_isoftlimit;
-	u_int64_t dqb_curinodes;
-	u_int64_t dqb_btime;
-	u_int64_t dqb_itime;
-	u_int32_t dqb_valid;
-};
-
-/*
- * Structure used for setting quota information about file via quotactl
- * Following flags are used to specify which fields are valid
- */
-#define IIF_BGRACE	1
-#define IIF_IGRACE	2
-#define IIF_FLAGS	4
-#define IIF_ALL		(IIF_BGRACE | IIF_IGRACE | IIF_FLAGS)
-
-struct if_dqinfo {
-	u_int64_t dqi_bgrace;
-	u_int64_t dqi_igrace;
-	u_int32_t dqi_flags;
-	u_int32_t dqi_valid;
-};
-
-/* Quota format identifiers */
-#define QFMT_VFS_OLD 1
-#define QFMT_VFS_V0  2
-
-/* Flags supported by kernel */
-#define V1_DQF_RSQUASH 1
-
-/* Ioctl for getting quota size */
-#include <sys/ioctl.h>
-#ifndef FIOQSIZE
-	#if defined(__alpha__) || defined(__powerpc__) || defined(__sh__) || defined(__sparc__) || defined(__sparc64__)
-		#define FIOQSIZE _IOR('f', 128, loff_t)
-	#elif defined(__arm__) || defined(__mc68000__) || defined(__s390__)
-		#define FIOQSIZE 0x545E
-        #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__ia64__) || defined(__parisc__) || defined(__cris__) || defined(__hppa__)
-		#define FIOQSIZE 0x5460
-	#elif defined(__mips__) || defined(__mips64__)
-		#define FIOQSIZE 0x6667
-	#endif
-#endif
-
-long quotactl(int, const char *, qid_t, caddr_t);
-
-#endif /* _QUOTA_LINUX */
-
-#define V2_DQINFOOFF	sizeof(struct v2_disk_dqheader)	/* Offset of info header in file */
-#define V2_DQBLKSIZE_BITS	10
-#define V2_DQBLKSIZE	(1 << V2_DQBLKSIZE_BITS)	/* Size of block with quota structures */
-#define V2_DQTREEOFF	1	/* Offset of tree in file in blOcks */
-#define V2_DQTREEDEPTH	4	/* Depth of quota tree */
-#define V2_DQSTRINBLK	((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))	/* Number of entries in one blocks */
-#define V2_GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
-#define V2_GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)(buf)) + sizeof(struct v2_disk_dqdbheader)))
-#define INIT_V2_VERSIONS { 0, 0}
-
-struct v2_disk_dqheader {
-	u_int32_t dqh_magic;	/* Magic number identifying file */
-	u_int32_t dqh_version;	/* File version */
-} __attribute__ ((packed));
-
-/* Flags for version specific files */
-#define V2_DQF_MASK  0x0000	/* Mask for all valid ondisk flags */
-
-/* Header with type and version specific information */
-struct v2_disk_dqinfo {
-	u_int32_t dqi_bgrace;	/* Time before block soft limit becomes hard limit */
-	u_int32_t dqi_igrace;	/* Time before inode soft limit becomes hard limit */
-	u_int32_t dqi_flags;	/* Flags for quotafile (DQF_*) */
-	u_int32_t dqi_blocks;	/* Number of blocks in file */
-	u_int32_t dqi_free_blk;	/* Number of first free block in the list */
-	u_int32_t dqi_free_entry;	/* Number of block with at least one free entry */
-} __attribute__ ((packed));
-
-/*
- *  Structure of header of block with quota structures. It is padded to 16 bytes so
- *  there will be space for exactly 18 quota-entries in a block
- */
-struct v2_disk_dqdbheader {
-	u_int32_t dqdh_next_free;	/* Number of next block with free entry */
-	u_int32_t dqdh_prev_free;	/* Number of previous block with free entry */
-	u_int16_t dqdh_entries;	/* Number of valid entries in block */
-	u_int16_t dqdh_pad1;
-	u_int32_t dqdh_pad2;
-} __attribute__ ((packed));
-
-/* Structure of quota for one user on disk */
-struct v2_disk_dqblk {
-	u_int32_t dqb_id;	/* id this quota applies to */
-	u_int32_t dqb_ihardlimit;	/* absolute limit on allocated inodes */
-	u_int32_t dqb_isoftlimit;	/* preferred inode limit */
-	u_int32_t dqb_curinodes;	/* current # allocated inodes */
-	u_int32_t dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
-	u_int32_t dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
-	u_int64_t dqb_curspace;	/* current space occupied (in bytes) */
-	u_int64_t dqb_btime;	/* time limit for excessive disk use */
-	u_int64_t dqb_itime;	/* time limit for excessive inode use */
-} __attribute__ ((packed));
-
-/* Structure of quota for communication with kernel */
-struct v2_kern_dqblk {
-	unsigned int dqb_ihardlimit;
-	unsigned int dqb_isoftlimit;
-	unsigned int dqb_curinodes;
-	unsigned int dqb_bhardlimit;
-	unsigned int dqb_bsoftlimit;
-	qsize_t dqb_curspace;
-	time_t dqb_btime;
-	time_t dqb_itime;
-};
-
-/* Structure of quotafile info for communication with kernel */
-struct v2_kern_dqinfo {
-	unsigned int dqi_bgrace;
-	unsigned int dqi_igrace;
-	unsigned int dqi_flags;
-	unsigned int dqi_blocks;
-	unsigned int dqi_free_blk;
-	unsigned int dqi_free_entry;
-};
-
-/* Structure with gathered statistics from kernel */
-struct v2_dqstats {
-	u_int32_t lookups;
-	u_int32_t drops;
-	u_int32_t reads;
-	u_int32_t writes;
-	u_int32_t cache_hits;
-	u_int32_t allocated_dquots;
-	u_int32_t free_dquots;
-	u_int32_t syncs;
-	u_int32_t version;
-};
-
-#ifndef Q_V2_GETQUOTA
-#define Q_V2_GETQUOTA  0x0D00
-#endif
-#ifndef Q_V2_SETQUOTA
-#define Q_V2_SETQUOTA  0x0E00
-#endif
-
-#endif /* _QUOTAIO_LINUX_V2 */
-
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE        1024
-#endif
-
-#endif /* _SAMBA_LINUX_QUOTA_H_ */
diff --git a/source3/lib/sysquotas_linux.c b/source3/lib/sysquotas_linux.c
index 5984626..61cbd2b 100644
--- a/source3/lib/sysquotas_linux.c
+++ b/source3/lib/sysquotas_linux.c
@@ -31,267 +31,7 @@
 
 #ifdef HAVE_QUOTACTL_LINUX 
 
-#include "samba_linux_quota.h"
-
-/****************************************************************************
- Abstract out the v1 Linux quota get calls.
-****************************************************************************/
-static int sys_get_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	uint32_t qflags = 0;
-	struct v1_kern_dqblk D;
-	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
-
-	ZERO_STRUCT(D);
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
-				path, bdev, (unsigned)id.uid));
-
-			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
-				return ret;
-			}
-
-			break;
-		case SMB_GROUP_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
-				path, bdev, (unsigned)id.gid));
-
-			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
-				return ret;
-			}
-
-			break;
-		case SMB_USER_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
-				path, bdev, (unsigned)id.uid));
-
-			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
-				path, bdev, (unsigned)id.gid));
-
-			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	dp->bsize = bsize;
-	dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
-	dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
-	dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
-	dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
-	dp->curinodes = (uint64_t)D.dqb_curinodes;
-	dp->curblocks = (uint64_t)D.dqb_curblocks;
-
-
-	dp->qflags = qflags;
-
-	return ret;
-}
-
-/****************************************************************************
- Abstract out the v1 Linux quota set calls.
-****************************************************************************/
-static int sys_set_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	struct v1_kern_dqblk D;
-	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
-
-	ZERO_STRUCT(D);
-
-	if (bsize == dp->bsize) {
-		D.dqb_bsoftlimit = dp->softlimit;
-		D.dqb_bhardlimit = dp->hardlimit;
-		D.dqb_ihardlimit = dp->ihardlimit;
-		D.dqb_isoftlimit = dp->isoftlimit;
-	} else {
-		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
-		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
-		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
-		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
-	}
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
-				path, bdev, (unsigned)id.uid));
-
-			ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
-			break;
-		case SMB_GROUP_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
-				path, bdev, (unsigned)id.gid));
-
-			ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
-			break;
-		case SMB_USER_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
-				path, bdev, (unsigned)id.uid));
-
-			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
-				dp->qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v1_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
-				path, bdev, (unsigned)id.gid));
-
-			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
-				dp->qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	return ret;
-}
-
-/****************************************************************************
- Abstract out the v2 Linux quota get calls.
-****************************************************************************/
-static int sys_get_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	uint32_t qflags = 0;
-	struct v2_kern_dqblk D;
-	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
-
-	ZERO_STRUCT(D);
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
-				path, bdev, (unsigned)id.uid));
-
-			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
-				return ret;
-			}
-
-			break;
-		case SMB_GROUP_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
-				path, bdev, (unsigned)id.gid));
-
-			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
-				return ret;
-			}
-
-			break;
-		case SMB_USER_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
-				path, bdev, (unsigned)id.uid));
-
-			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
-				path, bdev, (unsigned)id.gid));
-
-			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	dp->bsize = bsize;
-	dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
-	dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
-	dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
-	dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
-	dp->curinodes = (uint64_t)D.dqb_curinodes;
-	dp->curblocks = (uint64_t)D.dqb_curspace/bsize;
-
-
-	dp->qflags = qflags;
-
-	return ret;
-}
-
-/****************************************************************************
- Abstract out the v2 Linux quota set calls.
-****************************************************************************/
-static int sys_set_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	struct v2_kern_dqblk D;
-	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
-
-	ZERO_STRUCT(D);
-
-	if (bsize == dp->bsize) {
-		D.dqb_bsoftlimit = dp->softlimit;
-		D.dqb_bhardlimit = dp->hardlimit;
-		D.dqb_ihardlimit = dp->ihardlimit;
-		D.dqb_isoftlimit = dp->isoftlimit;
-	} else {
-		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
-		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
-		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
-		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
-	}
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
-				path, bdev, (unsigned)id.uid));
-
-			ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
-			break;
-		case SMB_GROUP_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
-				path, bdev, (unsigned)id.gid));
-
-			ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
-			break;
-		case SMB_USER_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
-				path, bdev, (unsigned)id.uid));
-
-			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
-				dp->qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_v2_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
-				path, bdev, (unsigned)id.gid));
-
-			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
-				dp->qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	return ret;
-}
+#include <sys/quota.h>
 
 /****************************************************************************
  Abstract out the generic Linux quota get calls.
@@ -300,7 +40,7 @@ static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_
 {
 	int ret = -1;
 	uint32_t qflags = 0;
-	struct if_dqblk D;
+	struct dqblk D;
 	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
 
 	ZERO_STRUCT(D);
@@ -367,7 +107,7 @@ static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_
 static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
 {
 	int ret = -1;
-	struct if_dqblk D;
+	struct dqblk D;
 	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
 
 	ZERO_STRUCT(D);
@@ -441,33 +181,21 @@ int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
 		case SMB_USER_QUOTA_TYPE:
 		case SMB_GROUP_QUOTA_TYPE:
 			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-					if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-						return ret;
-					}
-				}
+				return ret;
 			}
 			ret = 0;
 			break;
 		case SMB_USER_FS_QUOTA_TYPE:
 			id.uid = getuid();
 
-			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
-				}
-			}
+			sys_get_linux_gen_quota(path, bdev, qtype, id, dp);
 
 			ret = 0;
 			break;
 		case SMB_GROUP_FS_QUOTA_TYPE:
 			id.gid = getgid();
 
-			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
-				}
-			}
+			sys_get_linux_gen_quota(path, bdev, qtype, id, dp);
 
 			ret = 0;
 			break;
@@ -496,21 +224,13 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
 		case SMB_USER_QUOTA_TYPE:
 		case SMB_GROUP_QUOTA_TYPE:
 			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
-				if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
-					if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
-						return ret;
-					}
-				}
+				return ret;
 			}
 			break;
 		case SMB_USER_FS_QUOTA_TYPE:
 			id.uid = getuid();
 
-			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
-				if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
-					ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
-				}
-			}
+			sys_set_linux_gen_quota(path, bdev, qtype, id, dp);
 
 			if (oldqflags == dp->qflags) {
 				ret = 0;
@@ -521,11 +241,7 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
 		case SMB_GROUP_FS_QUOTA_TYPE:
 			id.gid = getgid();
 
-			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
-				if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
-					ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp);
-				}
-			}
+			sys_set_linux_gen_quota(path, bdev, qtype, id, dp);
 
 			if (oldqflags == dp->qflags) {
 				ret = 0;
-- 
2.5.5


From f96b1e2e382b782806f5966203f2190b701ed966 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Mon, 23 May 2016 22:27:28 +0300
Subject: [PATCH 2/3] s3-sysquotas-linux: remove check for EDQUOT on getting
 user quota

The same check is done by sys_get_quota() which is the only caller.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/lib/sysquotas_linux.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/source3/lib/sysquotas_linux.c b/source3/lib/sysquotas_linux.c
index 61cbd2b..2de3c85 100644
--- a/source3/lib/sysquotas_linux.c
+++ b/source3/lib/sysquotas_linux.c
@@ -180,10 +180,7 @@ int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
 	switch (qtype) {
 		case SMB_USER_QUOTA_TYPE:
 		case SMB_GROUP_QUOTA_TYPE:
-			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
-				return ret;
-			}
-			ret = 0;
+			ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp);
 			break;
 		case SMB_USER_FS_QUOTA_TYPE:
 			id.uid = getuid();
-- 
2.5.5


From d66970f7d81785da5f9e85fd84988864a294c91b Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Mon, 23 May 2016 23:14:12 +0300
Subject: [PATCH 3/3] s3-sysquotas-linux - cleanup

Now that the module supports only the current Linux quota
interface, it does not need a two-level hierarchy.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/lib/sysquotas_linux.c | 168 +++++++++++++++---------------------------
 1 file changed, 61 insertions(+), 107 deletions(-)

diff --git a/source3/lib/sysquotas_linux.c b/source3/lib/sysquotas_linux.c
index 2de3c85..543d56d 100644
--- a/source3/lib/sysquotas_linux.c
+++ b/source3/lib/sysquotas_linux.c
@@ -29,20 +29,28 @@
 #endif
 #endif
 
-#ifdef HAVE_QUOTACTL_LINUX 
+#ifdef HAVE_QUOTACTL_LINUX
 
 #include <sys/quota.h>
 
 /****************************************************************************
- Abstract out the generic Linux quota get calls.
+ Linux quota get calls.
 ****************************************************************************/
-static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+int sys_get_vfs_quota(const char *path, const char *bdev,
+		      enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
 {
 	int ret = -1;
 	uint32_t qflags = 0;
 	struct dqblk D;
 	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
 
+	if (!path || !bdev || !dp) {
+		smb_panic("sys_set_vfs_quota: called with NULL pointer");
+	}
+
+	ZERO_STRUCT(*dp);
+	dp->qtype = qtype;
+
 	ZERO_STRUCT(D);
 
 	switch (qtype) {
@@ -65,22 +73,29 @@ static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_
 
 			break;
 		case SMB_USER_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
-				path, bdev, (unsigned)id.uid));
+			DEBUG(10, ("sys_get_linux_gen_quota: path[%s] bdev[%s] "
+				   "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
+				   path, bdev, (unsigned)geteuid()));
 
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+			if ((ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
+					    geteuid(), (caddr_t)&D)) == 0) {
 				qflags |= QUOTAS_DENY_DISK;
 			}
 
+			ret = 0;
+
 			break;
 		case SMB_GROUP_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_get_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
-				path, bdev, (unsigned)id.gid));
+			DEBUG(10, ("sys_get_linux_gen_quota: path[%s] bdev[%s] "
+				   "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
+				   path, bdev, (unsigned)getgid()));
 
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+			if ((ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
+					    getgid(), (caddr_t)&D)) == 0) {
 				qflags |= QUOTAS_DENY_DISK;
 			}
 
+			ret = 0;
 			break;
 		default:
 			errno = ENOSYS;
@@ -102,13 +117,19 @@ static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_
 }
 
 /****************************************************************************
- Abstract out the gen Linux quota set calls.
+ Linux quota set calls.
 ****************************************************************************/
-static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+int sys_set_vfs_quota(const char *path, const char *bdev,
+		      enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
 {
 	int ret = -1;
 	struct dqblk D;
 	uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
+	bool cur_enf, new_enf;
+
+	if (!path || !bdev || !dp) {
+		smb_panic("sys_set_vfs_quota: called with NULL pointer");
+	}
 
 	ZERO_STRUCT(D);
 
@@ -139,110 +160,43 @@ static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_
 			ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
 			break;
 		case SMB_USER_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
-				path, bdev, (unsigned)id.uid));
-
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
-				dp->qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			DEBUG(10,("sys_set_linux_gen_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
-				path, bdev, (unsigned)id.gid));
-
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
-				dp->qflags |= QUOTAS_DENY_DISK;
-			}
-
-			break;
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	return ret;
-}
-
-/****************************************************************************
- Abstract out the Linux quota get calls.
-****************************************************************************/
-int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-
-	if (!path||!bdev||!dp)
-		smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
-	ZERO_STRUCT(*dp);
-	dp->qtype = qtype;
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-		case SMB_GROUP_QUOTA_TYPE:
-			ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp);
-			break;
-		case SMB_USER_FS_QUOTA_TYPE:
-			id.uid = getuid();
-
-			sys_get_linux_gen_quota(path, bdev, qtype, id, dp);
-
-			ret = 0;
-			break;
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			id.gid = getgid();
-
-			sys_get_linux_gen_quota(path, bdev, qtype, id, dp);
-
-			ret = 0;
-			break;
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	return ret;
-}
-
-/****************************************************************************
- Abstract out the Linux quota set calls.
-****************************************************************************/
-int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	uint32_t oldqflags = 0;
-
-	if (!path||!bdev||!dp)
-		smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
-	oldqflags = dp->qflags;
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-		case SMB_GROUP_QUOTA_TYPE:
-			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
-				return ret;
-			}
-			break;
-		case SMB_USER_FS_QUOTA_TYPE:
-			id.uid = getuid();
-
-			sys_set_linux_gen_quota(path, bdev, qtype, id, dp);
-
-			if (oldqflags == dp->qflags) {
+			DEBUG(10, ("sys_set_linux_gen_quota: path[%s] bdev[%s] "
+				   "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
+				   path, bdev, (unsigned)geteuid()));
+
+			ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
+				       geteuid(), (caddr_t)&D);
+			cur_enf = (ret == 0 || errno == EDQUOT);
+			new_enf = ((dp->qflags & QUOTAS_DENY_DISK) != 0);
+			/* We're not changing quota enforcement, so return
+			 * success
+			 * IFF the wanted state is identical to the current
+			 * state */
+			if (cur_enf == new_enf) {
 				ret = 0;
 			} else {
+				errno = EPERM;
 				ret = -1;
 			}
+
 			break;
 		case SMB_GROUP_FS_QUOTA_TYPE:
-			id.gid = getgid();
-
-			sys_set_linux_gen_quota(path, bdev, qtype, id, dp);
-
-			if (oldqflags == dp->qflags) {
+			DEBUG(10, ("sys_set_linux_gen_quota: path[%s] bdev[%s] "
+				   "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
+				   path, bdev, (unsigned)getgid()));
+
+			ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
+				       getgid(), (caddr_t)&D);
+			cur_enf = (ret == 0 || errno == EDQUOT);
+			new_enf = ((dp->qflags & QUOTAS_DENY_DISK) != 0);
+			/* We're not changing quota enforcement, so return
+			 * success
+			 * IFF the wanted state is identical to the current
+			 * state */
+			if (cur_enf == new_enf) {
 				ret = 0;
 			} else {
+				errno = EPERM;
 				ret = -1;
 			}
 
-- 
2.5.5



More information about the samba-technical mailing list