userns: Convert quota
[deliverable/linux.git] / fs / quota / dquot.c
index 36a29b753c79c709175ebfd788196d1ecad948b5..c4564d0a4a9bb604336401879d06138c3676fbfe 100644 (file)
@@ -253,8 +253,10 @@ static qsize_t inode_get_rsv_space(struct inode *inode);
 static void __dquot_initialize(struct inode *inode, int type);
 
 static inline unsigned int
-hashfn(const struct super_block *sb, unsigned int id, int type)
+hashfn(const struct super_block *sb, struct kqid qid)
 {
+       unsigned int id = from_kqid(&init_user_ns, qid);
+       int type = qid.type;
        unsigned long tmp;
 
        tmp = (((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type);
@@ -267,7 +269,7 @@ hashfn(const struct super_block *sb, unsigned int id, int type)
 static inline void insert_dquot_hash(struct dquot *dquot)
 {
        struct hlist_head *head;
-       head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type);
+       head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id);
        hlist_add_head(&dquot->dq_hash, head);
 }
 
@@ -277,15 +279,14 @@ static inline void remove_dquot_hash(struct dquot *dquot)
 }
 
 static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb,
-                               unsigned int id, int type)
+                               struct kqid qid)
 {
        struct hlist_node *node;
        struct dquot *dquot;
 
        hlist_for_each (node, dquot_hash+hashent) {
                dquot = hlist_entry(node, struct dquot, dq_hash);
-               if (dquot->dq_sb == sb && dquot->dq_id == id &&
-                   dquot->dq_type == type)
+               if (dquot->dq_sb == sb && qid_eq(dquot->dq_id, qid))
                        return dquot;
        }
        return NULL;
@@ -351,7 +352,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
        spin_lock(&dq_list_lock);
        if (!test_and_set_bit(DQ_MOD_B, &dquot->dq_flags)) {
                list_add(&dquot->dq_dirty, &sb_dqopt(dquot->dq_sb)->
-                               info[dquot->dq_type].dqi_dirty_list);
+                               info[dquot->dq_id.type].dqi_dirty_list);
                ret = 0;
        }
        spin_unlock(&dq_list_lock);
@@ -410,17 +411,17 @@ int dquot_acquire(struct dquot *dquot)
        mutex_lock(&dquot->dq_lock);
        mutex_lock(&dqopt->dqio_mutex);
        if (!test_bit(DQ_READ_B, &dquot->dq_flags))
-               ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
+               ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
        if (ret < 0)
                goto out_iolock;
        set_bit(DQ_READ_B, &dquot->dq_flags);
        /* Instantiate dquot if needed */
        if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) {
-               ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
+               ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
                /* Write the info if needed */
-               if (info_dirty(&dqopt->info[dquot->dq_type])) {
-                       ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
-                                               dquot->dq_sb, dquot->dq_type);
+               if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
+                       ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info(
+                                       dquot->dq_sb, dquot->dq_id.type);
                }
                if (ret < 0)
                        goto out_iolock;
@@ -455,7 +456,7 @@ int dquot_commit(struct dquot *dquot)
        /* Inactive dquot can be only if there was error during read/init
         * => we have better not writing it */
        if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
-               ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
+               ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
        else
                ret = -EIO;
 out_sem:
@@ -477,12 +478,12 @@ int dquot_release(struct dquot *dquot)
        if (atomic_read(&dquot->dq_count) > 1)
                goto out_dqlock;
        mutex_lock(&dqopt->dqio_mutex);
-       if (dqopt->ops[dquot->dq_type]->release_dqblk) {
-               ret = dqopt->ops[dquot->dq_type]->release_dqblk(dquot);
+       if (dqopt->ops[dquot->dq_id.type]->release_dqblk) {
+               ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot);
                /* Write the info */
-               if (info_dirty(&dqopt->info[dquot->dq_type])) {
-                       ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
-                                               dquot->dq_sb, dquot->dq_type);
+               if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
+                       ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info(
+                                               dquot->dq_sb, dquot->dq_id.type);
                }
                if (ret >= 0)
                        ret = ret2;
@@ -521,7 +522,7 @@ restart:
        list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) {
                if (dquot->dq_sb != sb)
                        continue;
-               if (dquot->dq_type != type)
+               if (dquot->dq_id.type != type)
                        continue;
                /* Wait for dquot users */
                if (atomic_read(&dquot->dq_count)) {
@@ -741,7 +742,8 @@ void dqput(struct dquot *dquot)
 #ifdef CONFIG_QUOTA_DEBUG
        if (!atomic_read(&dquot->dq_count)) {
                quota_error(dquot->dq_sb, "trying to free free dquot of %s %d",
-                           quotatypes[dquot->dq_type], dquot->dq_id);
+                           quotatypes[dquot->dq_id.type],
+                           from_kqid(&init_user_ns, dquot->dq_id));
                BUG();
        }
 #endif
@@ -752,7 +754,7 @@ we_slept:
                /* We have more than one user... nothing to do */
                atomic_dec(&dquot->dq_count);
                /* Releasing dquot during quotaoff phase? */
-               if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_type) &&
+               if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_id.type) &&
                    atomic_read(&dquot->dq_count) == 1)
                        wake_up(&dquot->dq_wait_unused);
                spin_unlock(&dq_list_lock);
@@ -815,7 +817,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
        INIT_LIST_HEAD(&dquot->dq_dirty);
        init_waitqueue_head(&dquot->dq_wait_unused);
        dquot->dq_sb = sb;
-       dquot->dq_type = type;
+       dquot->dq_id = make_kqid_invalid(type);
        atomic_set(&dquot->dq_count, 1);
 
        return dquot;
@@ -829,35 +831,35 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
  *   a) checking for quota flags under dq_list_lock and
  *   b) getting a reference to dquot before we release dq_list_lock
  */
-struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
+struct dquot *dqget(struct super_block *sb, struct kqid qid)
 {
-       unsigned int hashent = hashfn(sb, id, type);
+       unsigned int hashent = hashfn(sb, qid);
        struct dquot *dquot = NULL, *empty = NULL;
 
-        if (!sb_has_quota_active(sb, type))
+        if (!sb_has_quota_active(sb, qid.type))
                return NULL;
 we_slept:
        spin_lock(&dq_list_lock);
        spin_lock(&dq_state_lock);
-       if (!sb_has_quota_active(sb, type)) {
+       if (!sb_has_quota_active(sb, qid.type)) {
                spin_unlock(&dq_state_lock);
                spin_unlock(&dq_list_lock);
                goto out;
        }
        spin_unlock(&dq_state_lock);
 
-       dquot = find_dquot(hashent, sb, id, type);
+       dquot = find_dquot(hashent, sb, qid);
        if (!dquot) {
                if (!empty) {
                        spin_unlock(&dq_list_lock);
-                       empty = get_empty_dquot(sb, type);
+                       empty = get_empty_dquot(sb, qid.type);
                        if (!empty)
                                schedule();     /* Try to wait for a moment... */
                        goto we_slept;
                }
                dquot = empty;
                empty = NULL;
-               dquot->dq_id = id;
+               dquot->dq_id = qid;
                /* all dquots go on the inuse_list */
                put_inuse(dquot);
                /* hash it first so it can be found */
@@ -1129,8 +1131,7 @@ static void dquot_decr_space(struct dquot *dquot, qsize_t number)
 
 struct dquot_warn {
        struct super_block *w_sb;
-       qid_t w_dq_id;
-       short w_dq_type;
+       struct kqid w_dq_id;
        short w_type;
 };
 
@@ -1154,11 +1155,11 @@ static int need_print_warning(struct dquot_warn *warn)
        if (!flag_print_warnings)
                return 0;
 
-       switch (warn->w_dq_type) {
+       switch (warn->w_dq_id.type) {
                case USRQUOTA:
-                       return current_fsuid() == warn->w_dq_id;
+                       return uid_eq(current_fsuid(), warn->w_dq_id.uid);
                case GRPQUOTA:
-                       return in_group_p(warn->w_dq_id);
+                       return in_group_p(warn->w_dq_id.gid);
        }
        return 0;
 }
@@ -1184,7 +1185,7 @@ static void print_warning(struct dquot_warn *warn)
                tty_write_message(tty, ": warning, ");
        else
                tty_write_message(tty, ": write failed, ");
-       tty_write_message(tty, quotatypes[warn->w_dq_type]);
+       tty_write_message(tty, quotatypes[warn->w_dq_id.type]);
        switch (warntype) {
                case QUOTA_NL_IHARDWARN:
                        msg = " file limit reached.\r\n";
@@ -1218,7 +1219,6 @@ static void prepare_warning(struct dquot_warn *warn, struct dquot *dquot,
        warn->w_type = warntype;
        warn->w_sb = dquot->dq_sb;
        warn->w_dq_id = dquot->dq_id;
-       warn->w_dq_type = dquot->dq_type;
 }
 
 /*
@@ -1236,14 +1236,14 @@ static void flush_warnings(struct dquot_warn *warn)
 #ifdef CONFIG_PRINT_QUOTA_WARNING
                print_warning(&warn[i]);
 #endif
-               quota_send_warning(warn[i].w_dq_type, warn[i].w_dq_id,
+               quota_send_warning(warn[i].w_dq_id,
                                   warn[i].w_sb->s_dev, warn[i].w_type);
        }
 }
 
 static int ignore_hardlimit(struct dquot *dquot)
 {
-       struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
+       struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
 
        return capable(CAP_SYS_RESOURCE) &&
               (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD ||
@@ -1256,7 +1256,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes,
 {
        qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes;
 
-       if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
+       if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) ||
            test_bit(DQ_FAKE_B, &dquot->dq_flags))
                return 0;
 
@@ -1281,7 +1281,7 @@ static int check_idq(struct dquot *dquot, qsize_t inodes,
            dquot->dq_dqb.dqb_itime == 0) {
                prepare_warning(warn, dquot, QUOTA_NL_ISOFTWARN);
                dquot->dq_dqb.dqb_itime = get_seconds() +
-                   sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
+                   sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace;
        }
 
        return 0;
@@ -1294,7 +1294,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc,
        qsize_t tspace;
        struct super_block *sb = dquot->dq_sb;
 
-       if (!sb_has_quota_limits_enabled(sb, dquot->dq_type) ||
+       if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) ||
            test_bit(DQ_FAKE_B, &dquot->dq_flags))
                return 0;
 
@@ -1325,7 +1325,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc,
                if (!prealloc) {
                        prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN);
                        dquot->dq_dqb.dqb_btime = get_seconds() +
-                           sb_dqopt(sb)->info[dquot->dq_type].dqi_bgrace;
+                           sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace;
                }
                else
                        /*
@@ -1344,7 +1344,7 @@ static int info_idq_free(struct dquot *dquot, qsize_t inodes)
 
        if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
            dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit ||
-           !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type))
+           !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type))
                return QUOTA_NL_NOWARN;
 
        newinodes = dquot->dq_dqb.dqb_curinodes - inodes;
@@ -1390,7 +1390,6 @@ static int dquot_active(const struct inode *inode)
  */
 static void __dquot_initialize(struct inode *inode, int type)
 {
-       unsigned int id = 0;
        int cnt;
        struct dquot *got[MAXQUOTAS];
        struct super_block *sb = inode->i_sb;
@@ -1403,18 +1402,19 @@ static void __dquot_initialize(struct inode *inode, int type)
 
        /* First get references to structures we might need. */
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               struct kqid qid;
                got[cnt] = NULL;
                if (type != -1 && cnt != type)
                        continue;
                switch (cnt) {
                case USRQUOTA:
-                       id = inode->i_uid;
+                       qid = make_kqid_uid(inode->i_uid);
                        break;
                case GRPQUOTA:
-                       id = inode->i_gid;
+                       qid = make_kqid_gid(inode->i_gid);
                        break;
                }
-               got[cnt] = dqget(sb, id, cnt);
+               got[cnt] = dqget(sb, qid);
        }
 
        down_write(&sb_dqopt(sb)->dqptr_sem);
@@ -1897,10 +1897,10 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
        if (!dquot_active(inode))
                return 0;
 
-       if (iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid)
-               transfer_to[USRQUOTA] = dqget(sb, iattr->ia_uid, USRQUOTA);
-       if (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)
-               transfer_to[GRPQUOTA] = dqget(sb, iattr->ia_gid, GRPQUOTA);
+       if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid))
+               transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(iattr->ia_uid));
+       if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))
+               transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(iattr->ia_gid));
 
        ret = __dquot_transfer(inode, transfer_to);
        dqput_all(transfer_to);
@@ -2360,9 +2360,9 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
 
        memset(di, 0, sizeof(*di));
        di->d_version = FS_DQUOT_VERSION;
-       di->d_flags = dquot->dq_type == USRQUOTA ?
+       di->d_flags = dquot->dq_id.type == USRQUOTA ?
                        FS_USER_QUOTA : FS_GROUP_QUOTA;
-       di->d_id = dquot->dq_id;
+       di->d_id = from_kqid_munged(current_user_ns(), dquot->dq_id);
 
        spin_lock(&dq_data_lock);
        di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit);
@@ -2376,12 +2376,12 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
        spin_unlock(&dq_data_lock);
 }
 
-int dquot_get_dqblk(struct super_block *sb, int type, qid_t id,
+int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
                    struct fs_disk_quota *di)
 {
        struct dquot *dquot;
 
-       dquot = dqget(sb, id, type);
+       dquot = dqget(sb, qid);
        if (!dquot)
                return -ESRCH;
        do_get_dqblk(dquot, di);
@@ -2401,7 +2401,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
 {
        struct mem_dqblk *dm = &dquot->dq_dqb;
        int check_blim = 0, check_ilim = 0;
-       struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
+       struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
 
        if (di->d_fieldmask & ~VFS_FS_DQ_MASK)
                return -EINVAL;
@@ -2488,13 +2488,13 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
        return 0;
 }
 
-int dquot_set_dqblk(struct super_block *sb, int type, qid_t id,
+int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
                  struct fs_disk_quota *di)
 {
        struct dquot *dquot;
        int rc;
 
-       dquot = dqget(sb, id, type);
+       dquot = dqget(sb, qid);
        if (!dquot) {
                rc = -ESRCH;
                goto out;
This page took 0.032714 seconds and 5 git commands to generate.