aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/quota/dquot.c32
-rw-r--r--include/linux/quota.h2
-rw-r--r--include/linux/quotaops.h2
3 files changed, 22 insertions, 14 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 5a831dc5ab28..4d2041fddefc 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -1695,15 +1695,13 @@ EXPORT_SYMBOL(dquot_free_inode);
1695 * This operation can block, but only after everything is updated 1695 * This operation can block, but only after everything is updated
1696 * A transaction must be started when entering this function. 1696 * A transaction must be started when entering this function.
1697 */ 1697 */
1698int dquot_transfer(struct inode *inode, struct iattr *iattr) 1698int dquot_transfer(struct inode *inode, qid_t *chid, unsigned long mask)
1699{ 1699{
1700 qsize_t space, cur_space; 1700 qsize_t space, cur_space;
1701 qsize_t rsv_space = 0; 1701 qsize_t rsv_space = 0;
1702 struct dquot *transfer_from[MAXQUOTAS]; 1702 struct dquot *transfer_from[MAXQUOTAS];
1703 struct dquot *transfer_to[MAXQUOTAS]; 1703 struct dquot *transfer_to[MAXQUOTAS];
1704 int cnt, ret = QUOTA_OK; 1704 int cnt, ret = QUOTA_OK;
1705 int chuid = iattr->ia_valid & ATTR_UID && inode->i_uid != iattr->ia_uid,
1706 chgid = iattr->ia_valid & ATTR_GID && inode->i_gid != iattr->ia_gid;
1707 char warntype_to[MAXQUOTAS]; 1705 char warntype_to[MAXQUOTAS];
1708 char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS]; 1706 char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS];
1709 1707
@@ -1717,13 +1715,10 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
1717 transfer_to[cnt] = NULL; 1715 transfer_to[cnt] = NULL;
1718 warntype_to[cnt] = QUOTA_NL_NOWARN; 1716 warntype_to[cnt] = QUOTA_NL_NOWARN;
1719 } 1717 }
1720 if (chuid) 1718 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1721 transfer_to[USRQUOTA] = dqget(inode->i_sb, iattr->ia_uid, 1719 if (mask & (1 << cnt))
1722 USRQUOTA); 1720 transfer_to[cnt] = dqget(inode->i_sb, chid[cnt], cnt);
1723 if (chgid) 1721 }
1724 transfer_to[GRPQUOTA] = dqget(inode->i_sb, iattr->ia_gid,
1725 GRPQUOTA);
1726
1727 down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); 1722 down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
1728 if (IS_NOQUOTA(inode)) { /* File without quota accounting? */ 1723 if (IS_NOQUOTA(inode)) { /* File without quota accounting? */
1729 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem); 1724 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
@@ -1799,12 +1794,25 @@ over_quota:
1799} 1794}
1800EXPORT_SYMBOL(dquot_transfer); 1795EXPORT_SYMBOL(dquot_transfer);
1801 1796
1802/* Wrapper for transferring ownership of an inode */ 1797/* Wrapper for transferring ownership of an inode for uid/gid only
1798 * Called from FSXXX_setattr()
1799 */
1803int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) 1800int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
1804{ 1801{
1802 qid_t chid[MAXQUOTAS];
1803 unsigned long mask = 0;
1804
1805 if (iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) {
1806 mask |= 1 << USRQUOTA;
1807 chid[USRQUOTA] = iattr->ia_uid;
1808 }
1809 if (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid) {
1810 mask |= 1 << GRPQUOTA;
1811 chid[GRPQUOTA] = iattr->ia_gid;
1812 }
1805 if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode)) { 1813 if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode)) {
1806 vfs_dq_init(inode); 1814 vfs_dq_init(inode);
1807 if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA) 1815 if (inode->i_sb->dq_op->transfer(inode, chid, mask) == NO_QUOTA)
1808 return 1; 1816 return 1;
1809 } 1817 }
1810 return 0; 1818 return 0;
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 92547a57e25a..edf34f2fe87d 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -301,7 +301,7 @@ struct dquot_operations {
301 int (*alloc_inode) (const struct inode *, qsize_t); 301 int (*alloc_inode) (const struct inode *, qsize_t);
302 int (*free_space) (struct inode *, qsize_t); 302 int (*free_space) (struct inode *, qsize_t);
303 int (*free_inode) (const struct inode *, qsize_t); 303 int (*free_inode) (const struct inode *, qsize_t);
304 int (*transfer) (struct inode *, struct iattr *); 304 int (*transfer) (struct inode *, qid_t *, unsigned long);
305 int (*write_dquot) (struct dquot *); /* Ordinary dquot write */ 305 int (*write_dquot) (struct dquot *); /* Ordinary dquot write */
306 struct dquot *(*alloc_dquot)(struct super_block *, int); /* Allocate memory for new dquot */ 306 struct dquot *(*alloc_dquot)(struct super_block *, int); /* Allocate memory for new dquot */
307 void (*destroy_dquot)(struct dquot *); /* Free memory for dquot */ 307 void (*destroy_dquot)(struct dquot *); /* Free memory for dquot */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index e563a20cff4f..e1cae204b5d9 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -43,7 +43,7 @@ void dquot_release_reserved_space(struct inode *inode, qsize_t number);
43int dquot_free_space(struct inode *inode, qsize_t number); 43int dquot_free_space(struct inode *inode, qsize_t number);
44int dquot_free_inode(const struct inode *inode, qsize_t number); 44int dquot_free_inode(const struct inode *inode, qsize_t number);
45 45
46int dquot_transfer(struct inode *inode, struct iattr *iattr); 46int dquot_transfer(struct inode *inode, qid_t *chid, unsigned long mask);
47int dquot_commit(struct dquot *dquot); 47int dquot_commit(struct dquot *dquot);
48int dquot_acquire(struct dquot *dquot); 48int dquot_acquire(struct dquot *dquot);
49int dquot_release(struct dquot *dquot); 49int dquot_release(struct dquot *dquot);