summaryrefslogtreecommitdiff
path: root/quotaio.c
diff options
context:
space:
mode:
Diffstat (limited to 'quotaio.c')
-rw-r--r--quotaio.c105
1 files changed, 68 insertions, 37 deletions
diff --git a/quotaio.c b/quotaio.c
index e857328..d3c7cb6 100644
--- a/quotaio.c
+++ b/quotaio.c
@@ -37,18 +37,16 @@ struct disk_dqheader {
/*
* Detect quota format and initialize quota IO
*/
-struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
+struct quota_handle *init_io(struct mount_entry *mnt, int type, int fmt, int flags)
{
char *qfname = NULL;
int fd = -1, kernfmt;
struct quota_handle *h = smalloc(sizeof(struct quota_handle));
- const char *mnt_fsname = NULL;
+ int nameflag;
- if (!hasquota(mnt, type, 0))
+ if (!me_hasquota(mnt, type))
goto out_handle;
- if (!(mnt_fsname = get_device_name(mnt->mnt_fsname)))
- goto out_handle;
- if (stat(mnt_fsname, &h->qh_stat) < 0)
+ if (stat(mnt->me_devname, &h->qh_stat) < 0)
memset(&h->qh_stat, 0, sizeof(struct stat));
h->qh_io_flags = 0;
if (flags & IOI_READONLY)
@@ -56,10 +54,10 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
if (flags & IOI_NFS_MIXED_PATHS)
h->qh_io_flags |= IOFL_NFS_MIXED_PATHS;
h->qh_type = type;
- sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev));
- free((char *)mnt_fsname);
- sstrncpy(h->qh_fstype, mnt->mnt_type, MAX_FSTYPE_LEN);
- if (nfs_fstype(mnt->mnt_type)) { /* NFS filesystem? */
+ sstrncpy(h->qh_quotadev, mnt->me_devname, sizeof(h->qh_quotadev));
+ sstrncpy(h->qh_fstype, mnt->me_type, MAX_FSTYPE_LEN);
+ sstrncpy(h->qh_dir, mnt->me_dir, PATH_MAX);
+ if (nfs_fstype(mnt->me_type)) { /* NFS filesystem? */
if (fmt != -1 && fmt != QF_RPC) { /* User wanted some other format? */
errstr(_("Only RPC quota format is allowed on NFS filesystem.\n"));
goto out_handle;
@@ -68,6 +66,8 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
h->qh_fd = -1;
h->qh_fmt = QF_RPC;
h->qh_ops = &quotafile_ops_rpc;
+ memset(&h->qh_info, 0, sizeof(h->qh_info));
+ h->qh_ops->init_io(h);
return h;
#else
errstr(_("RPC quota format not compiled.\n"));
@@ -78,7 +78,8 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
goto out_handle;
}
- if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) { /* XFS filesystem? */
+ if (!strcmp(mnt->me_type, MNTTYPE_XFS) || /* XFS filesystem? */
+ !strcmp(mnt->me_type, MNTTYPE_GFS2)) { /* XFS filesystem? */
if (fmt != -1 && fmt != QF_XFS) { /* User wanted some other format? */
errstr(_("Only XFS quota format is allowed on XFS filesystem.\n"));
goto out_handle;
@@ -96,56 +97,54 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags)
}
if (kern_qfmt_supp(fmt)) { /* Quota compiled and desired format available? */
/* Quota turned on? */
- kernfmt = kern_quota_on(h->qh_quotadev, type, fmt);
+ kernfmt = kern_quota_on(mnt, type, fmt);
if (kernfmt >= 0) {
h->qh_io_flags |= IOFL_QUOTAON;
fmt = kernfmt; /* Default is kernel used format */
}
}
- if (meta_qf_fstype(mnt->mnt_type)) {
+ if (meta_qf_fstype(mnt->me_type) || mnt->me_qfmt[type] == QF_META) {
if (!QIO_ENABLED(h)) {
errstr(_("Quota not supported by the filesystem.\n"));
goto out_handle;
}
- if (flags & IOI_OPENFILE) {
- errstr(_("Operation not supported for filesystems with hidden quota files!\n"));
- goto out_handle;
- }
h->qh_fd = -1;
h->qh_fmt = fmt;
goto set_ops;
}
+ nameflag = (!QIO_ENABLED(h) || flags & IOI_INITSCAN) ? NF_FORMAT : 0;
if (fmt == -1) {
/* Let's try any VFSv0 quota format... */
- if (get_qf_name(mnt, type, QF_VFSV0,
- (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0,
- &qfname) >= 0)
+ if (get_qf_name(mnt, type, QF_VFSV0, nameflag, &qfname) >= 0)
fmt = QF_VFSV0;
/* And then VFSv1 quota format... */
- else if (get_qf_name(mnt, type, QF_VFSV1,
- (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0,
- &qfname) >= 0)
+ else if (get_qf_name(mnt, type, QF_VFSV1, nameflag, &qfname) >= 0)
fmt = QF_VFSV1;
/* And then old quota format... */
- else if (get_qf_name(mnt, type, QF_VFSOLD,
- (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0,
- &qfname) >= 0)
+ else if (get_qf_name(mnt, type, QF_VFSOLD, nameflag, &qfname) >= 0)
fmt = QF_VFSOLD;
else { /* Don't know... */
errstr(_("Cannot find any quota file to work on.\n"));
goto out_handle;
}
} else {
- if (get_qf_name(mnt, type, fmt,
- (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0,
- &qfname) < 0) {
+ if (get_qf_name(mnt, type, fmt, nameflag, &qfname) < 0) {
errstr(_("Quota file not found or has wrong format.\n"));
goto out_handle;
}
}
- if (!QIO_ENABLED(h) || flags & IOI_OPENFILE) { /* Need to open file? */
+ if (!QIO_ENABLED(h) || flags & IOI_INITSCAN) { /* Need to open file? */
+ if (QIO_ENABLED(h)) { /* Kernel uses same file? */
+ unsigned int cmd =
+ (kernel_iface == IFACE_GENERIC) ? Q_SYNC : Q_6_5_SYNC;
+ if (quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev,
+ 0, NULL) < 0) {
+ die(4, _("Cannot sync quotas on device %s: %s\n"),
+ h->qh_quotadev, strerror(errno));
+ }
+ }
/* We still need to open file for operations like 'repquota' */
if ((fd = open(qfname, QIO_RO(h) ? O_RDONLY : O_RDWR)) < 0) {
errstr(_("Cannot open quotafile %s: %s\n"),
@@ -190,21 +189,30 @@ out_handle:
/*
* Create new quotafile of specified format on given filesystem
*/
-struct quota_handle *new_io(struct mntent *mnt, int type, int fmt)
+struct quota_handle *new_io(struct mount_entry *mnt, int type, int fmt)
{
char *qfname;
int fd;
struct quota_handle *h;
- const char *mnt_fsname;
char namebuf[PATH_MAX];
if (fmt == -1)
fmt = QF_VFSV0;
- else if (fmt == QF_RPC || fmt == QF_XFS || meta_qf_fstype(mnt->mnt_type)) {
+ else if (fmt == QF_RPC || fmt == QF_XFS) {
errstr(_("Creation of %s quota format is not supported.\n"),
fmt2name(fmt));
return NULL;
}
+ /*
+ * For filesystems which never have quotas in quota files or for
+ * filesystems which have quotas already stored in system files we
+ * refuse to create anything.
+ */
+ if (meta_qf_fstype(mnt->me_type) || mnt->me_qfmt[type] == QF_META) {
+ errstr(_("Quota on %s is stored in system files and must"
+ " be manipulated by fs tools.\n"), mnt->me_dir);
+ return NULL;
+ }
if (get_qf_name(mnt, type, fmt, 0, &qfname) < 0)
return NULL;
sstrncpy(namebuf, qfname, PATH_MAX);
@@ -215,14 +223,13 @@ struct quota_handle *new_io(struct mntent *mnt, int type, int fmt)
namebuf, strerror(errno));
return NULL;
}
- if (!(mnt_fsname = get_device_name(mnt->mnt_fsname)))
- goto out_fd;
h = smalloc(sizeof(struct quota_handle));
h->qh_fd = fd;
h->qh_io_flags = 0;
- sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev));
- free((char *)mnt_fsname);
+ sstrncpy(h->qh_quotadev, mnt->me_devname, sizeof(h->qh_quotadev));
+ sstrncpy(h->qh_fstype, mnt->me_type, MAX_FSTYPE_LEN);
+ sstrncpy(h->qh_dir, mnt->me_dir, PATH_MAX);
h->qh_type = type;
h->qh_fmt = fmt;
memset(&h->qh_info, 0, sizeof(h->qh_info));
@@ -274,3 +281,27 @@ struct dquot *get_empty_dquot(void)
dquot->dq_id = -1;
return dquot;
}
+
+/*
+ * Check whether values in current dquot can be stored on disk
+ */
+int check_dquot_range(struct dquot *dquot)
+{
+ struct util_dqinfo *info = &dquot->dq_h->qh_info;
+
+ if (dquot->dq_dqb.dqb_bhardlimit > info->dqi_max_b_limit ||
+ dquot->dq_dqb.dqb_bsoftlimit > info->dqi_max_b_limit ||
+ dquot->dq_dqb.dqb_ihardlimit > info->dqi_max_i_limit ||
+ dquot->dq_dqb.dqb_isoftlimit > info->dqi_max_i_limit) {
+ errstr(_("Trying to set quota limits out of range "
+ "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev);
+ return -1;
+ }
+ if (dquot->dq_dqb.dqb_curinodes > info->dqi_max_i_usage ||
+ dquot->dq_dqb.dqb_curspace > info->dqi_max_b_usage) {
+ errstr(_("Trying to set quota usage out of range "
+ "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev);
+ return -1;
+ }
+ return 0;
+}