diff options
Diffstat (limited to 'quotaio.c')
-rw-r--r-- | quotaio.c | 105 |
1 files changed, 68 insertions, 37 deletions
@@ -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 = "afile_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; +} |