| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| |
| #include "libxfs.h" |
| #include "bit.h" |
| #include "bmap.h" |
| #include "command.h" |
| #include "type.h" |
| #include "faddr.h" |
| #include "fprint.h" |
| #include "field.h" |
| #include "inode.h" |
| #include "io.h" |
| #include "init.h" |
| #include "output.h" |
| #include "dquot.h" |
| |
| static int dquot_f(int argc, char **argv); |
| static void dquot_help(void); |
| |
| static const cmdinfo_t dquot_cmd = { |
| "dquot", NULL, dquot_f, 1, 2, 1, N_("[-g|-p|-u] id"), |
| N_("set current address to a group, project or user quota block for given ID"), |
| dquot_help, |
| }; |
| |
| const field_t dqblk_hfld[] = { |
| { "", FLDT_DQBLK, OI(0), C1, 0, TYP_NONE }, |
| { NULL } |
| }; |
| |
| #define DDOFF(f) bitize(offsetof(xfs_dqblk_t, dd_ ## f)) |
| #define DDSZC(f) szcount(xfs_dqblk_t, dd_ ## f) |
| const field_t dqblk_flds[] = { |
| { "diskdq", FLDT_DISK_DQUOT, OI(DDOFF(diskdq)), C1, 0, TYP_NONE }, |
| { "fill", FLDT_CHARS, OI(DDOFF(fill)), CI(DDSZC(fill)), FLD_SKIPALL, |
| TYP_NONE }, |
| { "crc", FLDT_CRC, OI(DDOFF(crc)), C1, 0, TYP_NONE }, |
| { "lsn", FLDT_UINT64X, OI(DDOFF(lsn)), C1, 0, TYP_NONE }, |
| { "uuid", FLDT_UUID, OI(DDOFF(uuid)), C1, 0, TYP_NONE }, |
| { NULL } |
| }; |
| |
| static int |
| dquot_timestamp_count( |
| void *obj, |
| int startoff) |
| { |
| return xfs_sb_version_hasbigtime(&mp->m_sb) ? 0 : 1; |
| } |
| |
| static int |
| dquot_bigtimestamp_count( |
| void *obj, |
| int startoff) |
| { |
| return xfs_sb_version_hasbigtime(&mp->m_sb) ? 1 : 0; |
| } |
| |
| #define DOFF(f) bitize(offsetof(struct xfs_disk_dquot, d_ ## f)) |
| const field_t disk_dquot_flds[] = { |
| { "magic", FLDT_UINT16X, OI(DOFF(magic)), C1, 0, TYP_NONE }, |
| { "version", FLDT_UINT8X, OI(DOFF(version)), C1, 0, TYP_NONE }, |
| { "flags", FLDT_UINT8X, OI(DOFF(flags)), C1, 0, TYP_NONE }, |
| { "id", FLDT_DQID, OI(DOFF(id)), C1, 0, TYP_NONE }, |
| { "blk_hardlimit", FLDT_QCNT, OI(DOFF(blk_hardlimit)), C1, 0, |
| TYP_NONE }, |
| { "blk_softlimit", FLDT_QCNT, OI(DOFF(blk_softlimit)), C1, 0, |
| TYP_NONE }, |
| { "ino_hardlimit", FLDT_QCNT, OI(DOFF(ino_hardlimit)), C1, 0, |
| TYP_NONE }, |
| { "ino_softlimit", FLDT_QCNT, OI(DOFF(ino_softlimit)), C1, 0, |
| TYP_NONE }, |
| { "bcount", FLDT_QCNT, OI(DOFF(bcount)), C1, 0, TYP_NONE }, |
| { "icount", FLDT_QCNT, OI(DOFF(icount)), C1, 0, TYP_NONE }, |
| { "itimer", FLDT_INT32D, OI(DOFF(itimer)), dquot_timestamp_count, |
| FLD_COUNT, TYP_NONE }, |
| { "btimer", FLDT_INT32D, OI(DOFF(btimer)), dquot_timestamp_count, |
| FLD_COUNT, TYP_NONE }, |
| { "itimer", FLDT_BTQTIMER, OI(DOFF(itimer)), dquot_bigtimestamp_count, |
| FLD_COUNT, TYP_NONE }, |
| { "btimer", FLDT_BTQTIMER, OI(DOFF(btimer)), dquot_bigtimestamp_count, |
| FLD_COUNT, TYP_NONE }, |
| { "iwarns", FLDT_QWARNCNT, OI(DOFF(iwarns)), C1, 0, TYP_NONE }, |
| { "bwarns", FLDT_QWARNCNT, OI(DOFF(bwarns)), C1, 0, TYP_NONE }, |
| { "pad0", FLDT_UINT32X, OI(DOFF(pad0)), C1, FLD_SKIPALL, TYP_NONE }, |
| { "rtb_hardlimit", FLDT_QCNT, OI(DOFF(rtb_hardlimit)), C1, 0, |
| TYP_NONE }, |
| { "rtb_softlimit", FLDT_QCNT, OI(DOFF(rtb_softlimit)), C1, 0, |
| TYP_NONE }, |
| { "rtbcount", FLDT_QCNT, OI(DOFF(rtbcount)), C1, 0, TYP_NONE }, |
| { "rtbtimer", FLDT_INT32D, OI(DOFF(rtbtimer)), dquot_timestamp_count, |
| FLD_COUNT, TYP_NONE }, |
| { "rtbtimer", FLDT_BTQTIMER, OI(DOFF(rtbtimer)), |
| dquot_bigtimestamp_count, FLD_COUNT, TYP_NONE }, |
| { "rtbwarns", FLDT_QWARNCNT, OI(DOFF(rtbwarns)), C1, 0, TYP_NONE }, |
| { "pad", FLDT_UINT16X, OI(DOFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, |
| { NULL } |
| }; |
| |
| static void |
| dquot_help(void) |
| { |
| } |
| |
| static int |
| dquot_f( |
| int argc, |
| char **argv) |
| { |
| bmap_ext_t bm; |
| int c; |
| int dogrp; |
| int doprj; |
| xfs_dqid_t id; |
| xfs_ino_t ino; |
| int nex; |
| char *p; |
| int perblock; |
| xfs_fileoff_t qbno; |
| int qoff; |
| char *s; |
| |
| dogrp = doprj = optind = 0; |
| while ((c = getopt(argc, argv, "gpu")) != EOF) { |
| switch (c) { |
| case 'g': |
| dogrp = 1; |
| doprj = 0; |
| break; |
| case 'p': |
| doprj = 1; |
| dogrp = 0; |
| break; |
| case 'u': |
| dogrp = doprj = 0; |
| break; |
| default: |
| dbprintf(_("bad option for dquot command\n")); |
| return 0; |
| } |
| } |
| s = doprj ? _("project") : dogrp ? _("group") : _("user"); |
| if (optind != argc - 1) { |
| dbprintf(_("dquot command requires one %s id argument\n"), s); |
| return 0; |
| } |
| ino = mp->m_sb.sb_uquotino; |
| if (doprj) |
| ino = mp->m_sb.sb_pquotino; |
| else if (dogrp) |
| ino = mp->m_sb.sb_gquotino; |
| |
| if (ino == 0 || ino == NULLFSINO) { |
| dbprintf(_("no %s quota inode present\n"), s); |
| return 0; |
| } |
| id = (xfs_dqid_t)strtol(argv[optind], &p, 0); |
| if (*p != '\0') { |
| dbprintf(_("bad %s id for dquot %s\n"), s, argv[optind]); |
| return 0; |
| } |
| perblock = (int)(mp->m_sb.sb_blocksize / sizeof(xfs_dqblk_t)); |
| qbno = (xfs_fileoff_t)id / perblock; |
| qoff = (int)(id % perblock); |
| push_cur(); |
| set_cur_inode(ino); |
| nex = 1; |
| bmap(qbno, 1, XFS_DATA_FORK, &nex, &bm); |
| pop_cur(); |
| if (nex == 0) { |
| dbprintf(_("no %s quota data for id %d\n"), s, id); |
| return 0; |
| } |
| set_cur(&typtab[TYP_DQBLK], XFS_FSB_TO_DADDR(mp, bm.startblock), blkbb, |
| DB_RING_IGN, NULL); |
| iocur_top->dquot_buf = 1; |
| off_cur(qoff * (int)sizeof(xfs_dqblk_t), sizeof(xfs_dqblk_t)); |
| ring_add(); |
| return 0; |
| } |
| |
| void |
| xfs_dquot_set_crc( |
| struct xfs_buf *bp) |
| { |
| ASSERT((iocur_top->dquot_buf)); |
| ASSERT(iocur_top->bp == bp); |
| |
| xfs_update_cksum(iocur_top->data, sizeof(struct xfs_dqblk), |
| XFS_DQUOT_CRC_OFF); |
| } |
| |
| void |
| dquot_init(void) |
| { |
| add_command(&dquot_cmd); |
| } |