Skip to content

Commit

Permalink
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jack/linux-fs

Pull quota interface unification and misc cleanups from Jan Kara:
 "The first part of the series unifying XFS and VFS quota interfaces.

  This part unifies turning quotas on and off so quota-tools and
  xfs_quota can be used to manage any filesystem.  This is useful so
  that userspace doesn't have to distinguish which filesystem it is
  working with.  As a result we can then easily reuse tests for project
  quotas in XFS for ext4.

  This also contains minor cleanups and fixes for udf, isofs, and ext3"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (23 commits)
  udf: remove bool assignment to 0/1
  udf: use bool for done
  quota: Store maximum space limit in bytes
  quota: Remove quota_on_meta callback
  ocfs2: Use generic helpers for quotaon and quotaoff
  ext4: Use generic helpers for quotaon and quotaoff
  quota: Add ->quota_{enable,disable} callbacks for VFS quotas
  quota: Wire up ->quota_{enable,disable} callbacks into Q_QUOTA{ON,OFF}
  quota: Split ->set_xstate callback into two
  xfs: Remove some pointless quota checks
  xfs: Remove some useless flags tests
  xfs: Remove useless test
  quota: Verify flags passed to Q_SETINFO
  quota: Cleanup flags definitions
  ocfs2: Move OLQF_CLEAN flag out of generic quota flags
  quota: Don't store flags for v2 quota format
  jbd: drop jbd_ENOSYS debug
  udf: destroy sbi mutex in put_super
  udf: Check length of extended attributes and allocation descriptors
  udf: Remove repeated loads blocksize
  ...
  • Loading branch information
torvalds committed Feb 10, 2015
2 parents 4b4f858 + 6981498 commit c5452a5
Show file tree
Hide file tree
Showing 21 changed files with 284 additions and 244 deletions.
2 changes: 2 additions & 0 deletions fs/ext3/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ static void ext3_put_super (struct super_block * sb)
}
sb->s_fs_info = NULL;
kfree(sbi->s_blockgroup_lock);
mutex_destroy(&sbi->s_orphan_lock);
mutex_destroy(&sbi->s_resize_lock);
kfree(sbi);
}

Expand Down
42 changes: 1 addition & 41 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1046,10 +1046,7 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot);
static int ext4_write_info(struct super_block *sb, int type);
static int ext4_quota_on(struct super_block *sb, int type, int format_id,
struct path *path);
static int ext4_quota_on_sysfile(struct super_block *sb, int type,
int format_id);
static int ext4_quota_off(struct super_block *sb, int type);
static int ext4_quota_off_sysfile(struct super_block *sb, int type);
static int ext4_quota_on_mount(struct super_block *sb, int type);
static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
size_t len, loff_t off);
Expand Down Expand Up @@ -1084,16 +1081,6 @@ static const struct quotactl_ops ext4_qctl_operations = {
.get_dqblk = dquot_get_dqblk,
.set_dqblk = dquot_set_dqblk
};

static const struct quotactl_ops ext4_qctl_sysfile_operations = {
.quota_on_meta = ext4_quota_on_sysfile,
.quota_off = ext4_quota_off_sysfile,
.quota_sync = dquot_quota_sync,
.get_info = dquot_get_dqinfo,
.set_info = dquot_set_dqinfo,
.get_dqblk = dquot_get_dqblk,
.set_dqblk = dquot_set_dqblk
};
#endif

static const struct super_operations ext4_sops = {
Expand Down Expand Up @@ -3935,7 +3922,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA
sb->dq_op = &ext4_quota_operations;
if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
sb->s_qcop = &ext4_qctl_sysfile_operations;
sb->s_qcop = &dquot_quotactl_sysfile_ops;
else
sb->s_qcop = &ext4_qctl_operations;
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
Expand Down Expand Up @@ -5288,21 +5275,6 @@ static int ext4_enable_quotas(struct super_block *sb)
return 0;
}

/*
* quota_on function that is used when QUOTA feature is set.
*/
static int ext4_quota_on_sysfile(struct super_block *sb, int type,
int format_id)
{
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
return -EINVAL;

/*
* USAGE was enabled at mount time. Only need to enable LIMITS now.
*/
return ext4_quota_enable(sb, type, format_id, DQUOT_LIMITS_ENABLED);
}

static int ext4_quota_off(struct super_block *sb, int type)
{
struct inode *inode = sb_dqopt(sb)->files[type];
Expand All @@ -5329,18 +5301,6 @@ static int ext4_quota_off(struct super_block *sb, int type)
return dquot_quota_off(sb, type);
}

/*
* quota_off function that is used when QUOTA feature is set.
*/
static int ext4_quota_off_sysfile(struct super_block *sb, int type)
{
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
return -EINVAL;

/* Disable only the limits. */
return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
}

/* Read data from quotafile - avoid pagecache and such because we cannot afford
* acquiring the locks... As quota files are never truncated and quota code
* itself serializes the operations (and no one else should touch the files)
Expand Down
18 changes: 4 additions & 14 deletions fs/isofs/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* linux/fs/isofs/util.c
*/

#include <linux/time.h>
#include "isofs.h"

/*
Expand All @@ -17,9 +18,9 @@
int iso_date(char * p, int flag)
{
int year, month, day, hour, minute, second, tz;
int crtime, days, i;
int crtime;

year = p[0] - 70;
year = p[0];
month = p[1];
day = p[2];
hour = p[3];
Expand All @@ -31,18 +32,7 @@ int iso_date(char * p, int flag)
if (year < 0) {
crtime = 0;
} else {
int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

days = year * 365;
if (year > 2)
days += (year+1) / 4;
for (i = 1; i < month; i++)
days += monlen[i-1];
if (((year+2) % 4) == 0 && month > 2)
days++;
days += day - 1;
crtime = ((((days * 24) + hour) * 60 + minute) * 60)
+ second;
crtime = mktime64(year+1900, month, day, hour, minute, second);

/* sign extend */
if (tz & 0x80)
Expand Down
1 change: 1 addition & 0 deletions fs/ocfs2/quota.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct ocfs2_quota_recovery {
/* In-memory structure with quota header information */
struct ocfs2_mem_dqinfo {
unsigned int dqi_type; /* Quota type this structure describes */
unsigned int dqi_flags; /* Flags OLQF_* */
unsigned int dqi_chunks; /* Number of chunks in local quota file */
unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
unsigned int dqi_syncms; /* How often should we sync with other nodes */
Expand Down
14 changes: 7 additions & 7 deletions fs/ocfs2/quota_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ static void olq_update_info(struct buffer_head *bh, void *private)
ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
OCFS2_LOCAL_INFO_OFF);
spin_lock(&dq_data_lock);
ldinfo->dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
ldinfo->dqi_flags = cpu_to_le32(oinfo->dqi_flags);
ldinfo->dqi_chunks = cpu_to_le32(oinfo->dqi_chunks);
ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks);
spin_unlock(&dq_data_lock);
Expand Down Expand Up @@ -701,8 +701,8 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
/* We don't need the lock and we have to acquire quota file locks
* which will later depend on this lock */
mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
info->dqi_maxblimit = 0x7fffffffffffffffLL;
info->dqi_maxilimit = 0x7fffffffffffffffLL;
info->dqi_max_spc_limit = 0x7fffffffffffffffLL;
info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
if (!oinfo) {
mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota"
Expand Down Expand Up @@ -737,13 +737,13 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
}
ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
OCFS2_LOCAL_INFO_OFF);
info->dqi_flags = le32_to_cpu(ldinfo->dqi_flags);
oinfo->dqi_flags = le32_to_cpu(ldinfo->dqi_flags);
oinfo->dqi_chunks = le32_to_cpu(ldinfo->dqi_chunks);
oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks);
oinfo->dqi_libh = bh;

/* We crashed when using local quota file? */
if (!(info->dqi_flags & OLQF_CLEAN)) {
if (!(oinfo->dqi_flags & OLQF_CLEAN)) {
rec = OCFS2_SB(sb)->quota_rec;
if (!rec) {
rec = ocfs2_alloc_quota_recovery();
Expand Down Expand Up @@ -772,7 +772,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
}

/* Now mark quota file as used */
info->dqi_flags &= ~OLQF_CLEAN;
oinfo->dqi_flags &= ~OLQF_CLEAN;
status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info);
if (status < 0) {
mlog_errno(status);
Expand Down Expand Up @@ -857,7 +857,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type)
goto out;

/* Mark local file as clean */
info->dqi_flags |= OLQF_CLEAN;
oinfo->dqi_flags |= OLQF_CLEAN;
status = ocfs2_modify_bh(sb_dqopt(sb)->files[type],
oinfo->dqi_libh,
olq_update_info,
Expand Down
32 changes: 1 addition & 31 deletions fs/ocfs2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,36 +1000,6 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb)
}
}

/* Handle quota on quotactl */
static int ocfs2_quota_on(struct super_block *sb, int type, int format_id)
{
unsigned int feature[OCFS2_MAXQUOTAS] = {
OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};

if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
return -EINVAL;

return dquot_enable(sb_dqopt(sb)->files[type], type,
format_id, DQUOT_LIMITS_ENABLED);
}

/* Handle quota off quotactl */
static int ocfs2_quota_off(struct super_block *sb, int type)
{
return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
}

static const struct quotactl_ops ocfs2_quotactl_ops = {
.quota_on_meta = ocfs2_quota_on,
.quota_off = ocfs2_quota_off,
.quota_sync = dquot_quota_sync,
.get_info = dquot_get_dqinfo,
.set_info = dquot_set_dqinfo,
.get_dqblk = dquot_get_dqblk,
.set_dqblk = dquot_set_dqblk,
};

static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
{
struct dentry *root;
Expand Down Expand Up @@ -2079,7 +2049,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
sb->s_op = &ocfs2_sops;
sb->s_d_op = &ocfs2_dentry_ops;
sb->s_export_op = &ocfs2_export_ops;
sb->s_qcop = &ocfs2_quotactl_ops;
sb->s_qcop = &dquot_quotactl_sysfile_ops;
sb->dq_op = &ocfs2_quota_operations;
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
sb->s_xattr = ocfs2_xattr_handlers;
Expand Down
107 changes: 98 additions & 9 deletions fs/quota/dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1248,7 +1248,7 @@ static int ignore_hardlimit(struct dquot *dquot)

return capable(CAP_SYS_RESOURCE) &&
(info->dqi_format->qf_fmt_id != QFMT_VFS_OLD ||
!(info->dqi_flags & V1_DQF_RSQUASH));
!(info->dqi_flags & DQF_ROOT_SQUASH));
}

/* needs dq_data_lock */
Expand Down Expand Up @@ -2385,14 +2385,84 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
}
EXPORT_SYMBOL(dquot_quota_on_mount);

static inline qsize_t qbtos(qsize_t blocks)
static int dquot_quota_enable(struct super_block *sb, unsigned int flags)
{
return blocks << QIF_DQBLKSIZE_BITS;
int ret;
int type;
struct quota_info *dqopt = sb_dqopt(sb);

if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
return -ENOSYS;
/* Accounting cannot be turned on while fs is mounted */
flags &= ~(FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT);
if (!flags)
return -EINVAL;
for (type = 0; type < MAXQUOTAS; type++) {
if (!(flags & qtype_enforce_flag(type)))
continue;
/* Can't enforce without accounting */
if (!sb_has_quota_usage_enabled(sb, type))
return -EINVAL;
ret = dquot_enable(dqopt->files[type], type,
dqopt->info[type].dqi_fmt_id,
DQUOT_LIMITS_ENABLED);
if (ret < 0)
goto out_err;
}
return 0;
out_err:
/* Backout enforcement enablement we already did */
for (type--; type >= 0; type--) {
if (flags & qtype_enforce_flag(type))
dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
}
/* Error code translation for better compatibility with XFS */
if (ret == -EBUSY)
ret = -EEXIST;
return ret;
}

static inline qsize_t stoqb(qsize_t space)
static int dquot_quota_disable(struct super_block *sb, unsigned int flags)
{
return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
int ret;
int type;
struct quota_info *dqopt = sb_dqopt(sb);

if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
return -ENOSYS;
/*
* We don't support turning off accounting via quotactl. In principle
* quota infrastructure can do this but filesystems don't expect
* userspace to be able to do it.
*/
if (flags &
(FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT))
return -EOPNOTSUPP;

/* Filter out limits not enabled */
for (type = 0; type < MAXQUOTAS; type++)
if (!sb_has_quota_limits_enabled(sb, type))
flags &= ~qtype_enforce_flag(type);
/* Nothing left? */
if (!flags)
return -EEXIST;
for (type = 0; type < MAXQUOTAS; type++) {
if (flags & qtype_enforce_flag(type)) {
ret = dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
if (ret < 0)
goto out_err;
}
}
return 0;
out_err:
/* Backout enforcement disabling we already did */
for (type--; type >= 0; type--) {
if (flags & qtype_enforce_flag(type))
dquot_enable(dqopt->files[type], type,
dqopt->info[type].dqi_fmt_id,
DQUOT_LIMITS_ENABLED);
}
return ret;
}

/* Generic routine for getting common part of quota structure */
Expand Down Expand Up @@ -2444,13 +2514,13 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
return -EINVAL;

if (((di->d_fieldmask & QC_SPC_SOFT) &&
stoqb(di->d_spc_softlimit) > dqi->dqi_maxblimit) ||
di->d_spc_softlimit > dqi->dqi_max_spc_limit) ||
((di->d_fieldmask & QC_SPC_HARD) &&
stoqb(di->d_spc_hardlimit) > dqi->dqi_maxblimit) ||
di->d_spc_hardlimit > dqi->dqi_max_spc_limit) ||
((di->d_fieldmask & QC_INO_SOFT) &&
(di->d_ino_softlimit > dqi->dqi_maxilimit)) ||
(di->d_ino_softlimit > dqi->dqi_max_ino_limit)) ||
((di->d_fieldmask & QC_INO_HARD) &&
(di->d_ino_hardlimit > dqi->dqi_maxilimit)))
(di->d_ino_hardlimit > dqi->dqi_max_ino_limit)))
return -ERANGE;

spin_lock(&dq_data_lock);
Expand Down Expand Up @@ -2577,6 +2647,14 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
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 &&
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;
Expand Down Expand Up @@ -2606,6 +2684,17 @@ const struct quotactl_ops dquot_quotactl_ops = {
};
EXPORT_SYMBOL(dquot_quotactl_ops);

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,
.set_info = dquot_set_dqinfo,
.get_dqblk = dquot_get_dqblk,
.set_dqblk = dquot_set_dqblk
};
EXPORT_SYMBOL(dquot_quotactl_sysfile_ops);

static int do_proc_dqstats(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
Expand Down
Loading

0 comments on commit c5452a5

Please sign in to comment.