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
  ...

1  2 
fs/gfs2/quota.c
fs/udf/file.c
fs/udf/inode.c

diff --combined fs/gfs2/quota.c
@@@ -923,9 -923,6 +923,9 @@@ restart
        if (error)
                return error;
  
 +      if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags))
 +              force_refresh = FORCE;
 +
        qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
  
        if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) {
@@@ -977,8 -974,11 +977,8 @@@ int gfs2_quota_lock(struct gfs2_inode *
             sizeof(struct gfs2_quota_data *), sort_qd, NULL);
  
        for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
 -              int force = NO_FORCE;
                qd = ip->i_res->rs_qa_qd[x];
 -              if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags))
 -                      force = FORCE;
 -              error = do_glock(qd, force, &ip->i_res->rs_qa_qd_ghs[x]);
 +              error = do_glock(qd, NO_FORCE, &ip->i_res->rs_qa_qd_ghs[x]);
                if (error)
                        break;
        }
@@@ -1094,33 -1094,14 +1094,33 @@@ static int print_message(struct gfs2_qu
        return 0;
  }
  
 -int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
 +/**
 + * gfs2_quota_check - check if allocating new blocks will exceed quota
 + * @ip:  The inode for which this check is being performed
 + * @uid: The uid to check against
 + * @gid: The gid to check against
 + * @ap:  The allocation parameters. ap->target contains the requested
 + *       blocks. ap->min_target, if set, contains the minimum blks
 + *       requested.
 + *
 + * Returns: 0 on success.
 + *                  min_req = ap->min_target ? ap->min_target : ap->target;
 + *                  quota must allow atleast min_req blks for success and
 + *                  ap->allowed is set to the number of blocks allowed
 + *
 + *          -EDQUOT otherwise, quota violation. ap->allowed is set to number
 + *                  of blocks available.
 + */
 +int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
 +                   struct gfs2_alloc_parms *ap)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_quota_data *qd;
 -      s64 value;
 +      s64 value, warn, limit;
        unsigned int x;
        int error = 0;
  
 +      ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */
        if (!test_bit(GIF_QD_LOCKED, &ip->i_flags))
                return 0;
  
                      qid_eq(qd->qd_id, make_kqid_gid(gid))))
                        continue;
  
 +              warn = (s64)be64_to_cpu(qd->qd_qb.qb_warn);
 +              limit = (s64)be64_to_cpu(qd->qd_qb.qb_limit);
                value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
                spin_lock(&qd_lock);
                value += qd->qd_change;
                spin_unlock(&qd_lock);
  
 -              if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {
 -                      print_message(qd, "exceeded");
 -                      quota_send_warning(qd->qd_id,
 -                                         sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN);
 -
 -                      error = -EDQUOT;
 -                      break;
 -              } else if (be64_to_cpu(qd->qd_qb.qb_warn) &&
 -                         (s64)be64_to_cpu(qd->qd_qb.qb_warn) < value &&
 +              if (limit > 0 && (limit - value) < ap->allowed)
 +                      ap->allowed = limit - value;
 +              /* If we can't meet the target */
 +              if (limit && limit < (value + (s64)ap->target)) {
 +                      /* If no min_target specified or we don't meet
 +                       * min_target, return -EDQUOT */
 +                      if (!ap->min_target || ap->min_target > ap->allowed) {
 +                              print_message(qd, "exceeded");
 +                              quota_send_warning(qd->qd_id,
 +                                                 sdp->sd_vfs->s_dev,
 +                                                 QUOTA_NL_BHARDWARN);
 +                              error = -EDQUOT;
 +                              break;
 +                      }
 +              } else if (warn && warn < value &&
                           time_after_eq(jiffies, qd->qd_last_warn +
 -                                       gfs2_tune_get(sdp,
 -                                              gt_quota_warn_period) * HZ)) {
 +                                       gfs2_tune_get(sdp, gt_quota_warn_period)
 +                                       * HZ)) {
                        quota_send_warning(qd->qd_id,
                                           sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);
                        error = print_message(qd, "warning");
                        qd->qd_last_warn = jiffies;
                }
        }
 -
        return error;
  }
  
@@@ -1494,32 -1468,34 +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 -1640,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,
  };
diff --combined fs/udf/file.c
@@@ -33,8 -33,7 +33,7 @@@
  #include <linux/capability.h>
  #include <linux/errno.h>
  #include <linux/pagemap.h>
- #include <linux/buffer_head.h>
 -#include <linux/aio.h>
 +#include <linux/uio.h>
  
  #include "udf_i.h"
  #include "udf_sb.h"
@@@ -122,7 -121,7 +121,7 @@@ static ssize_t udf_file_write_iter(stru
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        int err, pos;
 -      size_t count = iocb->ki_nbytes;
 +      size_t count = iov_iter_count(from);
        struct udf_inode_info *iinfo = UDF_I(inode);
  
        mutex_lock(&inode->i_mutex);
@@@ -240,10 -239,12 +239,10 @@@ static int udf_release_file(struct inod
  }
  
  const struct file_operations udf_file_operations = {
 -      .read                   = new_sync_read,
        .read_iter              = generic_file_read_iter,
        .unlocked_ioctl         = udf_ioctl,
        .open                   = generic_file_open,
        .mmap                   = generic_file_mmap,
 -      .write                  = new_sync_write,
        .write_iter             = udf_file_write_iter,
        .release                = udf_release_file,
        .fsync                  = generic_file_fsync,
diff --combined fs/udf/inode.c
  #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>
  #include <linux/mpage.h>
 -#include <linux/aio.h>
 +#include <linux/uio.h>
  
  #include "udf_i.h"
  #include "udf_sb.h"
@@@ -1637,7 -1636,7 +1636,7 @@@ static int udf_update_inode(struct inod
                        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);