提交 c5452a58 编写于 作者: L Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/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
  ...
...@@ -466,6 +466,8 @@ static void ext3_put_super (struct super_block * sb) ...@@ -466,6 +466,8 @@ static void ext3_put_super (struct super_block * sb)
} }
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
kfree(sbi->s_blockgroup_lock); kfree(sbi->s_blockgroup_lock);
mutex_destroy(&sbi->s_orphan_lock);
mutex_destroy(&sbi->s_resize_lock);
kfree(sbi); kfree(sbi);
} }
......
...@@ -1046,10 +1046,7 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot); ...@@ -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_write_info(struct super_block *sb, int type);
static int ext4_quota_on(struct super_block *sb, int type, int format_id, static int ext4_quota_on(struct super_block *sb, int type, int format_id,
struct path *path); 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(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 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, static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
size_t len, loff_t off); size_t len, loff_t off);
...@@ -1084,16 +1081,6 @@ static const struct quotactl_ops ext4_qctl_operations = { ...@@ -1084,16 +1081,6 @@ static const struct quotactl_ops ext4_qctl_operations = {
.get_dqblk = dquot_get_dqblk, .get_dqblk = dquot_get_dqblk,
.set_dqblk = dquot_set_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 #endif
static const struct super_operations ext4_sops = { static const struct super_operations ext4_sops = {
...@@ -3935,7 +3922,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3935,7 +3922,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
sb->dq_op = &ext4_quota_operations; sb->dq_op = &ext4_quota_operations;
if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) 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 else
sb->s_qcop = &ext4_qctl_operations; sb->s_qcop = &ext4_qctl_operations;
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
...@@ -5288,21 +5275,6 @@ static int ext4_enable_quotas(struct super_block *sb) ...@@ -5288,21 +5275,6 @@ static int ext4_enable_quotas(struct super_block *sb)
return 0; 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) static int ext4_quota_off(struct super_block *sb, int type)
{ {
struct inode *inode = sb_dqopt(sb)->files[type]; struct inode *inode = sb_dqopt(sb)->files[type];
...@@ -5329,18 +5301,6 @@ static int ext4_quota_off(struct super_block *sb, int type) ...@@ -5329,18 +5301,6 @@ static int ext4_quota_off(struct super_block *sb, int type)
return dquot_quota_off(sb, 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 /* Read data from quotafile - avoid pagecache and such because we cannot afford
* acquiring the locks... As quota files are never truncated and quota code * acquiring the locks... As quota files are never truncated and quota code
* itself serializes the operations (and no one else should touch the files) * itself serializes the operations (and no one else should touch the files)
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* linux/fs/isofs/util.c * linux/fs/isofs/util.c
*/ */
#include <linux/time.h>
#include "isofs.h" #include "isofs.h"
/* /*
...@@ -17,9 +18,9 @@ ...@@ -17,9 +18,9 @@
int iso_date(char * p, int flag) int iso_date(char * p, int flag)
{ {
int year, month, day, hour, minute, second, tz; int year, month, day, hour, minute, second, tz;
int crtime, days, i; int crtime;
year = p[0] - 70; year = p[0];
month = p[1]; month = p[1];
day = p[2]; day = p[2];
hour = p[3]; hour = p[3];
...@@ -31,18 +32,7 @@ int iso_date(char * p, int flag) ...@@ -31,18 +32,7 @@ int iso_date(char * p, int flag)
if (year < 0) { if (year < 0) {
crtime = 0; crtime = 0;
} else { } else {
int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; crtime = mktime64(year+1900, month, day, hour, minute, second);
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;
/* sign extend */ /* sign extend */
if (tz & 0x80) if (tz & 0x80)
......
...@@ -48,6 +48,7 @@ struct ocfs2_quota_recovery { ...@@ -48,6 +48,7 @@ struct ocfs2_quota_recovery {
/* In-memory structure with quota header information */ /* In-memory structure with quota header information */
struct ocfs2_mem_dqinfo { struct ocfs2_mem_dqinfo {
unsigned int dqi_type; /* Quota type this structure describes */ 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_chunks; /* Number of chunks in local quota file */
unsigned int dqi_blocks; /* Number of blocks allocated for 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 */ unsigned int dqi_syncms; /* How often should we sync with other nodes */
......
...@@ -292,7 +292,7 @@ static void olq_update_info(struct buffer_head *bh, void *private) ...@@ -292,7 +292,7 @@ static void olq_update_info(struct buffer_head *bh, void *private)
ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data + ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
OCFS2_LOCAL_INFO_OFF); OCFS2_LOCAL_INFO_OFF);
spin_lock(&dq_data_lock); 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_chunks = cpu_to_le32(oinfo->dqi_chunks);
ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks); ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks);
spin_unlock(&dq_data_lock); spin_unlock(&dq_data_lock);
...@@ -701,8 +701,8 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) ...@@ -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 /* We don't need the lock and we have to acquire quota file locks
* which will later depend on this lock */ * which will later depend on this lock */
mutex_unlock(&sb_dqopt(sb)->dqio_mutex); mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
info->dqi_maxblimit = 0x7fffffffffffffffLL; info->dqi_max_spc_limit = 0x7fffffffffffffffLL;
info->dqi_maxilimit = 0x7fffffffffffffffLL; info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
if (!oinfo) { if (!oinfo) {
mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota" mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota"
...@@ -737,13 +737,13 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) ...@@ -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 + ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
OCFS2_LOCAL_INFO_OFF); 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_chunks = le32_to_cpu(ldinfo->dqi_chunks);
oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks); oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks);
oinfo->dqi_libh = bh; oinfo->dqi_libh = bh;
/* We crashed when using local quota file? */ /* 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; rec = OCFS2_SB(sb)->quota_rec;
if (!rec) { if (!rec) {
rec = ocfs2_alloc_quota_recovery(); rec = ocfs2_alloc_quota_recovery();
...@@ -772,7 +772,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) ...@@ -772,7 +772,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
} }
/* Now mark quota file as used */ /* 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); status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -857,7 +857,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type) ...@@ -857,7 +857,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type)
goto out; goto out;
/* Mark local file as clean */ /* Mark local file as clean */
info->dqi_flags |= OLQF_CLEAN; oinfo->dqi_flags |= OLQF_CLEAN;
status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], status = ocfs2_modify_bh(sb_dqopt(sb)->files[type],
oinfo->dqi_libh, oinfo->dqi_libh,
olq_update_info, olq_update_info,
......
...@@ -1000,36 +1000,6 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) ...@@ -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) static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
{ {
struct dentry *root; struct dentry *root;
...@@ -2079,7 +2049,7 @@ static int ocfs2_initialize_super(struct super_block *sb, ...@@ -2079,7 +2049,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
sb->s_op = &ocfs2_sops; sb->s_op = &ocfs2_sops;
sb->s_d_op = &ocfs2_dentry_ops; sb->s_d_op = &ocfs2_dentry_ops;
sb->s_export_op = &ocfs2_export_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->dq_op = &ocfs2_quota_operations;
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
sb->s_xattr = ocfs2_xattr_handlers; sb->s_xattr = ocfs2_xattr_handlers;
......
...@@ -1248,7 +1248,7 @@ static int ignore_hardlimit(struct dquot *dquot) ...@@ -1248,7 +1248,7 @@ static int ignore_hardlimit(struct dquot *dquot)
return capable(CAP_SYS_RESOURCE) && return capable(CAP_SYS_RESOURCE) &&
(info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || (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 */ /* needs dq_data_lock */
...@@ -2385,14 +2385,84 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name, ...@@ -2385,14 +2385,84 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
} }
EXPORT_SYMBOL(dquot_quota_on_mount); 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 */ /* Generic routine for getting common part of quota structure */
...@@ -2444,13 +2514,13 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di) ...@@ -2444,13 +2514,13 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
return -EINVAL; return -EINVAL;
if (((di->d_fieldmask & QC_SPC_SOFT) && 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) && ((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_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_fieldmask & QC_INO_HARD) &&
(di->d_ino_hardlimit > dqi->dqi_maxilimit))) (di->d_ino_hardlimit > dqi->dqi_max_ino_limit)))
return -ERANGE; return -ERANGE;
spin_lock(&dq_data_lock); spin_lock(&dq_data_lock);
...@@ -2577,6 +2647,14 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) ...@@ -2577,6 +2647,14 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
goto out; goto out;
} }
mi = sb_dqopt(sb)->info + type; 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); spin_lock(&dq_data_lock);
if (ii->dqi_valid & IIF_BGRACE) if (ii->dqi_valid & IIF_BGRACE)
mi->dqi_bgrace = ii->dqi_bgrace; mi->dqi_bgrace = ii->dqi_bgrace;
...@@ -2606,6 +2684,17 @@ const struct quotactl_ops dquot_quotactl_ops = { ...@@ -2606,6 +2684,17 @@ const struct quotactl_ops dquot_quotactl_ops = {
}; };
EXPORT_SYMBOL(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, static int do_proc_dqstats(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos) void __user *buffer, size_t *lenp, loff_t *ppos)
{ {
......
...@@ -66,18 +66,40 @@ static int quota_sync_all(int type) ...@@ -66,18 +66,40 @@ static int quota_sync_all(int type)
return ret; return ret;
} }
unsigned int qtype_enforce_flag(int type)
{
switch (type) {
case USRQUOTA:
return FS_QUOTA_UDQ_ENFD;
case GRPQUOTA:
return FS_QUOTA_GDQ_ENFD;
case PRJQUOTA:
return FS_QUOTA_PDQ_ENFD;
}
return 0;
}
static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
struct path *path) struct path *path)
{ {
if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta) if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_enable)
return -ENOSYS; return -ENOSYS;
if (sb->s_qcop->quota_on_meta) if (sb->s_qcop->quota_enable)
return sb->s_qcop->quota_on_meta(sb, type, id); return sb->s_qcop->quota_enable(sb, qtype_enforce_flag(type));
if (IS_ERR(path)) if (IS_ERR(path))
return PTR_ERR(path); return PTR_ERR(path);
return sb->s_qcop->quota_on(sb, type, id, path); return sb->s_qcop->quota_on(sb, type, id, path);
} }
static int quota_quotaoff(struct super_block *sb, int type)
{
if (!sb->s_qcop->quota_off && !sb->s_qcop->quota_disable)
return -ENOSYS;
if (sb->s_qcop->quota_disable)
return sb->s_qcop->quota_disable(sb, qtype_enforce_flag(type));
return sb->s_qcop->quota_off(sb, type);
}
static int quota_getfmt(struct super_block *sb, int type, void __user *addr) static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
{ {
__u32 fmt; __u32 fmt;
...@@ -208,15 +230,26 @@ static int quota_setquota(struct super_block *sb, int type, qid_t id, ...@@ -208,15 +230,26 @@ static int quota_setquota(struct super_block *sb, int type, qid_t id,
return sb->s_qcop->set_dqblk(sb, qid, &fdq); return sb->s_qcop->set_dqblk(sb, qid, &fdq);
} }
static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) static int quota_enable(struct super_block *sb, void __user *addr)
{ {
__u32 flags; __u32 flags;
if (copy_from_user(&flags, addr, sizeof(flags))) if (copy_from_user(&flags, addr, sizeof(flags)))
return -EFAULT; return -EFAULT;
if (!sb->s_qcop->set_xstate) if (!sb->s_qcop->quota_enable)
return -ENOSYS; return -ENOSYS;
return sb->s_qcop->set_xstate(sb, flags, cmd); return sb->s_qcop->quota_enable(sb, flags);
}
static int quota_disable(struct super_block *sb, void __user *addr)
{
__u32 flags;
if (copy_from_user(&flags, addr, sizeof(flags)))
return -EFAULT;
if (!sb->s_qcop->quota_disable)
return -ENOSYS;
return sb->s_qcop->quota_disable(sb, flags);
} }
static int quota_getxstate(struct super_block *sb, void __user *addr) static int quota_getxstate(struct super_block *sb, void __user *addr)
...@@ -429,9 +462,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, ...@@ -429,9 +462,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
case Q_QUOTAON: case Q_QUOTAON:
return quota_quotaon(sb, type, cmd, id, path); return quota_quotaon(sb, type, cmd, id, path);
case Q_QUOTAOFF: case Q_QUOTAOFF:
if (!sb->s_qcop->quota_off) return quota_quotaoff(sb, type);
return -ENOSYS;
return sb->s_qcop->quota_off(sb, type);
case Q_GETFMT: case Q_GETFMT:
return quota_getfmt(sb, type, addr); return quota_getfmt(sb, type, addr);
case Q_GETINFO: case Q_GETINFO:
...@@ -447,8 +478,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, ...@@ -447,8 +478,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
return -ENOSYS; return -ENOSYS;
return sb->s_qcop->quota_sync(sb, type); return sb->s_qcop->quota_sync(sb, type);
case Q_XQUOTAON: case Q_XQUOTAON:
return quota_enable(sb, addr);
case Q_XQUOTAOFF: case Q_XQUOTAOFF:
return quota_setxstate(sb, cmd, addr); return quota_disable(sb, addr);
case Q_XQUOTARM: case Q_XQUOTARM:
return quota_rmxquota(sb, addr); return quota_rmxquota(sb, addr);
case Q_XGETQSTAT: case Q_XGETQSTAT:
......
...@@ -169,8 +169,8 @@ static int v1_read_file_info(struct super_block *sb, int type) ...@@ -169,8 +169,8 @@ static int v1_read_file_info(struct super_block *sb, int type)
} }
ret = 0; ret = 0;
/* limits are stored as unsigned 32-bit data */ /* limits are stored as unsigned 32-bit data */
dqopt->info[type].dqi_maxblimit = 0xffffffff; dqopt->info[type].dqi_max_spc_limit = 0xffffffffULL << QUOTABLOCK_BITS;
dqopt->info[type].dqi_maxilimit = 0xffffffff; dqopt->info[type].dqi_max_ino_limit = 0xffffffff;
dqopt->info[type].dqi_igrace = dqopt->info[type].dqi_igrace =
dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME; dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
dqopt->info[type].dqi_bgrace = dqopt->info[type].dqi_bgrace =
......
...@@ -117,16 +117,17 @@ static int v2_read_file_info(struct super_block *sb, int type) ...@@ -117,16 +117,17 @@ static int v2_read_file_info(struct super_block *sb, int type)
qinfo = info->dqi_priv; qinfo = info->dqi_priv;
if (version == 0) { if (version == 0) {
/* limits are stored as unsigned 32-bit data */ /* limits are stored as unsigned 32-bit data */
info->dqi_maxblimit = 0xffffffff; info->dqi_max_spc_limit = 0xffffffffULL << QUOTABLOCK_BITS;
info->dqi_maxilimit = 0xffffffff; info->dqi_max_ino_limit = 0xffffffff;
} else { } else {
/* used space is stored as unsigned 64-bit value */ /* used space is stored as unsigned 64-bit value in bytes */
info->dqi_maxblimit = 0xffffffffffffffffULL; /* 2^64-1 */ info->dqi_max_spc_limit = 0xffffffffffffffffULL; /* 2^64-1 */
info->dqi_maxilimit = 0xffffffffffffffffULL; info->dqi_max_ino_limit = 0xffffffffffffffffULL;
} }
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
info->dqi_flags = le32_to_cpu(dinfo.dqi_flags); /* No flags currently supported */
info->dqi_flags = 0;
qinfo->dqi_sb = sb; qinfo->dqi_sb = sb;
qinfo->dqi_type = type; qinfo->dqi_type = type;
qinfo->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks); qinfo->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
...@@ -157,7 +158,8 @@ static int v2_write_file_info(struct super_block *sb, int type) ...@@ -157,7 +158,8 @@ static int v2_write_file_info(struct super_block *sb, int type)
info->dqi_flags &= ~DQF_INFO_DIRTY; info->dqi_flags &= ~DQF_INFO_DIRTY;
dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace); dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace); dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK); /* No flags currently supported */
dinfo.dqi_flags = cpu_to_le32(0);
spin_unlock(&dq_data_lock); spin_unlock(&dq_data_lock);
dinfo.dqi_blocks = cpu_to_le32(qinfo->dqi_blocks); dinfo.dqi_blocks = cpu_to_le32(qinfo->dqi_blocks);
dinfo.dqi_free_blk = cpu_to_le32(qinfo->dqi_free_blk); dinfo.dqi_free_blk = cpu_to_le32(qinfo->dqi_free_blk);
......
...@@ -2,10 +2,12 @@ config UDF_FS ...@@ -2,10 +2,12 @@ config UDF_FS
tristate "UDF file system support" tristate "UDF file system support"
select CRC_ITU_T select CRC_ITU_T
help help
This is the new file system used on some CD-ROMs and DVDs. Say Y if This is a file system used on some CD-ROMs and DVDs. Since the
you intend to mount DVD discs or CDRW's written in packet mode, or file system is supported by multiple operating systems and is more
if written to by other UDF utilities, such as DirectCD. compatible with standard unix file systems, it is also suitable for
Please read <file:Documentation/filesystems/udf.txt>. removable USB disks. Say Y if you intend to mount DVD discs or CDRW's
written in packet mode, or if you want to use UDF for removable USB
disks. Please read <file:Documentation/filesystems/udf.txt>.
To compile this file system support as a module, choose M here: the To compile this file system support as a module, choose M here: the
module will be called udf. module will be called udf.
......
...@@ -750,7 +750,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -750,7 +750,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
/* Are we beyond EOF? */ /* Are we beyond EOF? */
if (etype == -1) { if (etype == -1) {
int ret; int ret;
isBeyondEOF = 1; isBeyondEOF = true;
if (count) { if (count) {
if (c) if (c)
laarr[0] = laarr[1]; laarr[0] = laarr[1];
...@@ -792,7 +792,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -792,7 +792,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
endnum = c + 1; endnum = c + 1;
lastblock = 1; lastblock = 1;
} else { } else {
isBeyondEOF = 0; isBeyondEOF = false;
endnum = startnum = ((count > 2) ? 2 : count); endnum = startnum = ((count > 2) ? 2 : count);
/* if the current extent is in position 0, /* if the current extent is in position 0,
...@@ -1288,6 +1288,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1288,6 +1288,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
struct kernel_lb_addr *iloc = &iinfo->i_location; struct kernel_lb_addr *iloc = &iinfo->i_location;
unsigned int link_count; unsigned int link_count;
unsigned int indirections = 0; unsigned int indirections = 0;
int bs = inode->i_sb->s_blocksize;
int ret = -EIO; int ret = -EIO;
reread: reread:
...@@ -1374,38 +1375,35 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1374,38 +1375,35 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) { if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) {
iinfo->i_efe = 1; iinfo->i_efe = 1;
iinfo->i_use = 0; iinfo->i_use = 0;
ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize - ret = udf_alloc_i_data(inode, bs -
sizeof(struct extendedFileEntry)); sizeof(struct extendedFileEntry));
if (ret) if (ret)
goto out; goto out;
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct extendedFileEntry), bh->b_data + sizeof(struct extendedFileEntry),
inode->i_sb->s_blocksize - bs - sizeof(struct extendedFileEntry));
sizeof(struct extendedFileEntry));
} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
iinfo->i_efe = 0; iinfo->i_efe = 0;
iinfo->i_use = 0; iinfo->i_use = 0;
ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize - ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry));
sizeof(struct fileEntry));
if (ret) if (ret)
goto out; goto out;
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct fileEntry), bh->b_data + sizeof(struct fileEntry),
inode->i_sb->s_blocksize - sizeof(struct fileEntry)); bs - sizeof(struct fileEntry));
} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) {
iinfo->i_efe = 0; iinfo->i_efe = 0;
iinfo->i_use = 1; iinfo->i_use = 1;
iinfo->i_lenAlloc = le32_to_cpu( iinfo->i_lenAlloc = le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)-> ((struct unallocSpaceEntry *)bh->b_data)->
lengthAllocDescs); lengthAllocDescs);
ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize - ret = udf_alloc_i_data(inode, bs -
sizeof(struct unallocSpaceEntry)); sizeof(struct unallocSpaceEntry));
if (ret) if (ret)
goto out; goto out;
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct unallocSpaceEntry), bh->b_data + sizeof(struct unallocSpaceEntry),
inode->i_sb->s_blocksize - bs - sizeof(struct unallocSpaceEntry));
sizeof(struct unallocSpaceEntry));
return 0; return 0;
} }
...@@ -1489,6 +1487,15 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1489,6 +1487,15 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
} }
inode->i_generation = iinfo->i_unique; inode->i_generation = iinfo->i_unique;
/*
* Sanity check length of allocation descriptors and extended attrs to
* avoid integer overflows
*/
if (iinfo->i_lenEAttr > bs || iinfo->i_lenAlloc > bs)
goto out;
/* Now do exact checks */
if (udf_file_entry_alloc_offset(inode) + iinfo->i_lenAlloc > bs)
goto out;
/* Sanity checks for files in ICB so that we don't get confused later */ /* Sanity checks for files in ICB so that we don't get confused later */
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
/* /*
...@@ -1498,8 +1505,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1498,8 +1505,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
if (iinfo->i_lenAlloc != inode->i_size) if (iinfo->i_lenAlloc != inode->i_size)
goto out; goto out;
/* File in ICB has to fit in there... */ /* File in ICB has to fit in there... */
if (inode->i_size > inode->i_sb->s_blocksize - if (inode->i_size > bs - udf_file_entry_alloc_offset(inode))
udf_file_entry_alloc_offset(inode))
goto out; goto out;
} }
......
...@@ -1599,7 +1599,7 @@ static noinline int udf_process_sequence( ...@@ -1599,7 +1599,7 @@ static noinline int udf_process_sequence(
struct udf_vds_record *curr; struct udf_vds_record *curr;
struct generic_desc *gd; struct generic_desc *gd;
struct volDescPtr *vdp; struct volDescPtr *vdp;
int done = 0; bool done = false;
uint32_t vdsn; uint32_t vdsn;
uint16_t ident; uint16_t ident;
long next_s = 0, next_e = 0; long next_s = 0, next_e = 0;
...@@ -1680,7 +1680,7 @@ static noinline int udf_process_sequence( ...@@ -1680,7 +1680,7 @@ static noinline int udf_process_sequence(
lastblock = next_e; lastblock = next_e;
next_s = next_e = 0; next_s = next_e = 0;
} else } else
done = 1; done = true;
break; break;
} }
brelse(bh); brelse(bh);
...@@ -2300,6 +2300,7 @@ static void udf_put_super(struct super_block *sb) ...@@ -2300,6 +2300,7 @@ static void udf_put_super(struct super_block *sb)
udf_close_lvid(sb); udf_close_lvid(sb);
brelse(sbi->s_lvid_bh); brelse(sbi->s_lvid_bh);
udf_sb_free_partitions(sb); udf_sb_free_partitions(sb);
mutex_destroy(&sbi->s_alloc_mutex);
kfree(sb->s_fs_info); kfree(sb->s_fs_info);
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
} }
......
...@@ -329,22 +329,16 @@ xfs_qm_scall_quotaon( ...@@ -329,22 +329,16 @@ xfs_qm_scall_quotaon(
return -EINVAL; return -EINVAL;
} }
/* No fs can turn on quotas with a delayed effect */
ASSERT((flags & XFS_ALL_QUOTA_ACCT) == 0);
/* /*
* Can't enforce without accounting. We check the superblock * Can't enforce without accounting. We check the superblock
* qflags here instead of m_qflags because rootfs can have * qflags here instead of m_qflags because rootfs can have
* quota acct on ondisk without m_qflags' knowing. * quota acct on ondisk without m_qflags' knowing.
*/ */
if (((flags & XFS_UQUOTA_ACCT) == 0 && if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
(flags & XFS_UQUOTA_ENFD)) || (flags & XFS_UQUOTA_ENFD)) ||
((flags & XFS_GQUOTA_ACCT) == 0 && ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
(flags & XFS_GQUOTA_ENFD)) || (flags & XFS_GQUOTA_ENFD)) ||
((flags & XFS_PQUOTA_ACCT) == 0 && ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
(flags & XFS_PQUOTA_ENFD))) { (flags & XFS_PQUOTA_ENFD))) {
xfs_debug(mp, xfs_debug(mp,
"%s: Can't enforce without acct, flags=%x sbflags=%x", "%s: Can't enforce without acct, flags=%x sbflags=%x",
...@@ -383,8 +377,7 @@ xfs_qm_scall_quotaon( ...@@ -383,8 +377,7 @@ xfs_qm_scall_quotaon(
((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) != ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
(mp->m_qflags & XFS_PQUOTA_ACCT)) || (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) != ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
(mp->m_qflags & XFS_GQUOTA_ACCT)) || (mp->m_qflags & XFS_GQUOTA_ACCT)))
(flags & XFS_ALL_QUOTA_ENFD) == 0)
return 0; return 0;
if (! XFS_IS_QUOTA_RUNNING(mp)) if (! XFS_IS_QUOTA_RUNNING(mp))
...@@ -421,20 +414,12 @@ xfs_qm_scall_getqstat( ...@@ -421,20 +414,12 @@ xfs_qm_scall_getqstat(
memset(out, 0, sizeof(fs_quota_stat_t)); memset(out, 0, sizeof(fs_quota_stat_t));
out->qs_version = FS_QSTAT_VERSION; out->qs_version = FS_QSTAT_VERSION;
if (!xfs_sb_version_hasquota(&mp->m_sb)) {
out->qs_uquota.qfs_ino = NULLFSINO;
out->qs_gquota.qfs_ino = NULLFSINO;
return 0;
}
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags & out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
(XFS_ALL_QUOTA_ACCT| (XFS_ALL_QUOTA_ACCT|
XFS_ALL_QUOTA_ENFD)); XFS_ALL_QUOTA_ENFD));
if (q) { uip = q->qi_uquotaip;
uip = q->qi_uquotaip; gip = q->qi_gquotaip;
gip = q->qi_gquotaip; pip = q->qi_pquotaip;
pip = q->qi_pquotaip;
}
if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) { if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
0, 0, &uip) == 0) 0, 0, &uip) == 0)
...@@ -480,14 +465,13 @@ xfs_qm_scall_getqstat( ...@@ -480,14 +465,13 @@ xfs_qm_scall_getqstat(
if (temppqip) if (temppqip)
IRELE(pip); IRELE(pip);
} }
if (q) { out->qs_incoredqs = q->qi_dquots;
out->qs_incoredqs = q->qi_dquots; out->qs_btimelimit = q->qi_btimelimit;
out->qs_btimelimit = q->qi_btimelimit; out->qs_itimelimit = q->qi_itimelimit;
out->qs_itimelimit = q->qi_itimelimit; out->qs_rtbtimelimit = q->qi_rtbtimelimit;
out->qs_rtbtimelimit = q->qi_rtbtimelimit; out->qs_bwarnlimit = q->qi_bwarnlimit;
out->qs_bwarnlimit = q->qi_bwarnlimit; out->qs_iwarnlimit = q->qi_iwarnlimit;
out->qs_iwarnlimit = q->qi_iwarnlimit;
}
return 0; return 0;
} }
...@@ -508,13 +492,6 @@ xfs_qm_scall_getqstatv( ...@@ -508,13 +492,6 @@ xfs_qm_scall_getqstatv(
bool tempgqip = false; bool tempgqip = false;
bool temppqip = false; bool temppqip = false;
if (!xfs_sb_version_hasquota(&mp->m_sb)) {
out->qs_uquota.qfs_ino = NULLFSINO;
out->qs_gquota.qfs_ino = NULLFSINO;
out->qs_pquota.qfs_ino = NULLFSINO;
return 0;
}
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags & out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
(XFS_ALL_QUOTA_ACCT| (XFS_ALL_QUOTA_ACCT|
XFS_ALL_QUOTA_ENFD)); XFS_ALL_QUOTA_ENFD));
...@@ -522,11 +499,9 @@ xfs_qm_scall_getqstatv( ...@@ -522,11 +499,9 @@ xfs_qm_scall_getqstatv(
out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino; out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino; out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
if (q) { uip = q->qi_uquotaip;
uip = q->qi_uquotaip; gip = q->qi_gquotaip;
gip = q->qi_gquotaip; pip = q->qi_pquotaip;
pip = q->qi_pquotaip;
}
if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) { if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
0, 0, &uip) == 0) 0, 0, &uip) == 0)
...@@ -561,14 +536,13 @@ xfs_qm_scall_getqstatv( ...@@ -561,14 +536,13 @@ xfs_qm_scall_getqstatv(
if (temppqip) if (temppqip)
IRELE(pip); IRELE(pip);
} }
if (q) { out->qs_incoredqs = q->qi_dquots;
out->qs_incoredqs = q->qi_dquots; out->qs_btimelimit = q->qi_btimelimit;
out->qs_btimelimit = q->qi_btimelimit; out->qs_itimelimit = q->qi_itimelimit;
out->qs_itimelimit = q->qi_itimelimit; out->qs_rtbtimelimit = q->qi_rtbtimelimit;
out->qs_rtbtimelimit = q->qi_rtbtimelimit; out->qs_bwarnlimit = q->qi_bwarnlimit;
out->qs_bwarnlimit = q->qi_bwarnlimit; out->qs_iwarnlimit = q->qi_iwarnlimit;
out->qs_iwarnlimit = q->qi_iwarnlimit;
}
return 0; return 0;
} }
......
...@@ -64,19 +64,10 @@ xfs_fs_get_xstatev( ...@@ -64,19 +64,10 @@ xfs_fs_get_xstatev(
return xfs_qm_scall_getqstatv(mp, fqs); return xfs_qm_scall_getqstatv(mp, fqs);
} }
STATIC int static unsigned int
xfs_fs_set_xstate( xfs_quota_flags(unsigned int uflags)
struct super_block *sb,
unsigned int uflags,
int op)
{ {
struct xfs_mount *mp = XFS_M(sb); unsigned int flags = 0;
unsigned int flags = 0;
if (sb->s_flags & MS_RDONLY)
return -EROFS;
if (op != Q_XQUOTARM && !XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
if (uflags & FS_QUOTA_UDQ_ACCT) if (uflags & FS_QUOTA_UDQ_ACCT)
flags |= XFS_UQUOTA_ACCT; flags |= XFS_UQUOTA_ACCT;
...@@ -91,16 +82,39 @@ xfs_fs_set_xstate( ...@@ -91,16 +82,39 @@ xfs_fs_set_xstate(
if (uflags & FS_QUOTA_PDQ_ENFD) if (uflags & FS_QUOTA_PDQ_ENFD)
flags |= XFS_PQUOTA_ENFD; flags |= XFS_PQUOTA_ENFD;
switch (op) { return flags;
case Q_XQUOTAON: }
return xfs_qm_scall_quotaon(mp, flags);
case Q_XQUOTAOFF: STATIC int
if (!XFS_IS_QUOTA_ON(mp)) xfs_quota_enable(
return -EINVAL; struct super_block *sb,
return xfs_qm_scall_quotaoff(mp, flags); unsigned int uflags)
} {
struct xfs_mount *mp = XFS_M(sb);
if (sb->s_flags & MS_RDONLY)
return -EROFS;
if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
return xfs_qm_scall_quotaon(mp, xfs_quota_flags(uflags));
}
STATIC int
xfs_quota_disable(
struct super_block *sb,
unsigned int uflags)
{
struct xfs_mount *mp = XFS_M(sb);
if (sb->s_flags & MS_RDONLY)
return -EROFS;
if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
if (!XFS_IS_QUOTA_ON(mp))
return -EINVAL;
return -EINVAL; return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
} }
STATIC int STATIC int
...@@ -166,7 +180,8 @@ xfs_fs_set_dqblk( ...@@ -166,7 +180,8 @@ xfs_fs_set_dqblk(
const struct quotactl_ops xfs_quotactl_operations = { const struct quotactl_ops xfs_quotactl_operations = {
.get_xstatev = xfs_fs_get_xstatev, .get_xstatev = xfs_fs_get_xstatev,
.get_xstate = xfs_fs_get_xstate, .get_xstate = xfs_fs_get_xstate,
.set_xstate = xfs_fs_set_xstate, .quota_enable = xfs_quota_enable,
.quota_disable = xfs_quota_disable,
.rm_xquota = xfs_fs_rm_xquota, .rm_xquota = xfs_fs_rm_xquota,
.get_dqblk = xfs_fs_get_dqblk, .get_dqblk = xfs_fs_get_dqblk,
.set_dqblk = xfs_fs_set_dqblk, .set_dqblk = xfs_fs_set_dqblk,
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
#ifndef _LINUX_DQBLK_V1_H #ifndef _LINUX_DQBLK_V1_H
#define _LINUX_DQBLK_V1_H #define _LINUX_DQBLK_V1_H
/* Root squash turned on */
#define V1_DQF_RSQUASH 1
/* Numbers of blocks needed for updates */ /* Numbers of blocks needed for updates */
#define V1_INIT_ALLOC 1 #define V1_INIT_ALLOC 1
#define V1_INIT_REWRITE 1 #define V1_INIT_REWRITE 1
......
...@@ -956,15 +956,6 @@ void __log_wait_for_space(journal_t *journal); ...@@ -956,15 +956,6 @@ void __log_wait_for_space(journal_t *journal);
extern void __journal_drop_transaction(journal_t *, transaction_t *); extern void __journal_drop_transaction(journal_t *, transaction_t *);
extern int cleanup_journal_tail(journal_t *); extern int cleanup_journal_tail(journal_t *);
/* Debugging code only: */
#define jbd_ENOSYS() \
do { \
printk (KERN_ERR "JBD unimplemented function %s\n", __func__); \
current->state = TASK_UNINTERRUPTIBLE; \
schedule(); \
} while (1)
/* /*
* is_journal_abort * is_journal_abort
* *
......
...@@ -1251,15 +1251,6 @@ void __jbd2_log_wait_for_space(journal_t *journal); ...@@ -1251,15 +1251,6 @@ void __jbd2_log_wait_for_space(journal_t *journal);
extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *); extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *);
extern int jbd2_cleanup_journal_tail(journal_t *); extern int jbd2_cleanup_journal_tail(journal_t *);
/* Debugging code only: */
#define jbd_ENOSYS() \
do { \
printk (KERN_ERR "JBD unimplemented function %s\n", __func__); \
current->state = TASK_UNINTERRUPTIBLE; \
schedule(); \
} while (1)
/* /*
* is_journal_abort * is_journal_abort
* *
......
...@@ -216,19 +216,21 @@ struct mem_dqinfo { ...@@ -216,19 +216,21 @@ struct mem_dqinfo {
unsigned long dqi_flags; unsigned long dqi_flags;
unsigned int dqi_bgrace; unsigned int dqi_bgrace;
unsigned int dqi_igrace; unsigned int dqi_igrace;
qsize_t dqi_maxblimit; qsize_t dqi_max_spc_limit;
qsize_t dqi_maxilimit; qsize_t dqi_max_ino_limit;
void *dqi_priv; void *dqi_priv;
}; };
struct super_block; struct super_block;
#define DQF_MASK 0xffff /* Mask for format specific flags */ /* Mask for flags passed to userspace */
#define DQF_GETINFO_MASK 0x1ffff /* Mask for flags passed to userspace */ #define DQF_GETINFO_MASK (DQF_ROOT_SQUASH | DQF_SYS_FILE)
#define DQF_SETINFO_MASK 0xffff /* Mask for flags modifiable from userspace */ /* Mask for flags modifiable from userspace */
#define DQF_SYS_FILE_B 16 #define DQF_SETINFO_MASK DQF_ROOT_SQUASH
#define DQF_SYS_FILE (1 << DQF_SYS_FILE_B) /* Quota file stored as system file */
#define DQF_INFO_DIRTY_B 31 enum {
DQF_INFO_DIRTY_B = DQF_PRIVATE,
};
#define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */ #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
extern void mark_info_dirty(struct super_block *sb, int type); extern void mark_info_dirty(struct super_block *sb, int type);
...@@ -367,15 +369,15 @@ struct qc_dqblk { ...@@ -367,15 +369,15 @@ struct qc_dqblk {
/* Operations handling requests from userspace */ /* Operations handling requests from userspace */
struct quotactl_ops { struct quotactl_ops {
int (*quota_on)(struct super_block *, int, int, struct path *); int (*quota_on)(struct super_block *, int, int, struct path *);
int (*quota_on_meta)(struct super_block *, int, int);
int (*quota_off)(struct super_block *, int); int (*quota_off)(struct super_block *, int);
int (*quota_enable)(struct super_block *, unsigned int);
int (*quota_disable)(struct super_block *, unsigned int);
int (*quota_sync)(struct super_block *, int); int (*quota_sync)(struct super_block *, int);
int (*get_info)(struct super_block *, int, struct if_dqinfo *); 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 if_dqinfo *);
int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *); int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
int (*set_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_xstate)(struct super_block *, struct fs_quota_stat *);
int (*set_xstate)(struct super_block *, unsigned int, int);
int (*get_xstatev)(struct super_block *, struct fs_quota_statv *); int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
int (*rm_xquota)(struct super_block *, unsigned int); int (*rm_xquota)(struct super_block *, unsigned int);
}; };
......
...@@ -166,6 +166,7 @@ static inline bool sb_has_quota_active(struct super_block *sb, int type) ...@@ -166,6 +166,7 @@ static inline bool sb_has_quota_active(struct super_block *sb, int type)
*/ */
extern const struct dquot_operations dquot_operations; extern const struct dquot_operations dquot_operations;
extern const struct quotactl_ops dquot_quotactl_ops; extern const struct quotactl_ops dquot_quotactl_ops;
extern const struct quotactl_ops dquot_quotactl_sysfile_ops;
#else #else
...@@ -386,4 +387,6 @@ static inline void dquot_release_reservation_block(struct inode *inode, ...@@ -386,4 +387,6 @@ static inline void dquot_release_reservation_block(struct inode *inode,
__dquot_free_space(inode, nr << inode->i_blkbits, DQUOT_SPACE_RESERVE); __dquot_free_space(inode, nr << inode->i_blkbits, DQUOT_SPACE_RESERVE);
} }
unsigned int qtype_enforce_flag(int type);
#endif /* _LINUX_QUOTAOPS_ */ #endif /* _LINUX_QUOTAOPS_ */
...@@ -126,10 +126,22 @@ struct if_dqblk { ...@@ -126,10 +126,22 @@ struct if_dqblk {
#define IIF_FLAGS 4 #define IIF_FLAGS 4
#define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS) #define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS)
enum {
DQF_ROOT_SQUASH_B = 0,
DQF_SYS_FILE_B = 16,
/* Kernel internal flags invisible to userspace */
DQF_PRIVATE
};
/* Root squash enabled (for v1 quota format) */
#define DQF_ROOT_SQUASH (1 << DQF_ROOT_SQUASH_B)
/* Quota stored in a system file */
#define DQF_SYS_FILE (1 << DQF_SYS_FILE_B)
struct if_dqinfo { struct if_dqinfo {
__u64 dqi_bgrace; __u64 dqi_bgrace;
__u64 dqi_igrace; __u64 dqi_igrace;
__u32 dqi_flags; __u32 dqi_flags; /* DFQ_* */
__u32 dqi_valid; __u32 dqi_valid;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册