2 * Implementation of XFS quota manager.
3 * Copyright (c) 2001 Silicon Graphics, Inc.
21 #include "dqblk_xfs.h"
23 #define XFS_USRQUOTA(h) ((h)->qh_type == USRQUOTA && \
24 (h)->qh_info.u.xfs_mdqi.qs_flags & XFS_QUOTA_UDQ_ACCT)
25 #define XFS_GRPQUOTA(h) ((h)->qh_type == GRPQUOTA && \
26 (h)->qh_info.u.xfs_mdqi.qs_flags & XFS_QUOTA_GDQ_ACCT)
28 static int xfs_init_io(struct quota_handle *h);
29 static int xfs_write_info(struct quota_handle *h);
30 static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id);
31 static int xfs_commit_dquot(struct dquot *dquot, int flags);
32 static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot *dquot, char *dqname));
33 static int xfs_report(struct quota_handle *h, int verbose);
35 struct quotafile_ops quotafile_ops_xfs = {
37 write_info: xfs_write_info,
38 read_dquot: xfs_read_dquot,
39 commit_dquot: xfs_commit_dquot,
40 scan_dquots: xfs_scan_dquots,
45 * Convert XFS kernel quota format to utility format
47 static inline void xfs_kern2utildqblk(struct util_dqblk *u, struct xfs_kern_dqblk * k)
49 u->dqb_ihardlimit = k->d_ino_hardlimit;
50 u->dqb_isoftlimit = k->d_ino_softlimit;
51 u->dqb_bhardlimit = k->d_blk_hardlimit >> 1;
52 u->dqb_bsoftlimit = k->d_blk_softlimit >> 1;
53 u->dqb_curinodes = k->d_icount;
54 u->dqb_curspace = ((qsize_t)k->d_bcount) << 9;
55 u->dqb_itime = k->d_itimer;
56 u->dqb_btime = k->d_btimer;
60 * Convert utility quota format to XFS kernel format
62 static inline void xfs_util2kerndqblk(struct xfs_kern_dqblk *k, struct util_dqblk *u)
64 memset(k, 0, sizeof(struct xfs_kern_dqblk));
65 k->d_ino_hardlimit = u->dqb_ihardlimit;
66 k->d_ino_softlimit = u->dqb_isoftlimit;
67 k->d_blk_hardlimit = u->dqb_bhardlimit << 1;
68 k->d_blk_softlimit = u->dqb_bsoftlimit << 1;
69 k->d_icount = u->dqb_curinodes;
70 k->d_bcount = u->dqb_curspace >> 9;
71 k->d_itimer = u->dqb_itime;
72 k->d_btimer = u->dqb_btime;
76 * Initialize quota information
78 static int xfs_init_io(struct quota_handle *h)
80 struct xfs_mem_dqinfo info;
83 qcmd = QCMD(Q_XFS_GETQSTAT, 0);
84 memset(&info, 0, sizeof(struct xfs_mem_dqinfo));
85 if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&info) < 0)
87 h->qh_info.dqi_bgrace = info.qs_btimelimit;
88 h->qh_info.dqi_igrace = info.qs_itimelimit;
89 h->qh_info.u.xfs_mdqi = info;
94 * Write information (grace times)
96 static int xfs_write_info(struct quota_handle *h)
98 struct xfs_kern_dqblk xdqblk;
101 if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h))
104 memset(&xdqblk, 0, sizeof(struct xfs_kern_dqblk));
106 xdqblk.d_btimer = h->qh_info.dqi_bgrace;
107 xdqblk.d_itimer = h->qh_info.dqi_igrace;
108 xdqblk.d_fieldmask |= FS_DQ_TIMER_MASK;
109 qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type);
110 if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&xdqblk) < 0)
116 * Read a dqblk struct from the quota manager
118 static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id)
120 struct dquot *dquot = get_empty_dquot();
121 struct xfs_kern_dqblk xdqblk;
127 if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h))
130 qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type);
131 if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) {
135 xfs_kern2utildqblk(&dquot->dq_dqb, &xdqblk);
141 * Write a dqblk struct to the XFS quota manager
143 static int xfs_commit_dquot(struct dquot *dquot, int flags)
145 struct quota_handle *h = dquot->dq_h;
146 struct xfs_kern_dqblk xdqblk;
147 qid_t id = dquot->dq_id;
150 if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h))
153 xfs_util2kerndqblk(&xdqblk, &dquot->dq_dqb);
154 xdqblk.d_fieldmask |= FS_DQ_LIMIT_MASK;
155 qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type);
156 if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) {
166 * xfs_scan_dquots helper - processes a single dquot
168 static int xfs_scan_dquot(struct quota_handle *h,
169 struct xfs_kern_dqblk *d,
170 char *name, struct dquot *dq,
171 int (*process_dquot) (struct dquot *dquot, char *dqname))
173 int qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type);
175 memset(d, 0, sizeof(struct xfs_kern_dqblk));
177 if (quotactl(qcmd, h->qh_quotadev, dq->dq_id, (void *)d) < 0) {
180 if (d->d_blk_hardlimit == 0 &&
181 d->d_blk_softlimit == 0 &&
182 d->d_ino_hardlimit == 0 &&
183 d->d_ino_softlimit == 0 && d->d_bcount == 0 && d->d_icount == 0) return 0;
184 xfs_kern2utildqblk(&dq->dq_dqb, d);
185 return process_dquot(dq, name);
189 * Scan all known dquots and call callback on each
191 static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot *dquot, char *dqname))
194 struct xfs_kern_dqblk d;
197 if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h))
200 dq = get_empty_dquot();
202 if (h->qh_type == USRQUOTA) {
206 while ((usr = getpwent()) != NULL) {
207 dq->dq_id = usr->pw_uid;
208 rd = xfs_scan_dquot(h, &d, usr->pw_name, dq, process_dquot);
214 else { /* GRPQUOTA */
218 while ((grp = getgrent()) != NULL) {
219 dq->dq_id = grp->gr_gid;
220 rd = xfs_scan_dquot(h, &d, grp->gr_name, dq, process_dquot);
232 * Report information about XFS quota on given filesystem
234 static int xfs_report(struct quota_handle *h, int verbose)
237 struct xfs_mem_dqinfo *info = &h->qh_info.u.xfs_mdqi;
242 /* quotaon/off flags */
243 printf(_("*** Status for %s quotas on device %s\n"), type2name(h->qh_type), h->qh_quotadev);
245 #define XQM_ON(flag) ((info->qs_flags & (flag)) ? _("ON") : _("OFF"))
246 if (h->qh_type == USRQUOTA) {
247 printf(_("Accounting: %s; Enforcement: %s\n"),
248 XQM_ON(XFS_QUOTA_UDQ_ACCT), XQM_ON(XFS_QUOTA_UDQ_ENFD));
250 else { /* qh_type == USRQUOTA */
251 printf(_("Accounting: %s; Enforcement: %s\n"),
252 XQM_ON(XFS_QUOTA_GDQ_ACCT), XQM_ON(XFS_QUOTA_GDQ_ENFD));
257 * If this is the root file system, it is possible that quotas are
258 * on ondisk, but not incore. Those flags will be in the HI 8 bits.
260 #define XQM_ONDISK(flag) ((sbflags & (flag)) ? _("ON") : _("OFF"))
261 if ((sbflags = (info->qs_flags & 0xff00) >> 8) != 0) {
262 if (h->qh_type == USRQUOTA) {
263 printf(_("Accounting [ondisk]: %s; Enforcement [ondisk]: %s\n"),
264 XQM_ONDISK(XFS_QUOTA_UDQ_ACCT), XQM_ONDISK(XFS_QUOTA_UDQ_ENFD));
266 else { /* qh_type == USRQUOTA */
267 printf(_("Accounting [ondisk]: %s; Enforcement [ondisk]: %s\n"),
268 XQM_ONDISK(XFS_QUOTA_GDQ_ACCT), XQM_ONDISK(XFS_QUOTA_GDQ_ENFD));
273 /* user and group quota file status information */
274 if (h->qh_type == USRQUOTA) {
275 if (info->qs_uquota.qfs_ino == -1 || info->qs_uquota.qfs_ino == 0)
276 printf(_("Inode: none\n"));
278 printf(_("Inode: #%llu (%llu blocks, %u extents)\n"),
279 (unsigned long long)info->qs_uquota.qfs_ino,
280 (unsigned long long)info->qs_uquota.qfs_nblks,
281 info->qs_uquota.qfs_nextents);
283 else { /* qh_type == GRPQUOTA */
284 if (info->qs_gquota.qfs_ino == -1)
285 printf(_("Inode: none\n"));
287 printf(_("Inode: #%llu (%llu blocks, %u extents)\n"),
288 (unsigned long long)info->qs_gquota.qfs_ino,
289 (unsigned long long)info->qs_gquota.qfs_nblks,
290 info->qs_gquota.qfs_nextents);