/* This routine is guarded by dqonoff_mutex mutex */
static void add_dquot_ref(struct super_block *sb, int type)
{
- struct inode *inode;
+ struct inode *inode, *old_inode = NULL;
-restart:
spin_lock(&inode_lock);
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
if (!atomic_read(&inode->i_writecount))
__iget(inode);
spin_unlock(&inode_lock);
+ iput(old_inode);
sb->dq_op->initialize(inode, type);
- iput(inode);
- /* As we may have blocked we had better restart... */
- goto restart;
+ /* We hold a reference to 'inode' so it couldn't have been
+ * removed from s_inodes list while we dropped the inode_lock.
+ * We cannot iput the inode now as we can be holding the last
+ * reference and we cannot iput it under inode_lock. So we
+ * keep the reference and iput it later. */
+ old_inode = inode;
+ spin_lock(&inode_lock);
}
spin_unlock(&inode_lock);
+ iput(old_inode);
}
/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
clear_bit(DQ_BLKS_B, &dquot->dq_flags);
}
+static int warning_issued(struct dquot *dquot, const int warntype)
+{
+ int flag = (warntype == QUOTA_NL_BHARDWARN ||
+ warntype == QUOTA_NL_BSOFTLONGWARN) ? DQ_BLKS_B :
+ ((warntype == QUOTA_NL_IHARDWARN ||
+ warntype == QUOTA_NL_ISOFTLONGWARN) ? DQ_INODES_B : 0);
+
+ if (!flag)
+ return 0;
+ return test_and_set_bit(flag, &dquot->dq_flags);
+}
+
#ifdef CONFIG_PRINT_QUOTA_WARNING
static int flag_print_warnings = 1;
}
/* Print warning to user which exceeded quota */
-static void print_warning(struct dquot *dquot, const char warntype)
+static void print_warning(struct dquot *dquot, const int warntype)
{
char *msg = NULL;
struct tty_struct *tty;
- int flag = (warntype == QUOTA_NL_BHARDWARN ||
- warntype == QUOTA_NL_BSOFTLONGWARN) ? DQ_BLKS_B :
- ((warntype == QUOTA_NL_IHARDWARN ||
- warntype == QUOTA_NL_ISOFTLONGWARN) ? DQ_INODES_B : 0);
- if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
+ if (!need_print_warning(dquot))
return;
mutex_lock(&tty_mutex);
#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
-/* Size of quota netlink message - actually an upperbound for buffer size */
-#define QUOTA_NL_MSG_SIZE 32
-
/* Netlink family structure for quota */
static struct genl_family quota_genl_family = {
.id = GENL_ID_GENERATE,
struct sk_buff *skb;
void *msg_head;
int ret;
+ int msg_size = 4 * nla_total_size(sizeof(u32)) +
+ 2 * nla_total_size(sizeof(u64));
/* We have to allocate using GFP_NOFS as we are called from a
* filesystem performing write and thus further recursion into
* the fs to free some data could cause deadlocks. */
- skb = genlmsg_new(QUOTA_NL_MSG_SIZE, GFP_NOFS);
+ skb = genlmsg_new(msg_size, GFP_NOFS);
if (!skb) {
printk(KERN_ERR
"VFS: Not enough memory to send quota warning.\n");
"VFS: Failed to send notification message: %d\n", ret);
return;
attr_err_out:
- printk(KERN_ERR "VFS: Failed to compose quota message: %d\n", ret);
+ printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
err_out:
kfree_skb(skb);
}
int i;
for (i = 0; i < MAXQUOTAS; i++)
- if (dquots[i] != NODQUOT && warntype[i] != QUOTA_NL_NOWARN) {
+ if (dquots[i] != NODQUOT && warntype[i] != QUOTA_NL_NOWARN &&
+ !warning_issued(dquots[i], warntype[i])) {
#ifdef CONFIG_PRINT_QUOTA_WARNING
print_warning(dquots[i], warntype[i]);
#endif
truncate_inode_pages(&toputinode[cnt]->i_data, 0);
mutex_unlock(&toputinode[cnt]->i_mutex);
mark_inode_dirty(toputinode[cnt]);
- iput(toputinode[cnt]);
}
+ iput(toputinode[cnt]);
mutex_unlock(&dqopt->dqonoff_mutex);
}
if (sb->s_bdev)
error = path_lookup(path, LOOKUP_FOLLOW, &nd);
if (error < 0)
return error;
- error = security_quota_on(nd.dentry);
+ error = security_quota_on(nd.path.dentry);
if (error)
goto out_path;
/* Quota file not on the same filesystem? */
- if (nd.mnt->mnt_sb != sb)
+ if (nd.path.mnt->mnt_sb != sb)
error = -EXDEV;
else
- error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
+ error = vfs_quota_on_inode(nd.path.dentry->d_inode, type,
+ format_id);
out_path:
- path_release(&nd);
+ path_put(&nd.path);
return error;
}