Commit df38988c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] quota semaphore fix

The second quota locking fix.  Sorry, I seem to have misplaced the
changelog.
parent 9a747377
This diff is collapsed.
...@@ -1239,6 +1239,12 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr) ...@@ -1239,6 +1239,12 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
error = inode_change_ok(inode, iattr); error = inode_change_ok(inode, iattr);
if (error) if (error)
return error; return error;
if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
(iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
error = DQUOT_TRANSFER(inode, iattr) ? -EDQUOT : 0;
if (error)
return error;
}
inode_setattr(inode, iattr); inode_setattr(inode, iattr);
if (iattr->ia_valid & ATTR_MODE) if (iattr->ia_valid & ATTR_MODE)
error = ext2_acl_chmod(inode); error = ext2_acl_chmod(inode);
......
...@@ -123,13 +123,13 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, cadd ...@@ -123,13 +123,13 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, cadd
case Q_GETFMT: { case Q_GETFMT: {
__u32 fmt; __u32 fmt;
down_read(&sb_dqopt(sb)->dqoff_sem); down_read(&sb_dqopt(sb)->dqptr_sem);
if (!sb_has_quota_enabled(sb, type)) { if (!sb_has_quota_enabled(sb, type)) {
up_read(&sb_dqopt(sb)->dqoff_sem); up_read(&sb_dqopt(sb)->dqptr_sem);
return -ESRCH; return -ESRCH;
} }
fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
up_read(&sb_dqopt(sb)->dqoff_sem); up_read(&sb_dqopt(sb)->dqptr_sem);
if (copy_to_user(addr, &fmt, sizeof(fmt))) if (copy_to_user(addr, &fmt, sizeof(fmt)))
return -EFAULT; return -EFAULT;
return 0; return 0;
......
...@@ -71,7 +71,8 @@ static struct super_block *alloc_super(void) ...@@ -71,7 +71,8 @@ static struct super_block *alloc_super(void)
atomic_set(&s->s_active, 1); atomic_set(&s->s_active, 1);
sema_init(&s->s_vfs_rename_sem,1); sema_init(&s->s_vfs_rename_sem,1);
sema_init(&s->s_dquot.dqio_sem, 1); sema_init(&s->s_dquot.dqio_sem, 1);
init_rwsem(&s->s_dquot.dqoff_sem); sema_init(&s->s_dquot.dqonoff_sem, 1);
init_rwsem(&s->s_dquot.dqptr_sem);
s->s_maxbytes = MAX_NON_LFS; s->s_maxbytes = MAX_NON_LFS;
s->dq_op = sb_dquot_ops; s->dq_op = sb_dquot_ops;
s->s_qcop = sb_quotactl_ops; s->s_qcop = sb_quotactl_ops;
......
...@@ -280,7 +280,8 @@ struct quota_format_type { ...@@ -280,7 +280,8 @@ struct quota_format_type {
struct quota_info { struct quota_info {
unsigned int flags; /* Flags for diskquotas on this device */ unsigned int flags; /* Flags for diskquotas on this device */
struct semaphore dqio_sem; /* lock device while I/O in progress */ struct semaphore dqio_sem; /* lock device while I/O in progress */
struct rw_semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device and ops using quota_info struct, pointers from inode to dquots */ struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */
struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */
struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment