Re: Quotas cleanup in 2.3.29

Jan Kara (jack@suse.cz)
Sun, 5 Dec 1999 15:48:56 +0100


--i9LlY+UWpKt15+FH
Content-Type: text/plain; charset=us-ascii

> Hello.
>
> I've done a cleanup in quota code in 2.3.29.. There were some parts from ancient
> ages (like testing uid against 0, passing ttys through functions when we can get
> them from 'current' and so on..).
> I'm also attaching patch which fixes testing of quotafile size and also fixes
> testing whether user has rights to get some quota information. Please apply them.
I'm sorry. I forgot to attach the files...

Honza.

--i9LlY+UWpKt15+FH
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="quota-fix-2.3.28-2.diff"

--- linux/kernel/sysctl.c Wed Nov 17 22:22:39 1999
+++ linux/kernel/sysctl.c Wed Nov 17 22:25:03 1999
@@ -351,7 +351,7 @@
}

/* Like in_group_p, but testing against egid, not fsgid */
-static int in_egroup_p(gid_t grp)
+int in_egroup_p(gid_t grp)
{
if (grp != current->egid) {
int i = current->ngroups;
--- linux/include/linux/sched.h Wed Nov 17 22:03:53 1999
+++ linux/include/linux/sched.h Wed Nov 17 22:24:34 1999
@@ -510,6 +510,7 @@
#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE)

extern int in_group_p(gid_t);
+extern int in_egroup_p(gid_t);

extern void flush_signals(struct task_struct *);
extern void flush_signal_handlers(struct task_struct *);
--- linux/fs/dquot.c Wed Nov 17 22:03:04 1999
+++ linux/fs/dquot.c Wed Nov 17 23:06:16 1999
@@ -1458,9 +1458,9 @@
static inline int check_quotafile_size(loff_t size)
{
ulong blocks = size >> BLOCK_SIZE_BITS;
- size_t off = size & ~(BLOCK_SIZE - 1);
+ size_t off = size & (BLOCK_SIZE - 1);

- return !((blocks % sizeof(struct dqblk) + off % sizeof(struct dqblk)) % sizeof(struct dqblk));
+ return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk));
}

int quota_on(kdev_t dev, short type, char *path)
@@ -1555,7 +1555,7 @@
break;
case Q_GETQUOTA:
if (((type == USRQUOTA && current->euid != id) ||
- (type == GRPQUOTA && in_group_p(id))) &&
+ (type == GRPQUOTA && in_egroup_p(id))) &&
!capable(CAP_SYS_RESOURCE))
goto out;
break;

--i9LlY+UWpKt15+FH
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="quota-fix-2.3.29-1.diff"

--- linux/include/linux/quota.h Thu Nov 18 19:12:08 1999
+++ linux/include/linux/quota.h Fri Dec 3 21:59:38 1999
@@ -44,8 +44,8 @@
/*
* Convert diskblocks to blocks and the other way around.
*/
-#define dbtob(num) (num << 10)
-#define btodb(num) (num >> 10)
+#define dbtob(num) (num << BLOCK_SIZE_BITS)
+#define btodb(num) (num >> BLOCK_SIZE_BITS)

/*
* Convert count of filesystem blocks to diskquota blocks, meant
--- linux/include/linux/quotaops.h Thu Nov 18 19:12:09 1999
+++ linux/include/linux/quotaops.h Fri Dec 3 22:49:45 1999
@@ -23,16 +23,13 @@
extern int quota_off(kdev_t dev, short type);
extern int sync_dquots(kdev_t dev, short type);

-extern int dquot_alloc_block(const struct inode *inode, unsigned long number,
- uid_t initiator, char warn);
-extern int dquot_alloc_inode(const struct inode *inode, unsigned long number,
- uid_t initiator);
+extern int dquot_alloc_block(const struct inode *inode, unsigned long number, char prealloc);
+extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);

extern void dquot_free_block(const struct inode *inode, unsigned long number);
extern void dquot_free_inode(const struct inode *inode, unsigned long number);

-extern int dquot_transfer(struct dentry *dentry, struct iattr *iattr,
- uid_t initiator);
+extern int dquot_transfer(struct dentry *dentry, struct iattr *iattr);

/*
* Operations supported for diskquotas.
@@ -54,8 +51,7 @@
extern __inline__ int DQUOT_PREALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
{
if (sb->dq_op) {
- if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
- current->fsuid, 0) == NO_QUOTA)
+ if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), 1) == NO_QUOTA)
return 1;
}
return 0;
@@ -64,8 +60,7 @@
extern __inline__ int DQUOT_ALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
{
if (sb->dq_op) {
- if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
- current->fsuid, 1) == NO_QUOTA)
+ if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), 0) == NO_QUOTA)
return 1;
}
return 0;
@@ -75,7 +70,7 @@
{
if (sb->dq_op) {
sb->dq_op->initialize (inode, -1);
- if (sb->dq_op->alloc_inode (inode, 1, current->fsuid))
+ if (sb->dq_op->alloc_inode (inode, 1))
return 1;
}
inode->i_flags |= S_QUOTA;
@@ -100,7 +95,7 @@

if (dentry->d_inode->i_sb->dq_op) {
dentry->d_inode->i_sb->dq_op->initialize(dentry->d_inode, -1);
- error = dentry->d_inode->i_sb->dq_op->transfer(dentry, iattr, current->fsuid);
+ error = dentry->d_inode->i_sb->dq_op->transfer(dentry, iattr);
} else {
error = notify_change(dentry, iattr);
}
--- linux/include/linux/fs.h Fri Dec 3 22:39:44 1999
+++ linux/include/linux/fs.h Fri Dec 3 22:45:05 1999
@@ -678,11 +678,11 @@
struct dquot_operations {
void (*initialize) (struct inode *, short);
void (*drop) (struct inode *);
- int (*alloc_block) (const struct inode *, unsigned long, uid_t, char);
- int (*alloc_inode) (const struct inode *, unsigned long, uid_t);
+ int (*alloc_block) (const struct inode *, unsigned long, char);
+ int (*alloc_inode) (const struct inode *, unsigned long);
void (*free_block) (const struct inode *, unsigned long);
void (*free_inode) (const struct inode *, unsigned long);
- int (*transfer) (struct dentry *, struct iattr *, uid_t);
+ int (*transfer) (struct dentry *, struct iattr *);
};

struct file_system_type {
--- linux/fs/dquot.c Fri Dec 3 22:39:03 1999
+++ linux/fs/dquot.c Fri Dec 3 22:58:29 1999
@@ -786,110 +786,113 @@
dquot->dq_flags |= DQ_MOD;
}

-static inline char need_print_warning(short type, uid_t initiator, struct dquot *dquot)
+static inline int need_print_warning(struct dquot *dquot, int flag)
{
- switch (type) {
+ switch (dquot->dq_type) {
case USRQUOTA:
- return(initiator == dquot->dq_id);
+ return current->fsuid == dquot->dq_id && !(dquot->dq_flags & flag);
case GRPQUOTA:
- return(initiator == dquot->dq_id);
+ return in_group_p(dquot->dq_id) && !(dquot->dq_flags & flag);
}
- return(0);
+ return 0;
+}
+
+static void print_warning(struct dquot *dquot, int flag, char *fmtstr, ...)
+{
+ va_list args;
+
+ if (!need_print_warning(dquot, flag))
+ return;
+ va_start(args, fmtstr);
+ vsprintf(quotamessage, fmtstr, args);
+ va_end(args);
+ tty_write_message(current->tty, quotamessage);
+ dquot->dq_flags |= flag;
}

-static inline char ignore_hardlimit(struct dquot *dquot, uid_t initiator)
+static inline char ignore_hardlimit(struct dquot *dquot)
{
- return(initiator == 0 && dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type] == 0);
+ return capable(CAP_SYS_RESOURCE) && !dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type];
}

-static int check_idq(struct dquot *dquot, short type, u_long inodes, uid_t initiator,
- struct tty_struct *tty)
+static int check_idq(struct dquot *dquot, u_long inodes)
{
+ short type = dquot->dq_type;
+
if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
- return(QUOTA_OK);
+ return QUOTA_OK;

if (dquot->dq_ihardlimit &&
(dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit &&
- !ignore_hardlimit(dquot, initiator)) {
- if ((dquot->dq_flags & DQ_INODES) == 0 &&
- need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: write failed, %s file limit reached\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- dquot->dq_flags |= DQ_INODES;
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ print_warning(dquot, DQ_INODES, "%s: write failed, %s file limit reached\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}

if (dquot->dq_isoftlimit &&
(dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime &&
- !ignore_hardlimit(dquot, initiator)) {
- if (need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ print_warning(dquot, DQ_INODES, "%s: warning, %s file quota exceeded too long.\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}

if (dquot->dq_isoftlimit &&
(dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
dquot->dq_itime == 0) {
- if (need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: warning, %s file quota exceeded\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- }
+ print_warning(dquot, 0, "%s: warning, %s file quota exceeded\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type];
}

- return(QUOTA_OK);
+ return QUOTA_OK;
}

-static int check_bdq(struct dquot *dquot, short type, u_long blocks, uid_t initiator,
- struct tty_struct *tty, char warn)
+static int check_bdq(struct dquot *dquot, u_long blocks, char prealloc)
{
+ short type = dquot->dq_type;
+
if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
- return(QUOTA_OK);
+ return QUOTA_OK;

if (dquot->dq_bhardlimit &&
(dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit &&
- !ignore_hardlimit(dquot, initiator)) {
- if (warn && (dquot->dq_flags & DQ_BLKS) == 0 &&
- need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: write failed, %s disk limit reached.\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- dquot->dq_flags |= DQ_BLKS;
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ if (!prealloc)
+ print_warning(dquot, DQ_BLKS, "%s: write failed, %s disk limit reached.\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}

if (dquot->dq_bsoftlimit &&
(dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime &&
- !ignore_hardlimit(dquot, initiator)) {
- if (warn && need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ if (!prealloc)
+ print_warning(dquot, DQ_BLKS, "%s: write failed, %s disk quota exceeded too long.\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}

if (dquot->dq_bsoftlimit &&
(dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
dquot->dq_btime == 0) {
- if (warn && need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: warning, %s disk quota exceeded\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
+ if (!prealloc) {
+ print_warning(dquot, 0, "%s: warning, %s disk quota exceeded\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
}
- dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
+ else
+ /*
+ * We don't allow preallocation to exceed softlimit so exceeding will
+ * be always printed
+ */
+ return NO_QUOTA;
}

- return(QUOTA_OK);
+ return QUOTA_OK;
}

/*
@@ -1102,11 +1105,9 @@
/*
* Note: this is a blocking operation.
*/
-int dquot_alloc_block(const struct inode *inode, unsigned long number, uid_t initiator,
- char warn)
+int dquot_alloc_block(const struct inode *inode, unsigned long number, char warn)
{
int cnt;
- struct tty_struct *tty = current->tty;
struct dquot *dquot[MAXQUOTAS];

for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1114,7 +1115,7 @@
if (dquot[cnt] == NODQUOT)
continue;
lock_dquot(dquot[cnt]);
- if (check_bdq(dquot[cnt], cnt, number, initiator, tty, warn))
+ if (check_bdq(dquot[cnt], number, warn))
goto put_all;
}

@@ -1140,10 +1141,9 @@
/*
* Note: this is a blocking operation.
*/
-int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t initiator)
+int dquot_alloc_inode(const struct inode *inode, unsigned long number)
{
int cnt;
- struct tty_struct *tty = current->tty;
struct dquot *dquot[MAXQUOTAS];

for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1151,7 +1151,7 @@
if (dquot[cnt] == NODQUOT)
continue;
lock_dquot(dquot[cnt]);
- if (check_idq(dquot[cnt], cnt, number, initiator, tty))
+ if (check_idq(dquot[cnt], number))
goto put_all;
}

@@ -1213,13 +1213,12 @@
*
* Note: this is a blocking operation.
*/
-int dquot_transfer(struct dentry *dentry, struct iattr *iattr, uid_t initiator)
+int dquot_transfer(struct dentry *dentry, struct iattr *iattr)
{
struct inode *inode = dentry -> d_inode;
unsigned long blocks;
struct dquot *transfer_from[MAXQUOTAS];
struct dquot *transfer_to[MAXQUOTAS];
- struct tty_struct *tty = current->tty;
short cnt, disc;
int error = -EDQUOT;

@@ -1293,8 +1292,8 @@
* invalidated or locked...
*/
if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt ||
- check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA ||
- check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) {
+ check_idq(transfer_to[cnt], 1) == NO_QUOTA ||
+ check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) {
cnt++;
goto put_all;
}

--i9LlY+UWpKt15+FH--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/