forked from Minki/linux
0b61f8a407
Remove the verbose license text from XFS files and replace them with SPDX tags. This does not change the license of any of the code, merely refers to the common, up-to-date license files in LICENSES/ This change was mostly scripted. fs/xfs/Makefile and fs/xfs/libxfs/xfs_fs.h were modified by hand, the rest were detected and modified by the following command: for f in `git grep -l "GNU General" fs/xfs/` ; do echo $f cat $f | awk -f hdr.awk > $f.new mv -f $f.new $f done And the hdr.awk script that did the modification (including detecting the difference between GPL-2.0 and GPL-2.0+ licenses) is as follows: $ cat hdr.awk BEGIN { hdr = 1.0 tag = "GPL-2.0" str = "" } /^ \* This program is free software/ { hdr = 2.0; next } /any later version./ { tag = "GPL-2.0+" next } /^ \*\// { if (hdr > 0.0) { print "// SPDX-License-Identifier: " tag print str print $0 str="" hdr = 0.0 next } print $0 next } /^ \* / { if (hdr > 1.0) next if (hdr > 0.0) { if (str != "") str = str "\n" str = str $0 next } print $0 next } /^ \*/ { if (hdr > 0.0) next print $0 next } // { if (hdr > 0.0) { if (str != "") str = str "\n" str = str $0 next } print $0 } END { } $ Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
289 lines
6.4 KiB
C
289 lines
6.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2008, Christoph Hellwig
|
|
* All Rights Reserved.
|
|
*/
|
|
#include "xfs.h"
|
|
#include "xfs_format.h"
|
|
#include "xfs_log_format.h"
|
|
#include "xfs_trans_resv.h"
|
|
#include "xfs_mount.h"
|
|
#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)
|
|
{
|
|
switch (type) {
|
|
case USRQUOTA:
|
|
return XFS_DQ_USER;
|
|
case GRPQUOTA:
|
|
return XFS_DQ_GROUP;
|
|
default:
|
|
return XFS_DQ_PROJ;
|
|
}
|
|
}
|
|
|
|
#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,
|
|
int type,
|
|
struct qc_info *info)
|
|
{
|
|
struct xfs_mount *mp = XFS_M(sb);
|
|
struct qc_dqblk newlim;
|
|
|
|
if (sb_rdonly(sb))
|
|
return -EROFS;
|
|
if (!XFS_IS_QUOTA_RUNNING(mp))
|
|
return -ENOSYS;
|
|
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;
|
|
|
|
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;
|
|
|
|
return xfs_qm_scall_setqlim(mp, 0, xfs_quota_type(type), &newlim);
|
|
}
|
|
|
|
static unsigned int
|
|
xfs_quota_flags(unsigned int uflags)
|
|
{
|
|
unsigned int flags = 0;
|
|
|
|
if (uflags & FS_QUOTA_UDQ_ACCT)
|
|
flags |= XFS_UQUOTA_ACCT;
|
|
if (uflags & FS_QUOTA_PDQ_ACCT)
|
|
flags |= XFS_PQUOTA_ACCT;
|
|
if (uflags & FS_QUOTA_GDQ_ACCT)
|
|
flags |= XFS_GQUOTA_ACCT;
|
|
if (uflags & FS_QUOTA_UDQ_ENFD)
|
|
flags |= XFS_UQUOTA_ENFD;
|
|
if (uflags & FS_QUOTA_GDQ_ENFD)
|
|
flags |= XFS_GQUOTA_ENFD;
|
|
if (uflags & FS_QUOTA_PDQ_ENFD)
|
|
flags |= XFS_PQUOTA_ENFD;
|
|
|
|
return flags;
|
|
}
|
|
|
|
STATIC int
|
|
xfs_quota_enable(
|
|
struct super_block *sb,
|
|
unsigned int uflags)
|
|
{
|
|
struct xfs_mount *mp = XFS_M(sb);
|
|
|
|
if (sb_rdonly(sb))
|
|
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_rdonly(sb))
|
|
return -EROFS;
|
|
if (!XFS_IS_QUOTA_RUNNING(mp))
|
|
return -ENOSYS;
|
|
if (!XFS_IS_QUOTA_ON(mp))
|
|
return -EINVAL;
|
|
|
|
return xfs_qm_scall_quotaoff(mp, xfs_quota_flags(uflags));
|
|
}
|
|
|
|
STATIC int
|
|
xfs_fs_rm_xquota(
|
|
struct super_block *sb,
|
|
unsigned int uflags)
|
|
{
|
|
struct xfs_mount *mp = XFS_M(sb);
|
|
unsigned int flags = 0;
|
|
|
|
if (sb_rdonly(sb))
|
|
return -EROFS;
|
|
|
|
if (XFS_IS_QUOTA_ON(mp))
|
|
return -EINVAL;
|
|
|
|
if (uflags & FS_USER_QUOTA)
|
|
flags |= XFS_DQ_USER;
|
|
if (uflags & FS_GROUP_QUOTA)
|
|
flags |= XFS_DQ_GROUP;
|
|
if (uflags & FS_PROJ_QUOTA)
|
|
flags |= XFS_DQ_PROJ;
|
|
|
|
return xfs_qm_scall_trunc_qfiles(mp, flags);
|
|
}
|
|
|
|
STATIC int
|
|
xfs_fs_get_dqblk(
|
|
struct super_block *sb,
|
|
struct kqid qid,
|
|
struct qc_dqblk *qdq)
|
|
{
|
|
struct xfs_mount *mp = XFS_M(sb);
|
|
xfs_dqid_t id;
|
|
|
|
if (!XFS_IS_QUOTA_RUNNING(mp))
|
|
return -ENOSYS;
|
|
if (!XFS_IS_QUOTA_ON(mp))
|
|
return -ESRCH;
|
|
|
|
id = from_kqid(&init_user_ns, qid);
|
|
return xfs_qm_scall_getquota(mp, id, xfs_quota_type(qid.type), qdq);
|
|
}
|
|
|
|
/* Return quota info for active quota >= this qid */
|
|
STATIC int
|
|
xfs_fs_get_nextdqblk(
|
|
struct super_block *sb,
|
|
struct kqid *qid,
|
|
struct qc_dqblk *qdq)
|
|
{
|
|
int ret;
|
|
struct xfs_mount *mp = XFS_M(sb);
|
|
xfs_dqid_t id;
|
|
|
|
if (!XFS_IS_QUOTA_RUNNING(mp))
|
|
return -ENOSYS;
|
|
if (!XFS_IS_QUOTA_ON(mp))
|
|
return -ESRCH;
|
|
|
|
id = from_kqid(&init_user_ns, *qid);
|
|
ret = xfs_qm_scall_getquota_next(mp, &id, xfs_quota_type(qid->type),
|
|
qdq);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/* ID may be different, so convert back what we got */
|
|
*qid = make_kqid(current_user_ns(), qid->type, id);
|
|
return 0;
|
|
}
|
|
|
|
STATIC int
|
|
xfs_fs_set_dqblk(
|
|
struct super_block *sb,
|
|
struct kqid qid,
|
|
struct qc_dqblk *qdq)
|
|
{
|
|
struct xfs_mount *mp = XFS_M(sb);
|
|
|
|
if (sb_rdonly(sb))
|
|
return -EROFS;
|
|
if (!XFS_IS_QUOTA_RUNNING(mp))
|
|
return -ENOSYS;
|
|
if (!XFS_IS_QUOTA_ON(mp))
|
|
return -ESRCH;
|
|
|
|
return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
|
|
xfs_quota_type(qid.type), qdq);
|
|
}
|
|
|
|
const struct quotactl_ops xfs_quotactl_operations = {
|
|
.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,
|
|
.get_dqblk = xfs_fs_get_dqblk,
|
|
.get_nextdqblk = xfs_fs_get_nextdqblk,
|
|
.set_dqblk = xfs_fs_set_dqblk,
|
|
};
|