Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Apr 2015 02:19:33 +0000 (22:19 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Apr 2015 02:19:33 +0000 (22:19 -0400)
Pull quota and udf updates from Jan Kara:
 "The pull contains quota changes which complete unification of XFS and
  VFS quota interfaces (so tools can use either interface to manipulate
  any filesystem).  There's also a patch to support project quotas in
  VFS quota subsystem from Li Xi.

  Finally there's a bunch of UDF fixes and cleanups and tiny cleanup in
  reiserfs & ext3"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (21 commits)
  udf: Update ctime and mtime when directory is modified
  udf: return correct errno for udf_update_inode()
  ext3: Remove useless condition in if statement.
  vfs: Add general support to enforce project quota limits
  reiserfs: fix __RASSERT format string
  udf: use int for allocated blocks instead of sector_t
  udf: remove redundant buffer_head.h includes
  udf: remove else after return in __load_block_bitmap()
  udf: remove unused variable in udf_table_free_blocks()
  quota: Fix maximum quota limit settings
  quota: reorder flags in quota state
  quota: paranoia: check quota tree root
  quota: optimize i_dquot access
  quota: Hook up Q_XSETQLIM for id 0 to ->set_info
  xfs: Add support for Q_SETINFO
  quota: Make ->set_info use structure with neccesary info to VFS and XFS
  quota: Remove ->get_xstate and ->get_xstatev callbacks
  gfs2: Convert to using ->get_state callback
  xfs: Convert to using ->get_state callback
  quota: Wire up Q_GETXSTATE and Q_GETXSTATV calls to work with ->get_state
  ...

28 files changed:
fs/ext3/super.c
fs/ext3/xattr.c
fs/ext4/super.c
fs/gfs2/quota.c
fs/quota/dquot.c
fs/quota/quota.c
fs/quota/quota_tree.c
fs/quota/quota_v2.c
fs/quota/quotaio_v2.h
fs/reiserfs/reiserfs.h
fs/reiserfs/super.c
fs/udf/balloc.c
fs/udf/dir.c
fs/udf/directory.c
fs/udf/file.c
fs/udf/inode.c
fs/udf/misc.c
fs/udf/namei.c
fs/udf/partition.c
fs/udf/super.c
fs/udf/symlink.c
fs/udf/truncate.c
fs/xfs/xfs_qm.h
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_quotaops.c
include/linux/quota.h
include/linux/quotaops.h
include/uapi/linux/quota.h

index d4dbf3c259b3288a961304daff37d7e1a848e43f..f037b4b273002f5a6815da593cad35f59b81b890 100644 (file)
@@ -789,7 +789,7 @@ static const struct quotactl_ops ext3_qctl_operations = {
        .quota_on       = ext3_quota_on,
        .quota_off      = dquot_quota_off,
        .quota_sync     = dquot_quota_sync,
-       .get_info       = dquot_get_dqinfo,
+       .get_state      = dquot_get_state,
        .set_info       = dquot_set_dqinfo,
        .get_dqblk      = dquot_get_dqblk,
        .set_dqblk      = dquot_set_dqblk
index c6874be6d58b41f02bcaa3b93cf182845bd85bec..24215dc09a18f5ac876a6adfe4465b6e20ea6009 100644 (file)
@@ -546,8 +546,7 @@ ext3_xattr_set_entry(struct ext3_xattr_info *i, struct ext3_xattr_search *s)
                free += EXT3_XATTR_LEN(name_len);
        }
        if (i->value) {
-               if (free < EXT3_XATTR_SIZE(i->value_len) ||
-                   free < EXT3_XATTR_LEN(name_len) +
+               if (free < EXT3_XATTR_LEN(name_len) +
                           EXT3_XATTR_SIZE(i->value_len))
                        return -ENOSPC;
        }
index e061e66c82800f700b7642e4c82fa2cc836be05f..d348c7d29d801d92dfba884b0ca188b26e84fbf9 100644 (file)
@@ -1076,7 +1076,7 @@ static const struct quotactl_ops ext4_qctl_operations = {
        .quota_on       = ext4_quota_on,
        .quota_off      = ext4_quota_off,
        .quota_sync     = dquot_quota_sync,
-       .get_info       = dquot_get_dqinfo,
+       .get_state      = dquot_get_state,
        .set_info       = dquot_set_dqinfo,
        .get_dqblk      = dquot_get_dqblk,
        .set_dqblk      = dquot_set_dqblk
index 5c27e48aa76f57e1e070cfc89c0c99647fbea456..e3065cb9ab087530cc53e59525f1854c6d191686 100644 (file)
@@ -1494,32 +1494,34 @@ int gfs2_quotad(void *data)
        return 0;
 }
 
-static int gfs2_quota_get_xstate(struct super_block *sb,
-                                struct fs_quota_stat *fqs)
+static int gfs2_quota_get_state(struct super_block *sb, struct qc_state *state)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
 
-       memset(fqs, 0, sizeof(struct fs_quota_stat));
-       fqs->qs_version = FS_QSTAT_VERSION;
+       memset(state, 0, sizeof(*state));
 
        switch (sdp->sd_args.ar_quota) {
        case GFS2_QUOTA_ON:
-               fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD);
+               state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
+               state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
                /*FALLTHRU*/
        case GFS2_QUOTA_ACCOUNT:
-               fqs->qs_flags |= (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT);
+               state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED |
+                                                 QCI_SYSFILE;
+               state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED |
+                                                 QCI_SYSFILE;
                break;
        case GFS2_QUOTA_OFF:
                break;
        }
-
        if (sdp->sd_quota_inode) {
-               fqs->qs_uquota.qfs_ino = GFS2_I(sdp->sd_quota_inode)->i_no_addr;
-               fqs->qs_uquota.qfs_nblks = sdp->sd_quota_inode->i_blocks;
+               state->s_state[USRQUOTA].ino =
+                                       GFS2_I(sdp->sd_quota_inode)->i_no_addr;
+               state->s_state[USRQUOTA].blocks = sdp->sd_quota_inode->i_blocks;
        }
-       fqs->qs_uquota.qfs_nextents = 1; /* unsupported */
-       fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */
-       fqs->qs_incoredqs = list_lru_count(&gfs2_qd_lru);
+       state->s_state[USRQUOTA].nextents = 1;  /* unsupported */
+       state->s_state[GRPQUOTA] = state->s_state[USRQUOTA];
+       state->s_incoredqs = list_lru_count(&gfs2_qd_lru);
        return 0;
 }
 
@@ -1664,7 +1666,7 @@ out_put:
 
 const struct quotactl_ops gfs2_quotactl_ops = {
        .quota_sync     = gfs2_quota_sync,
-       .get_xstate     = gfs2_quota_get_xstate,
+       .get_state      = gfs2_quota_get_state,
        .get_dqblk      = gfs2_get_dqblk,
        .set_dqblk      = gfs2_set_dqblk,
 };
index 0ccd4ba3a2467f6783a396686b5ae20266ba515b..ecc25cf0ee6e99f96b8d4c7550d8881593c303cf 100644 (file)
@@ -900,14 +900,17 @@ static inline struct dquot **i_dquot(struct inode *inode)
 
 static int dqinit_needed(struct inode *inode, int type)
 {
+       struct dquot * const *dquots;
        int cnt;
 
        if (IS_NOQUOTA(inode))
                return 0;
+
+       dquots = i_dquot(inode);
        if (type != -1)
-               return !i_dquot(inode)[type];
+               return !dquots[type];
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if (!i_dquot(inode)[cnt])
+               if (!dquots[cnt])
                        return 1;
        return 0;
 }
@@ -970,12 +973,13 @@ static void add_dquot_ref(struct super_block *sb, int type)
 static void remove_inode_dquot_ref(struct inode *inode, int type,
                                   struct list_head *tofree_head)
 {
-       struct dquot *dquot = i_dquot(inode)[type];
+       struct dquot **dquots = i_dquot(inode);
+       struct dquot *dquot = dquots[type];
 
-       i_dquot(inode)[type] = NULL;
        if (!dquot)
                return;
 
+       dquots[type] = NULL;
        if (list_empty(&dquot->dq_free)) {
                /*
                 * The inode still has reference to dquot so it can't be in the
@@ -1159,8 +1163,8 @@ static int need_print_warning(struct dquot_warn *warn)
                        return uid_eq(current_fsuid(), warn->w_dq_id.uid);
                case GRPQUOTA:
                        return in_group_p(warn->w_dq_id.gid);
-               case PRJQUOTA:  /* Never taken... Just make gcc happy */
-                       return 0;
+               case PRJQUOTA:
+                       return 1;
        }
        return 0;
 }
@@ -1389,16 +1393,21 @@ static int dquot_active(const struct inode *inode)
 static void __dquot_initialize(struct inode *inode, int type)
 {
        int cnt, init_needed = 0;
-       struct dquot *got[MAXQUOTAS];
+       struct dquot **dquots, *got[MAXQUOTAS];
        struct super_block *sb = inode->i_sb;
        qsize_t rsv;
 
        if (!dquot_active(inode))
                return;
 
+       dquots = i_dquot(inode);
+
        /* First get references to structures we might need. */
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                struct kqid qid;
+               kprojid_t projid;
+               int rc;
+
                got[cnt] = NULL;
                if (type != -1 && cnt != type)
                        continue;
@@ -1407,8 +1416,12 @@ static void __dquot_initialize(struct inode *inode, int type)
                 * we check it without locking here to avoid unnecessary
                 * dqget()/dqput() calls.
                 */
-               if (i_dquot(inode)[cnt])
+               if (dquots[cnt])
+                       continue;
+
+               if (!sb_has_quota_active(sb, cnt))
                        continue;
+
                init_needed = 1;
 
                switch (cnt) {
@@ -1418,6 +1431,12 @@ static void __dquot_initialize(struct inode *inode, int type)
                case GRPQUOTA:
                        qid = make_kqid_gid(inode->i_gid);
                        break;
+               case PRJQUOTA:
+                       rc = inode->i_sb->dq_op->get_projid(inode, &projid);
+                       if (rc)
+                               continue;
+                       qid = make_kqid_projid(projid);
+                       break;
                }
                got[cnt] = dqget(sb, qid);
        }
@@ -1438,8 +1457,8 @@ static void __dquot_initialize(struct inode *inode, int type)
                /* We could race with quotaon or dqget() could have failed */
                if (!got[cnt])
                        continue;
-               if (!i_dquot(inode)[cnt]) {
-                       i_dquot(inode)[cnt] = got[cnt];
+               if (!dquots[cnt]) {
+                       dquots[cnt] = got[cnt];
                        got[cnt] = NULL;
                        /*
                         * Make quota reservation system happy if someone
@@ -1447,7 +1466,7 @@ static void __dquot_initialize(struct inode *inode, int type)
                         */
                        rsv = inode_get_rsv_space(inode);
                        if (unlikely(rsv))
-                               dquot_resv_space(i_dquot(inode)[cnt], rsv);
+                               dquot_resv_space(dquots[cnt], rsv);
                }
        }
 out_err:
@@ -1473,12 +1492,13 @@ EXPORT_SYMBOL(dquot_initialize);
 static void __dquot_drop(struct inode *inode)
 {
        int cnt;
+       struct dquot **dquots = i_dquot(inode);
        struct dquot *put[MAXQUOTAS];
 
        spin_lock(&dq_data_lock);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               put[cnt] = i_dquot(inode)[cnt];
-               i_dquot(inode)[cnt] = NULL;
+               put[cnt] = dquots[cnt];
+               dquots[cnt] = NULL;
        }
        spin_unlock(&dq_data_lock);
        dqput_all(put);
@@ -1486,6 +1506,7 @@ static void __dquot_drop(struct inode *inode)
 
 void dquot_drop(struct inode *inode)
 {
+       struct dquot * const *dquots;
        int cnt;
 
        if (IS_NOQUOTA(inode))
@@ -1498,8 +1519,9 @@ void dquot_drop(struct inode *inode)
         * must assure that nobody can come after the DQUOT_DROP and
         * add quota pointers back anyway.
         */
+       dquots = i_dquot(inode);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (i_dquot(inode)[cnt])
+               if (dquots[cnt])
                        break;
        }
 
@@ -1600,8 +1622,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
 {
        int cnt, ret = 0, index;
        struct dquot_warn warn[MAXQUOTAS];
-       struct dquot **dquots = i_dquot(inode);
        int reserve = flags & DQUOT_SPACE_RESERVE;
+       struct dquot **dquots;
 
        if (!dquot_active(inode)) {
                inode_incr_space(inode, number, reserve);
@@ -1611,6 +1633,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                warn[cnt].w_type = QUOTA_NL_NOWARN;
 
+       dquots = i_dquot(inode);
        index = srcu_read_lock(&dquot_srcu);
        spin_lock(&dq_data_lock);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1652,13 +1675,14 @@ int dquot_alloc_inode(struct inode *inode)
 {
        int cnt, ret = 0, index;
        struct dquot_warn warn[MAXQUOTAS];
-       struct dquot * const *dquots = i_dquot(inode);
+       struct dquot * const *dquots;
 
        if (!dquot_active(inode))
                return 0;
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                warn[cnt].w_type = QUOTA_NL_NOWARN;
 
+       dquots = i_dquot(inode);
        index = srcu_read_lock(&dquot_srcu);
        spin_lock(&dq_data_lock);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1690,6 +1714,7 @@ EXPORT_SYMBOL(dquot_alloc_inode);
  */
 int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
 {
+       struct dquot **dquots;
        int cnt, index;
 
        if (!dquot_active(inode)) {
@@ -1697,18 +1722,18 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
                return 0;
        }
 
+       dquots = i_dquot(inode);
        index = srcu_read_lock(&dquot_srcu);
        spin_lock(&dq_data_lock);
        /* Claim reserved quotas to allocated quotas */
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (i_dquot(inode)[cnt])
-                       dquot_claim_reserved_space(i_dquot(inode)[cnt],
-                                                       number);
+               if (dquots[cnt])
+                       dquot_claim_reserved_space(dquots[cnt], number);
        }
        /* Update inode bytes */
        inode_claim_rsv_space(inode, number);
        spin_unlock(&dq_data_lock);
-       mark_all_dquot_dirty(i_dquot(inode));
+       mark_all_dquot_dirty(dquots);
        srcu_read_unlock(&dquot_srcu, index);
        return 0;
 }
@@ -1719,6 +1744,7 @@ EXPORT_SYMBOL(dquot_claim_space_nodirty);
  */
 void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
 {
+       struct dquot **dquots;
        int cnt, index;
 
        if (!dquot_active(inode)) {
@@ -1726,18 +1752,18 @@ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
                return;
        }
 
+       dquots = i_dquot(inode);
        index = srcu_read_lock(&dquot_srcu);
        spin_lock(&dq_data_lock);
        /* Claim reserved quotas to allocated quotas */
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-               if (i_dquot(inode)[cnt])
-                       dquot_reclaim_reserved_space(i_dquot(inode)[cnt],
-                                                    number);
+               if (dquots[cnt])
+                       dquot_reclaim_reserved_space(dquots[cnt], number);
        }
        /* Update inode bytes */
        inode_reclaim_rsv_space(inode, number);
        spin_unlock(&dq_data_lock);
-       mark_all_dquot_dirty(i_dquot(inode));
+       mark_all_dquot_dirty(dquots);
        srcu_read_unlock(&dquot_srcu, index);
        return;
 }
@@ -1750,7 +1776,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
 {
        unsigned int cnt;
        struct dquot_warn warn[MAXQUOTAS];
-       struct dquot **dquots = i_dquot(inode);
+       struct dquot **dquots;
        int reserve = flags & DQUOT_SPACE_RESERVE, index;
 
        if (!dquot_active(inode)) {
@@ -1758,6 +1784,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
                return;
        }
 
+       dquots = i_dquot(inode);
        index = srcu_read_lock(&dquot_srcu);
        spin_lock(&dq_data_lock);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1793,12 +1820,13 @@ void dquot_free_inode(struct inode *inode)
 {
        unsigned int cnt;
        struct dquot_warn warn[MAXQUOTAS];
-       struct dquot * const *dquots = i_dquot(inode);
+       struct dquot * const *dquots;
        int index;
 
        if (!dquot_active(inode))
                return;
 
+       dquots = i_dquot(inode);
        index = srcu_read_lock(&dquot_srcu);
        spin_lock(&dq_data_lock);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -2161,7 +2189,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
                error = -EROFS;
                goto out_fmt;
        }
-       if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
+       if (!sb->s_op->quota_write || !sb->s_op->quota_read ||
+           (type == PRJQUOTA && sb->dq_op->get_projid == NULL)) {
                error = -EINVAL;
                goto out_fmt;
        }
@@ -2614,55 +2643,73 @@ out:
 EXPORT_SYMBOL(dquot_set_dqblk);
 
 /* Generic routine for getting common part of quota file information */
-int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
+int dquot_get_state(struct super_block *sb, struct qc_state *state)
 {
        struct mem_dqinfo *mi;
+       struct qc_type_state *tstate;
+       struct quota_info *dqopt = sb_dqopt(sb);
+       int type;
   
        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
-       if (!sb_has_quota_active(sb, type)) {
-               mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
-               return -ESRCH;
+       memset(state, 0, sizeof(*state));
+       for (type = 0; type < MAXQUOTAS; type++) {
+               if (!sb_has_quota_active(sb, type))
+                       continue;
+               tstate = state->s_state + type;
+               mi = sb_dqopt(sb)->info + type;
+               tstate->flags = QCI_ACCT_ENABLED;
+               spin_lock(&dq_data_lock);
+               if (mi->dqi_flags & DQF_SYS_FILE)
+                       tstate->flags |= QCI_SYSFILE;
+               if (mi->dqi_flags & DQF_ROOT_SQUASH)
+                       tstate->flags |= QCI_ROOT_SQUASH;
+               if (sb_has_quota_limits_enabled(sb, type))
+                       tstate->flags |= QCI_LIMITS_ENFORCED;
+               tstate->spc_timelimit = mi->dqi_bgrace;
+               tstate->ino_timelimit = mi->dqi_igrace;
+               tstate->ino = dqopt->files[type]->i_ino;
+               tstate->blocks = dqopt->files[type]->i_blocks;
+               tstate->nextents = 1;   /* We don't know... */
+               spin_unlock(&dq_data_lock);
        }
-       mi = sb_dqopt(sb)->info + type;
-       spin_lock(&dq_data_lock);
-       ii->dqi_bgrace = mi->dqi_bgrace;
-       ii->dqi_igrace = mi->dqi_igrace;
-       ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK;
-       ii->dqi_valid = IIF_ALL;
-       spin_unlock(&dq_data_lock);
        mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
        return 0;
 }
-EXPORT_SYMBOL(dquot_get_dqinfo);
+EXPORT_SYMBOL(dquot_get_state);
 
 /* Generic routine for setting common part of quota file information */
-int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
+int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii)
 {
        struct mem_dqinfo *mi;
        int err = 0;
 
+       if ((ii->i_fieldmask & QC_WARNS_MASK) ||
+           (ii->i_fieldmask & QC_RT_SPC_TIMER))
+               return -EINVAL;
        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
        if (!sb_has_quota_active(sb, type)) {
                err = -ESRCH;
                goto out;
        }
        mi = sb_dqopt(sb)->info + type;
-       if (ii->dqi_valid & IIF_FLAGS) {
-               if (ii->dqi_flags & ~DQF_SETINFO_MASK ||
-                   (ii->dqi_flags & DQF_ROOT_SQUASH &&
+       if (ii->i_fieldmask & QC_FLAGS) {
+               if ((ii->i_flags & QCI_ROOT_SQUASH &&
                     mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) {
                        err = -EINVAL;
                        goto out;
                }
        }
        spin_lock(&dq_data_lock);
-       if (ii->dqi_valid & IIF_BGRACE)
-               mi->dqi_bgrace = ii->dqi_bgrace;
-       if (ii->dqi_valid & IIF_IGRACE)
-               mi->dqi_igrace = ii->dqi_igrace;
-       if (ii->dqi_valid & IIF_FLAGS)
-               mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) |
-                               (ii->dqi_flags & DQF_SETINFO_MASK);
+       if (ii->i_fieldmask & QC_SPC_TIMER)
+               mi->dqi_bgrace = ii->i_spc_timelimit;
+       if (ii->i_fieldmask & QC_INO_TIMER)
+               mi->dqi_igrace = ii->i_ino_timelimit;
+       if (ii->i_fieldmask & QC_FLAGS) {
+               if (ii->i_flags & QCI_ROOT_SQUASH)
+                       mi->dqi_flags |= DQF_ROOT_SQUASH;
+               else
+                       mi->dqi_flags &= ~DQF_ROOT_SQUASH;
+       }
        spin_unlock(&dq_data_lock);
        mark_info_dirty(sb, type);
        /* Force write to disk */
@@ -2677,7 +2724,7 @@ const struct quotactl_ops dquot_quotactl_ops = {
        .quota_on       = dquot_quota_on,
        .quota_off      = dquot_quota_off,
        .quota_sync     = dquot_quota_sync,
-       .get_info       = dquot_get_dqinfo,
+       .get_state      = dquot_get_state,
        .set_info       = dquot_set_dqinfo,
        .get_dqblk      = dquot_get_dqblk,
        .set_dqblk      = dquot_set_dqblk
@@ -2688,7 +2735,7 @@ const struct quotactl_ops dquot_quotactl_sysfile_ops = {
        .quota_enable   = dquot_quota_enable,
        .quota_disable  = dquot_quota_disable,
        .quota_sync     = dquot_quota_sync,
-       .get_info       = dquot_get_dqinfo,
+       .get_state      = dquot_get_state,
        .set_info       = dquot_set_dqinfo,
        .get_dqblk      = dquot_get_dqblk,
        .set_dqblk      = dquot_set_dqblk
index d14a799c77850e6a1dc8ca762244f325721785a7..86ded7375c216d55fe26eb1dfd6ff366ce1fa29d 100644 (file)
@@ -118,13 +118,30 @@ static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
 
 static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
 {
-       struct if_dqinfo info;
+       struct qc_state state;
+       struct qc_type_state *tstate;
+       struct if_dqinfo uinfo;
        int ret;
 
-       if (!sb->s_qcop->get_info)
+       /* This checks whether qc_state has enough entries... */
+       BUILD_BUG_ON(MAXQUOTAS > XQM_MAXQUOTAS);
+       if (!sb->s_qcop->get_state)
                return -ENOSYS;
-       ret = sb->s_qcop->get_info(sb, type, &info);
-       if (!ret && copy_to_user(addr, &info, sizeof(info)))
+       ret = sb->s_qcop->get_state(sb, &state);
+       if (ret)
+               return ret;
+       tstate = state.s_state + type;
+       if (!(tstate->flags & QCI_ACCT_ENABLED))
+               return -ESRCH;
+       memset(&uinfo, 0, sizeof(uinfo));
+       uinfo.dqi_bgrace = tstate->spc_timelimit;
+       uinfo.dqi_igrace = tstate->ino_timelimit;
+       if (tstate->flags & QCI_SYSFILE)
+               uinfo.dqi_flags |= DQF_SYS_FILE;
+       if (tstate->flags & QCI_ROOT_SQUASH)
+               uinfo.dqi_flags |= DQF_ROOT_SQUASH;
+       uinfo.dqi_valid = IIF_ALL;
+       if (!ret && copy_to_user(addr, &uinfo, sizeof(uinfo)))
                return -EFAULT;
        return ret;
 }
@@ -132,12 +149,31 @@ static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
 static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
 {
        struct if_dqinfo info;
+       struct qc_info qinfo;
 
        if (copy_from_user(&info, addr, sizeof(info)))
                return -EFAULT;
        if (!sb->s_qcop->set_info)
                return -ENOSYS;
-       return sb->s_qcop->set_info(sb, type, &info);
+       if (info.dqi_valid & ~(IIF_FLAGS | IIF_BGRACE | IIF_IGRACE))
+               return -EINVAL;
+       memset(&qinfo, 0, sizeof(qinfo));
+       if (info.dqi_valid & IIF_FLAGS) {
+               if (info.dqi_flags & ~DQF_SETINFO_MASK)
+                       return -EINVAL;
+               if (info.dqi_flags & DQF_ROOT_SQUASH)
+                       qinfo.i_flags |= QCI_ROOT_SQUASH;
+               qinfo.i_fieldmask |= QC_FLAGS;
+       }
+       if (info.dqi_valid & IIF_BGRACE) {
+               qinfo.i_spc_timelimit = info.dqi_bgrace;
+               qinfo.i_fieldmask |= QC_SPC_TIMER;
+       }
+       if (info.dqi_valid & IIF_IGRACE) {
+               qinfo.i_ino_timelimit = info.dqi_igrace;
+               qinfo.i_fieldmask |= QC_INO_TIMER;
+       }
+       return sb->s_qcop->set_info(sb, type, &qinfo);
 }
 
 static inline qsize_t qbtos(qsize_t blocks)
@@ -252,25 +288,149 @@ static int quota_disable(struct super_block *sb, void __user *addr)
        return sb->s_qcop->quota_disable(sb, flags);
 }
 
+static int quota_state_to_flags(struct qc_state *state)
+{
+       int flags = 0;
+
+       if (state->s_state[USRQUOTA].flags & QCI_ACCT_ENABLED)
+               flags |= FS_QUOTA_UDQ_ACCT;
+       if (state->s_state[USRQUOTA].flags & QCI_LIMITS_ENFORCED)
+               flags |= FS_QUOTA_UDQ_ENFD;
+       if (state->s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)
+               flags |= FS_QUOTA_GDQ_ACCT;
+       if (state->s_state[GRPQUOTA].flags & QCI_LIMITS_ENFORCED)
+               flags |= FS_QUOTA_GDQ_ENFD;
+       if (state->s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED)
+               flags |= FS_QUOTA_PDQ_ACCT;
+       if (state->s_state[PRJQUOTA].flags & QCI_LIMITS_ENFORCED)
+               flags |= FS_QUOTA_PDQ_ENFD;
+       return flags;
+}
+
+static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs)
+{
+       int type;
+       struct qc_state state;
+       int ret;
+
+       ret = sb->s_qcop->get_state(sb, &state);
+       if (ret < 0)
+               return ret;
+
+       memset(fqs, 0, sizeof(*fqs));
+       fqs->qs_version = FS_QSTAT_VERSION;
+       fqs->qs_flags = quota_state_to_flags(&state);
+       /* No quota enabled? */
+       if (!fqs->qs_flags)
+               return -ENOSYS;
+       fqs->qs_incoredqs = state.s_incoredqs;
+       /*
+        * GETXSTATE quotactl has space for just one set of time limits so
+        * report them for the first enabled quota type
+        */
+       for (type = 0; type < XQM_MAXQUOTAS; type++)
+               if (state.s_state[type].flags & QCI_ACCT_ENABLED)
+                       break;
+       BUG_ON(type == XQM_MAXQUOTAS);
+       fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
+       fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
+       fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
+       fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
+       fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
+       if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) {
+               fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
+               fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
+               fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
+       }
+       if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) {
+               fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
+               fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
+               fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
+       }
+       if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) {
+               /*
+                * Q_XGETQSTAT doesn't have room for both group and project
+                * quotas.  So, allow the project quota values to be copied out
+                * only if there is no group quota information available.
+                */
+               if (!(state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)) {
+                       fqs->qs_gquota.qfs_ino = state.s_state[PRJQUOTA].ino;
+                       fqs->qs_gquota.qfs_nblks =
+                                       state.s_state[PRJQUOTA].blocks;
+                       fqs->qs_gquota.qfs_nextents =
+                                       state.s_state[PRJQUOTA].nextents;
+               }
+       }
+       return 0;
+}
+
 static int quota_getxstate(struct super_block *sb, void __user *addr)
 {
        struct fs_quota_stat fqs;
        int ret;
 
-       if (!sb->s_qcop->get_xstate)
+       if (!sb->s_qcop->get_state)
                return -ENOSYS;
-       ret = sb->s_qcop->get_xstate(sb, &fqs);
+       ret = quota_getstate(sb, &fqs);
        if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
                return -EFAULT;
        return ret;
 }
 
+static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs)
+{
+       int type;
+       struct qc_state state;
+       int ret;
+
+       ret = sb->s_qcop->get_state(sb, &state);
+       if (ret < 0)
+               return ret;
+
+       memset(fqs, 0, sizeof(*fqs));
+       fqs->qs_version = FS_QSTAT_VERSION;
+       fqs->qs_flags = quota_state_to_flags(&state);
+       /* No quota enabled? */
+       if (!fqs->qs_flags)
+               return -ENOSYS;
+       fqs->qs_incoredqs = state.s_incoredqs;
+       /*
+        * GETXSTATV quotactl has space for just one set of time limits so
+        * report them for the first enabled quota type
+        */
+       for (type = 0; type < XQM_MAXQUOTAS; type++)
+               if (state.s_state[type].flags & QCI_ACCT_ENABLED)
+                       break;
+       BUG_ON(type == XQM_MAXQUOTAS);
+       fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
+       fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
+       fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
+       fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
+       fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
+       if (state.s_state[USRQUOTA].flags & QCI_ACCT_ENABLED) {
+               fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
+               fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
+               fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
+       }
+       if (state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED) {
+               fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
+               fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
+               fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
+       }
+       if (state.s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED) {
+               fqs->qs_pquota.qfs_ino = state.s_state[PRJQUOTA].ino;
+               fqs->qs_pquota.qfs_nblks = state.s_state[PRJQUOTA].blocks;
+               fqs->qs_pquota.qfs_nextents = state.s_state[PRJQUOTA].nextents;
+       }
+       return 0;
+}
+
 static int quota_getxstatev(struct super_block *sb, void __user *addr)
 {
        struct fs_quota_statv fqs;
        int ret;
 
-       if (!sb->s_qcop->get_xstatev)
+       if (!sb->s_qcop->get_state)
                return -ENOSYS;
 
        memset(&fqs, 0, sizeof(fqs));
@@ -284,7 +444,7 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
        default:
                return -EINVAL;
        }
-       ret = sb->s_qcop->get_xstatev(sb, &fqs);
+       ret = quota_getstatev(sb, &fqs);
        if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
                return -EFAULT;
        return ret;
@@ -357,6 +517,30 @@ static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
                dst->d_fieldmask |= QC_RT_SPACE;
 }
 
+static void copy_qcinfo_from_xfs_dqblk(struct qc_info *dst,
+                                      struct fs_disk_quota *src)
+{
+       memset(dst, 0, sizeof(*dst));
+       dst->i_spc_timelimit = src->d_btimer;
+       dst->i_ino_timelimit = src->d_itimer;
+       dst->i_rt_spc_timelimit = src->d_rtbtimer;
+       dst->i_ino_warnlimit = src->d_iwarns;
+       dst->i_spc_warnlimit = src->d_bwarns;
+       dst->i_rt_spc_warnlimit = src->d_rtbwarns;
+       if (src->d_fieldmask & FS_DQ_BWARNS)
+               dst->i_fieldmask |= QC_SPC_WARNS;
+       if (src->d_fieldmask & FS_DQ_IWARNS)
+               dst->i_fieldmask |= QC_INO_WARNS;
+       if (src->d_fieldmask & FS_DQ_RTBWARNS)
+               dst->i_fieldmask |= QC_RT_SPC_WARNS;
+       if (src->d_fieldmask & FS_DQ_BTIMER)
+               dst->i_fieldmask |= QC_SPC_TIMER;
+       if (src->d_fieldmask & FS_DQ_ITIMER)
+               dst->i_fieldmask |= QC_INO_TIMER;
+       if (src->d_fieldmask & FS_DQ_RTBTIMER)
+               dst->i_fieldmask |= QC_RT_SPC_TIMER;
+}
+
 static int quota_setxquota(struct super_block *sb, int type, qid_t id,
                           void __user *addr)
 {
@@ -371,6 +555,21 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
        qid = make_kqid(current_user_ns(), type, id);
        if (!qid_valid(qid))
                return -EINVAL;
+       /* Are we actually setting timer / warning limits for all users? */
+       if (from_kqid(&init_user_ns, qid) == 0 &&
+           fdq.d_fieldmask & (FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK)) {
+               struct qc_info qinfo;
+               int ret;
+
+               if (!sb->s_qcop->set_info)
+                       return -EINVAL;
+               copy_qcinfo_from_xfs_dqblk(&qinfo, &fdq);
+               ret = sb->s_qcop->set_info(sb, type, &qinfo);
+               if (ret)
+                       return ret;
+               /* These are already done */
+               fdq.d_fieldmask &= ~(FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK);
+       }
        copy_from_xfs_dqblk(&qdq, &fdq);
        return sb->s_qcop->set_dqblk(sb, qid, &qdq);
 }
index d65877fbe8f4a389100527ce426c5e22f8fe1e88..58efb83dec1c870c672a5330fcb4571323c73914 100644 (file)
@@ -349,6 +349,13 @@ static inline int dq_insert_tree(struct qtree_mem_dqinfo *info,
                                 struct dquot *dquot)
 {
        int tmp = QT_TREEOFF;
+
+#ifdef __QUOTA_QT_PARANOIA
+       if (info->dqi_blocks <= QT_TREEOFF) {
+               quota_error(dquot->dq_sb, "Quota tree root isn't allocated!");
+               return -EIO;
+       }
+#endif
        return do_insert_tree(info, dquot, &tmp, 0);
 }
 
index 9cb10d7197f70c1a74b01b927f0cbd14e40a84e2..2aa012a68e90e524255fb47e983d121cf9c839b4 100644 (file)
@@ -117,12 +117,16 @@ static int v2_read_file_info(struct super_block *sb, int type)
        qinfo = info->dqi_priv;
        if (version == 0) {
                /* limits are stored as unsigned 32-bit data */
-               info->dqi_max_spc_limit = 0xffffffffULL << QUOTABLOCK_BITS;
+               info->dqi_max_spc_limit = 0xffffffffLL << QUOTABLOCK_BITS;
                info->dqi_max_ino_limit = 0xffffffff;
        } else {
-               /* used space is stored as unsigned 64-bit value in bytes */
-               info->dqi_max_spc_limit = 0xffffffffffffffffULL; /* 2^64-1 */
-               info->dqi_max_ino_limit = 0xffffffffffffffffULL;
+               /*
+                * Used space is stored as unsigned 64-bit value in bytes but
+                * quota core supports only signed 64-bit values so use that
+                * as a limit
+                */
+               info->dqi_max_spc_limit = 0x7fffffffffffffffLL; /* 2^63-1 */
+               info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
        }
        info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
        info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
index f1966b42c2fdc07c3269a36402ab4bc3e2d9cb76..4e95430093d9959f271b970e645c1911152a7886 100644 (file)
  */
 #define V2_INITQMAGICS {\
        0xd9c01f11,     /* USRQUOTA */\
-       0xd9c01927      /* GRPQUOTA */\
+       0xd9c01927,     /* GRPQUOTA */\
+       0xd9c03f14,     /* PRJQUOTA */\
 }
 
 #define V2_INITQVERSIONS {\
        1,              /* USRQUOTA */\
-       1               /* GRPQUOTA */\
+       1,              /* GRPQUOTA */\
+       1,              /* PRJQUOTA */\
 }
 
 /* First generic header */
index bb79cddf0a1f15691cb59252448ffd4a02ecad43..2adcde137c3fb8d569cddcdf83dfd443a11f693f 100644 (file)
@@ -910,7 +910,6 @@ do {                                                                        \
        if (!(cond))                                                    \
                reiserfs_panic(NULL, "assertion failure", "(" #cond ") at " \
                               __FILE__ ":%i:%s: " format "\n",         \
-                              in_interrupt() ? -1 : task_pid_nr(current), \
                               __LINE__, __func__ , ##args);            \
 } while (0)
 
index 71fbbe3e2dab310481ef97ca12885a4a2137e8cf..68b5f182984e245c786f05cf29a6e148d2466654 100644 (file)
@@ -805,7 +805,7 @@ static const struct quotactl_ops reiserfs_qctl_operations = {
        .quota_on = reiserfs_quota_on,
        .quota_off = dquot_quota_off,
        .quota_sync = dquot_quota_sync,
-       .get_info = dquot_get_dqinfo,
+       .get_state = dquot_get_state,
        .set_info = dquot_set_dqinfo,
        .get_dqblk = dquot_get_dqblk,
        .set_dqblk = dquot_set_dqblk,
index 1ba2baaf43671889f2eb0339e92996a1bf41f7ca..6d6a96b4e73fe20ba15edc1213564613cb201bbd 100644 (file)
@@ -21,7 +21,6 @@
 
 #include "udfdecl.h"
 
-#include <linux/buffer_head.h>
 #include <linux/bitops.h>
 
 #include "udf_i.h"
@@ -63,15 +62,14 @@ static int __load_block_bitmap(struct super_block *sb,
                          block_group, nr_groups);
        }
 
-       if (bitmap->s_block_bitmap[block_group]) {
+       if (bitmap->s_block_bitmap[block_group])
                return block_group;
-       } else {
-               retval = read_block_bitmap(sb, bitmap, block_group,
-                                          block_group);
-               if (retval < 0)
-                       return retval;
-               return block_group;
-       }
+
+       retval = read_block_bitmap(sb, bitmap, block_group, block_group);
+       if (retval < 0)
+               return retval;
+
+       return block_group;
 }
 
 static inline int load_block_bitmap(struct super_block *sb,
@@ -358,7 +356,6 @@ static void udf_table_free_blocks(struct super_block *sb,
        struct kernel_lb_addr eloc;
        struct extent_position oepos, epos;
        int8_t etype;
-       int i;
        struct udf_inode_info *iinfo;
 
        mutex_lock(&sbi->s_alloc_mutex);
@@ -425,7 +422,6 @@ static void udf_table_free_blocks(struct super_block *sb,
                }
 
                if (epos.bh != oepos.bh) {
-                       i = -1;
                        oepos.block = epos.block;
                        brelse(oepos.bh);
                        get_bh(epos.bh);
@@ -762,7 +758,7 @@ inline int udf_prealloc_blocks(struct super_block *sb,
                               uint32_t block_count)
 {
        struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
-       sector_t allocated;
+       int allocated;
 
        if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
                allocated = udf_bitmap_prealloc_blocks(sb,
index 05e90edd199214fd0507b5e5b79a3b60ea8a49d3..541a12b5792d3a296d864efc626d75d42f180ab4 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/buffer_head.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
index 3e44f575fb9cbaf39d8f05bb4594807bb0a7a3be..c763fda257bf371ad04a5b4b5aff0a1269a9366e 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/fs.h>
 #include <linux/string.h>
-#include <linux/buffer_head.h>
 
 struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
                                         struct udf_fileident_bh *fibh,
index 74050bff64f4000b745374fccde9a9e3eaec4256..f77f7681288f790dc7b8b73fd4863f5e4a88688b 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/pagemap.h>
-#include <linux/buffer_head.h>
 #include <linux/uio.h>
 
 #include "udf_i.h"
index 9c1fbd23913db541c3facc1342614793b1403bfd..9e3d780e5efffc373cb4055f8bcbfe2469b3134d 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
-#include <linux/buffer_head.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
 #include <linux/crc-itu-t.h>
@@ -1637,7 +1636,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)
                        udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
        if (!bh) {
                udf_debug("getblk failure\n");
-               return -ENOMEM;
+               return -EIO;
        }
 
        lock_buffer(bh);
index c175b4dabc14e576eea191fbb0f923f4735171e4..71d1c25f360d170286862382cb4cf0e31cf40508 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/fs.h>
 #include <linux/string.h>
-#include <linux/buffer_head.h>
 #include <linux/crc-itu-t.h>
 
 #include "udf_i.h"
index 33b246b82c98510289d533fcdcbc59154d38589f..39661977c89cdd657b19a60bf33d58bf79762c94 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/buffer_head.h>
 #include <linux/sched.h>
 #include <linux/crc-itu-t.h>
 #include <linux/exportfs.h>
@@ -569,8 +568,8 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
                cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
-       if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
-               mark_inode_dirty(dir);
+       dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
+       mark_inode_dirty(dir);
        if (fibh.sbh != fibh.ebh)
                brelse(fibh.ebh);
        brelse(fibh.sbh);
@@ -683,6 +682,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
        inc_nlink(dir);
+       dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
        mark_inode_dirty(dir);
        unlock_new_inode(inode);
        d_instantiate(dentry, inode);
@@ -1024,6 +1024,8 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
        inc_nlink(inode);
        inode->i_ctime = current_fs_time(inode->i_sb);
        mark_inode_dirty(inode);
+       dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
+       mark_inode_dirty(dir);
        ihold(inode);
        d_instantiate(dentry, inode);
 
@@ -1127,7 +1129,9 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
                inode_dec_link_count(new_inode);
        }
        old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
+       new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb);
        mark_inode_dirty(old_dir);
+       mark_inode_dirty(new_dir);
 
        if (dir_fi) {
                dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
index d6caf01a20971e2e3237e885aa55f9ccd9998569..5f861ed287c3fde0fbf87de4c740e672213acd5d 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/fs.h>
 #include <linux/string.h>
-#include <linux/buffer_head.h>
 #include <linux/mutex.h>
 
 uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
index f169411c4ea0d9ee2681b8a374a02759cfec7498..6299f341967baf8e03b4e032b37eda524006e4ce 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/stat.h>
 #include <linux/cdrom.h>
 #include <linux/nls.h>
-#include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/vmalloc.h>
 #include <linux/errno.h>
index ac10ca939f267283ba0f64da9d4ec82de0eeeb61..8dfbc4025e2f39afcb204d5abe8b0dff5f5a8f7b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/mm.h>
 #include <linux/stat.h>
 #include <linux/pagemap.h>
-#include <linux/buffer_head.h>
 #include "udf_i.h"
 
 static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
index 8a9657d7f7c680eed83bd007372796b5c2f2523c..42b8c57795cbadf08e120f75e6eb92658369bdec 100644 (file)
@@ -22,7 +22,6 @@
 #include "udfdecl.h"
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/buffer_head.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
index 0d4d3590cf85451c2885bd68421ae97de8ff6b0c..996a04064894cf4c07ffa28d058150243ffd86a4 100644 (file)
@@ -168,10 +168,6 @@ extern int         xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t,
                                        uint, struct qc_dqblk *);
 extern int             xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
                                        struct qc_dqblk *);
-extern int             xfs_qm_scall_getqstat(struct xfs_mount *,
-                                       struct fs_quota_stat *);
-extern int             xfs_qm_scall_getqstatv(struct xfs_mount *,
-                                       struct fs_quota_statv *);
 extern int             xfs_qm_scall_quotaon(struct xfs_mount *, uint);
 extern int             xfs_qm_scall_quotaoff(struct xfs_mount *, uint);
 
index 9b965db458000f684379f6a7e19c26387556e826..9a25c9275fb32aa6be67a79e7b5b5d4eab96cd09 100644 (file)
@@ -38,7 +38,6 @@
 STATIC int     xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
 STATIC int     xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
                                        uint);
-STATIC uint    xfs_qm_export_flags(uint);
 
 /*
  * Turn off quota accounting and/or enforcement for all udquots and/or
@@ -389,159 +388,6 @@ xfs_qm_scall_quotaon(
        return 0;
 }
 
-
-/*
- * Return quota status information, such as uquota-off, enforcements, etc.
- * for Q_XGETQSTAT command.
- */
-int
-xfs_qm_scall_getqstat(
-       struct xfs_mount        *mp,
-       struct fs_quota_stat    *out)
-{
-       struct xfs_quotainfo    *q = mp->m_quotainfo;
-       struct xfs_inode        *uip = NULL;
-       struct xfs_inode        *gip = NULL;
-       struct xfs_inode        *pip = NULL;
-       bool                    tempuqip = false;
-       bool                    tempgqip = false;
-       bool                    temppqip = false;
-
-       memset(out, 0, sizeof(fs_quota_stat_t));
-
-       out->qs_version = FS_QSTAT_VERSION;
-       out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
-                                                       (XFS_ALL_QUOTA_ACCT|
-                                                        XFS_ALL_QUOTA_ENFD));
-       uip = q->qi_uquotaip;
-       gip = q->qi_gquotaip;
-       pip = q->qi_pquotaip;
-       if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
-               if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-                                       0, 0, &uip) == 0)
-                       tempuqip = true;
-       }
-       if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
-               if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-                                       0, 0, &gip) == 0)
-                       tempgqip = true;
-       }
-       /*
-        * Q_XGETQSTAT doesn't have room for both group and project quotas.
-        * So, allow the project quota values to be copied out only if
-        * there is no group quota information available.
-        */
-       if (!gip) {
-               if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
-                       if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
-                                               0, 0, &pip) == 0)
-                               temppqip = true;
-               }
-       } else
-               pip = NULL;
-       if (uip) {
-               out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
-               out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
-               out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
-               if (tempuqip)
-                       IRELE(uip);
-       }
-
-       if (gip) {
-               out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
-               out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
-               out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
-               if (tempgqip)
-                       IRELE(gip);
-       }
-       if (pip) {
-               out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
-               out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
-               out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
-               if (temppqip)
-                       IRELE(pip);
-       }
-       out->qs_incoredqs = q->qi_dquots;
-       out->qs_btimelimit = q->qi_btimelimit;
-       out->qs_itimelimit = q->qi_itimelimit;
-       out->qs_rtbtimelimit = q->qi_rtbtimelimit;
-       out->qs_bwarnlimit = q->qi_bwarnlimit;
-       out->qs_iwarnlimit = q->qi_iwarnlimit;
-
-       return 0;
-}
-
-/*
- * Return quota status information, such as uquota-off, enforcements, etc.
- * for Q_XGETQSTATV command, to support separate project quota field.
- */
-int
-xfs_qm_scall_getqstatv(
-       struct xfs_mount        *mp,
-       struct fs_quota_statv   *out)
-{
-       struct xfs_quotainfo    *q = mp->m_quotainfo;
-       struct xfs_inode        *uip = NULL;
-       struct xfs_inode        *gip = NULL;
-       struct xfs_inode        *pip = NULL;
-       bool                    tempuqip = false;
-       bool                    tempgqip = false;
-       bool                    temppqip = false;
-
-       out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
-                                                       (XFS_ALL_QUOTA_ACCT|
-                                                        XFS_ALL_QUOTA_ENFD));
-       out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
-       out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
-       out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
-
-       uip = q->qi_uquotaip;
-       gip = q->qi_gquotaip;
-       pip = q->qi_pquotaip;
-       if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
-               if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-                                       0, 0, &uip) == 0)
-                       tempuqip = true;
-       }
-       if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
-               if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-                                       0, 0, &gip) == 0)
-                       tempgqip = true;
-       }
-       if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
-               if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
-                                       0, 0, &pip) == 0)
-                       temppqip = true;
-       }
-       if (uip) {
-               out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
-               out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
-               if (tempuqip)
-                       IRELE(uip);
-       }
-
-       if (gip) {
-               out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
-               out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
-               if (tempgqip)
-                       IRELE(gip);
-       }
-       if (pip) {
-               out->qs_pquota.qfs_nblks = pip->i_d.di_nblocks;
-               out->qs_pquota.qfs_nextents = pip->i_d.di_nextents;
-               if (temppqip)
-                       IRELE(pip);
-       }
-       out->qs_incoredqs = q->qi_dquots;
-       out->qs_btimelimit = q->qi_btimelimit;
-       out->qs_itimelimit = q->qi_itimelimit;
-       out->qs_rtbtimelimit = q->qi_rtbtimelimit;
-       out->qs_bwarnlimit = q->qi_bwarnlimit;
-       out->qs_iwarnlimit = q->qi_iwarnlimit;
-
-       return 0;
-}
-
 #define XFS_QC_MASK \
        (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
 
@@ -873,28 +719,6 @@ out_put:
        return error;
 }
 
-STATIC uint
-xfs_qm_export_flags(
-       uint flags)
-{
-       uint uflags;
-
-       uflags = 0;
-       if (flags & XFS_UQUOTA_ACCT)
-               uflags |= FS_QUOTA_UDQ_ACCT;
-       if (flags & XFS_GQUOTA_ACCT)
-               uflags |= FS_QUOTA_GDQ_ACCT;
-       if (flags & XFS_PQUOTA_ACCT)
-               uflags |= FS_QUOTA_PDQ_ACCT;
-       if (flags & XFS_UQUOTA_ENFD)
-               uflags |= FS_QUOTA_UDQ_ENFD;
-       if (flags & XFS_GQUOTA_ENFD)
-               uflags |= FS_QUOTA_GDQ_ENFD;
-       if (flags & XFS_PQUOTA_ENFD)
-               uflags |= FS_QUOTA_PDQ_ENFD;
-       return uflags;
-}
-
 
 STATIC int
 xfs_dqrele_inode(
index 6923905ab33d973eb30206dd97c247eafffbd2f4..7795e0d01382a60798b4e83f35ba6db725fe8779 100644 (file)
 #include "xfs_inode.h"
 #include "xfs_quota.h"
 #include "xfs_trans.h"
+#include "xfs_trace.h"
+#include "xfs_icache.h"
 #include "xfs_qm.h"
 #include <linux/quota.h>
 
 
+static void
+xfs_qm_fill_state(
+       struct qc_type_state    *tstate,
+       struct xfs_mount        *mp,
+       struct xfs_inode        *ip,
+       xfs_ino_t               ino)
+{
+       struct xfs_quotainfo *q = mp->m_quotainfo;
+       bool tempqip = false;
+
+       tstate->ino = ino;
+       if (!ip && ino == NULLFSINO)
+               return;
+       if (!ip) {
+               if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
+                       return;
+               tempqip = true;
+       }
+       tstate->flags |= QCI_SYSFILE;
+       tstate->blocks = ip->i_d.di_nblocks;
+       tstate->nextents = ip->i_d.di_nextents;
+       tstate->spc_timelimit = q->qi_btimelimit;
+       tstate->ino_timelimit = q->qi_itimelimit;
+       tstate->rt_spc_timelimit = q->qi_rtbtimelimit;
+       tstate->spc_warnlimit = q->qi_bwarnlimit;
+       tstate->ino_warnlimit = q->qi_iwarnlimit;
+       tstate->rt_spc_warnlimit = q->qi_rtbwarnlimit;
+       if (tempqip)
+               IRELE(ip);
+}
+
+/*
+ * Return quota status information, such as enforcements, quota file inode
+ * numbers etc.
+ */
+static int
+xfs_fs_get_quota_state(
+       struct super_block      *sb,
+       struct qc_state         *state)
+{
+       struct xfs_mount *mp = XFS_M(sb);
+       struct xfs_quotainfo *q = mp->m_quotainfo;
+
+       memset(state, 0, sizeof(*state));
+       if (!XFS_IS_QUOTA_RUNNING(mp))
+               return 0;
+       state->s_incoredqs = q->qi_dquots;
+       if (XFS_IS_UQUOTA_RUNNING(mp))
+               state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED;
+       if (XFS_IS_UQUOTA_ENFORCED(mp))
+               state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED;
+       if (XFS_IS_GQUOTA_RUNNING(mp))
+               state->s_state[GRPQUOTA].flags |= QCI_ACCT_ENABLED;
+       if (XFS_IS_GQUOTA_ENFORCED(mp))
+               state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED;
+       if (XFS_IS_PQUOTA_RUNNING(mp))
+               state->s_state[PRJQUOTA].flags |= QCI_ACCT_ENABLED;
+       if (XFS_IS_PQUOTA_ENFORCED(mp))
+               state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
+
+       xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
+                         mp->m_sb.sb_uquotino);
+       xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
+                         mp->m_sb.sb_gquotino);
+       xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
+                         mp->m_sb.sb_pquotino);
+       return 0;
+}
+
 STATIC int
 xfs_quota_type(int type)
 {
@@ -40,28 +111,40 @@ xfs_quota_type(int type)
        }
 }
 
-STATIC int
-xfs_fs_get_xstate(
+#define XFS_QC_SETINFO_MASK (QC_TIMER_MASK | QC_WARNS_MASK)
+
+/*
+ * Adjust quota timers & warnings
+ */
+static int
+xfs_fs_set_info(
        struct super_block      *sb,
-       struct fs_quota_stat    *fqs)
+       int                     type,
+       struct qc_info          *info)
 {
-       struct xfs_mount        *mp = XFS_M(sb);
+       struct xfs_mount *mp = XFS_M(sb);
+       struct qc_dqblk newlim;
 
+       if (sb->s_flags & MS_RDONLY)
+               return -EROFS;
        if (!XFS_IS_QUOTA_RUNNING(mp))
                return -ENOSYS;
-       return xfs_qm_scall_getqstat(mp, fqs);
-}
+       if (!XFS_IS_QUOTA_ON(mp))
+               return -ESRCH;
+       if (info->i_fieldmask & ~XFS_QC_SETINFO_MASK)
+               return -EINVAL;
+       if ((info->i_fieldmask & XFS_QC_SETINFO_MASK) == 0)
+               return 0;
 
-STATIC int
-xfs_fs_get_xstatev(
-       struct super_block      *sb,
-       struct fs_quota_statv   *fqs)
-{
-       struct xfs_mount        *mp = XFS_M(sb);
+       newlim.d_fieldmask = info->i_fieldmask;
+       newlim.d_spc_timer = info->i_spc_timelimit;
+       newlim.d_ino_timer = info->i_ino_timelimit;
+       newlim.d_rt_spc_timer = info->i_rt_spc_timelimit;
+       newlim.d_ino_warns = info->i_ino_warnlimit;
+       newlim.d_spc_warns = info->i_spc_warnlimit;
+       newlim.d_rt_spc_warns = info->i_rt_spc_warnlimit;
 
-       if (!XFS_IS_QUOTA_RUNNING(mp))
-               return -ENOSYS;
-       return xfs_qm_scall_getqstatv(mp, fqs);
+       return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
 }
 
 static unsigned int
@@ -178,8 +261,8 @@ xfs_fs_set_dqblk(
 }
 
 const struct quotactl_ops xfs_quotactl_operations = {
-       .get_xstatev            = xfs_fs_get_xstatev,
-       .get_xstate             = xfs_fs_get_xstate,
+       .get_state              = xfs_fs_get_quota_state,
+       .set_info               = xfs_fs_set_info,
        .quota_enable           = xfs_quota_enable,
        .quota_disable          = xfs_quota_disable,
        .rm_xquota              = xfs_fs_rm_xquota,
index d534e8ed308a1a116ae968ed78d98d9e183bb00a..b2505acfd3c078c70e733f7d9e826cfc4b6c9524 100644 (file)
@@ -50,6 +50,7 @@
 
 #undef USRQUOTA
 #undef GRPQUOTA
+#undef PRJQUOTA
 enum quota_type {
        USRQUOTA = 0,           /* element used for user quotas */
        GRPQUOTA = 1,           /* element used for group quotas */
@@ -319,6 +320,7 @@ struct dquot_operations {
        /* get reserved quota for delayed alloc, value returned is managed by
         * quota code only */
        qsize_t *(*get_reserved_space) (struct inode *);
+       int (*get_projid) (struct inode *, kprojid_t *);/* Get project ID */
 };
 
 struct path;
@@ -344,7 +346,10 @@ struct qc_dqblk {
        int d_rt_spc_warns;     /* # warnings issued wrt RT space */
 };
 
-/* Field specifiers for ->set_dqblk() in struct qc_dqblk */
+/*
+ * Field specifiers for ->set_dqblk() in struct qc_dqblk and also for
+ * ->set_info() in struct qc_info
+ */
 #define        QC_INO_SOFT     (1<<0)
 #define        QC_INO_HARD     (1<<1)
 #define        QC_SPC_SOFT     (1<<2)
@@ -365,6 +370,51 @@ struct qc_dqblk {
 #define        QC_INO_COUNT    (1<<13)
 #define        QC_RT_SPACE     (1<<14)
 #define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE)
+#define QC_FLAGS       (1<<15)
+
+#define QCI_SYSFILE            (1 << 0)        /* Quota file is hidden from userspace */
+#define QCI_ROOT_SQUASH                (1 << 1)        /* Root squash turned on */
+#define QCI_ACCT_ENABLED       (1 << 2)        /* Quota accounting enabled */
+#define QCI_LIMITS_ENFORCED    (1 << 3)        /* Quota limits enforced */
+
+/* Structures for communicating via ->get_state */
+struct qc_type_state {
+       unsigned int flags;             /* Flags QCI_* */
+       unsigned int spc_timelimit;     /* Time after which space softlimit is
+                                        * enforced */
+       unsigned int ino_timelimit;     /* Ditto for inode softlimit */
+       unsigned int rt_spc_timelimit;  /* Ditto for real-time space */
+       unsigned int spc_warnlimit;     /* Limit for number of space warnings */
+       unsigned int ino_warnlimit;     /* Ditto for inodes */
+       unsigned int rt_spc_warnlimit;  /* Ditto for real-time space */
+       unsigned long long ino;         /* Inode number of quota file */
+       blkcnt_t blocks;                /* Number of 512-byte blocks in the file */
+       blkcnt_t nextents;              /* Number of extents in the file */
+};
+
+struct qc_state {
+       unsigned int s_incoredqs;       /* Number of dquots in core */
+       /*
+        * Per quota type information. The array should really have
+        * max(MAXQUOTAS, XQM_MAXQUOTAS) entries. BUILD_BUG_ON in
+        * quota_getinfo() makes sure XQM_MAXQUOTAS is large enough.  Once VFS
+        * supports project quotas, this can be changed to MAXQUOTAS
+        */
+       struct qc_type_state s_state[XQM_MAXQUOTAS];
+};
+
+/* Structure for communicating via ->set_info */
+struct qc_info {
+       int i_fieldmask;        /* mask of fields to change in ->set_info() */
+       unsigned int i_flags;           /* Flags QCI_* */
+       unsigned int i_spc_timelimit;   /* Time after which space softlimit is
+                                        * enforced */
+       unsigned int i_ino_timelimit;   /* Ditto for inode softlimit */
+       unsigned int i_rt_spc_timelimit;/* Ditto for real-time space */
+       unsigned int i_spc_warnlimit;   /* Limit for number of space warnings */
+       unsigned int i_ino_warnlimit;   /* Limit for number of inode warnings */
+       unsigned int i_rt_spc_warnlimit;        /* Ditto for real-time space */
+};
 
 /* Operations handling requests from userspace */
 struct quotactl_ops {
@@ -373,12 +423,10 @@ struct quotactl_ops {
        int (*quota_enable)(struct super_block *, unsigned int);
        int (*quota_disable)(struct super_block *, unsigned int);
        int (*quota_sync)(struct super_block *, int);
-       int (*get_info)(struct super_block *, int, struct if_dqinfo *);
-       int (*set_info)(struct super_block *, int, struct if_dqinfo *);
+       int (*set_info)(struct super_block *, int, struct qc_info *);
        int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
        int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
-       int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
-       int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
+       int (*get_state)(struct super_block *, struct qc_state *);
        int (*rm_xquota)(struct super_block *, unsigned int);
 };
 
@@ -389,7 +437,19 @@ struct quota_format_type {
        struct quota_format_type *qf_next;
 };
 
-/* Quota state flags - they actually come in two flavors - for users and groups */
+/**
+ * Quota state flags - they actually come in two flavors - for users and groups.
+ *
+ * Actual typed flags layout:
+ *                             USRQUOTA        GRPQUOTA
+ *  DQUOT_USAGE_ENABLED                0x0001          0x0002
+ *  DQUOT_LIMITS_ENABLED       0x0004          0x0008
+ *  DQUOT_SUSPENDED            0x0010          0x0020
+ *
+ * Following bits are used for non-typed flags:
+ *  DQUOT_QUOTA_SYS_FILE       0x0040
+ *  DQUOT_NEGATIVE_USAGE       0x0080
+ */
 enum {
        _DQUOT_USAGE_ENABLED = 0,               /* Track disk usage for users */
        _DQUOT_LIMITS_ENABLED,                  /* Enforce quota limits for users */
@@ -398,9 +458,9 @@ enum {
                                                 * memory to turn them on */
        _DQUOT_STATE_FLAGS
 };
-#define DQUOT_USAGE_ENABLED    (1 << _DQUOT_USAGE_ENABLED)
-#define DQUOT_LIMITS_ENABLED   (1 << _DQUOT_LIMITS_ENABLED)
-#define DQUOT_SUSPENDED                (1 << _DQUOT_SUSPENDED)
+#define DQUOT_USAGE_ENABLED    (1 << _DQUOT_USAGE_ENABLED * MAXQUOTAS)
+#define DQUOT_LIMITS_ENABLED   (1 << _DQUOT_LIMITS_ENABLED * MAXQUOTAS)
+#define DQUOT_SUSPENDED                (1 << _DQUOT_SUSPENDED * MAXQUOTAS)
 #define DQUOT_STATE_FLAGS      (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
                                 DQUOT_SUSPENDED)
 /* Other quota flags */
@@ -414,15 +474,21 @@ enum {
                                                 */
 #define DQUOT_NEGATIVE_USAGE   (1 << (DQUOT_STATE_LAST + 1))
                                               /* Allow negative quota usage */
-
 static inline unsigned int dquot_state_flag(unsigned int flags, int type)
 {
-       return flags << _DQUOT_STATE_FLAGS * type;
+       return flags << type;
 }
 
 static inline unsigned int dquot_generic_flag(unsigned int flags, int type)
 {
-       return (flags >> _DQUOT_STATE_FLAGS * type) & DQUOT_STATE_FLAGS;
+       return (flags >> type) & DQUOT_STATE_FLAGS;
+}
+
+/* Bitmap of quota types where flag is set in flags */
+static __always_inline unsigned dquot_state_types(unsigned flags, unsigned flag)
+{
+       BUILD_BUG_ON_NOT_POWER_OF_2(flag);
+       return (flags / flag) & ((1 << MAXQUOTAS) - 1);
 }
 
 #ifdef CONFIG_QUOTA_NETLINK_INTERFACE
index df73258cca47744ce4720659159ef4f4d96ec956..77ca6601ff258bea58da18d176444ca4b48c82be 100644 (file)
@@ -95,8 +95,8 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
 int dquot_quota_off(struct super_block *sb, int type);
 int dquot_writeback_dquots(struct super_block *sb, int type);
 int dquot_quota_sync(struct super_block *sb, int type);
-int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
-int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+int dquot_get_state(struct super_block *sb, struct qc_state *state);
+int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii);
 int dquot_get_dqblk(struct super_block *sb, struct kqid id,
                struct qc_dqblk *di);
 int dquot_set_dqblk(struct super_block *sb, struct kqid id,
@@ -134,10 +134,7 @@ static inline bool sb_has_quota_suspended(struct super_block *sb, int type)
 
 static inline unsigned sb_any_quota_suspended(struct super_block *sb)
 {
-       unsigned type, tmsk = 0;
-       for (type = 0; type < MAXQUOTAS; type++)
-               tmsk |= sb_has_quota_suspended(sb, type) << type;
-       return tmsk;
+       return dquot_state_types(sb_dqopt(sb)->flags, DQUOT_SUSPENDED);
 }
 
 /* Does kernel know about any quota information for given sb + type? */
@@ -149,10 +146,7 @@ static inline bool sb_has_quota_loaded(struct super_block *sb, int type)
 
 static inline unsigned sb_any_quota_loaded(struct super_block *sb)
 {
-       unsigned type, tmsk = 0;
-       for (type = 0; type < MAXQUOTAS; type++)
-               tmsk |= sb_has_quota_loaded(sb, type) << type;
-       return  tmsk;
+       return dquot_state_types(sb_dqopt(sb)->flags, DQUOT_USAGE_ENABLED);
 }
 
 static inline bool sb_has_quota_active(struct super_block *sb, int type)
index 1f49b8341c994f27ca84374a1115a1d2be01a1e9..9c95b2c1c88a6ef0a6bb4207cd5122011d3007f9 100644 (file)
 #include <linux/errno.h>
 #include <linux/types.h>
 
-#define __DQUOT_VERSION__      "dquot_6.5.2"
+#define __DQUOT_VERSION__      "dquot_6.6.0"
 
-#define MAXQUOTAS 2
+#define MAXQUOTAS 3
 #define USRQUOTA  0            /* element used for user quotas */
 #define GRPQUOTA  1            /* element used for group quotas */
+#define PRJQUOTA  2            /* element used for project quotas */
 
 /*
  * Definitions for the default names of the quotas files.
@@ -48,6 +49,7 @@
 #define INITQFNAMES { \
        "user",    /* USRQUOTA */ \
        "group",   /* GRPQUOTA */ \
+       "project", /* PRJQUOTA */ \
        "undefined", \
 };