]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/quot.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2005 Silicon Graphics, Inc.
14 #include "libfrog/logging.h"
15 #include "libfrog/fsgeom.h"
16 #include "libfrog/bulkstat.h"
29 static uint64_t sizes
[TSIZE
];
30 static uint64_t overflow
;
34 static du_t du
[3][NDU
];
35 static du_t
*duhash
[3][DUHASH
];
36 static int ndu
[3]; /* #usr/grp/prj */
41 static cmdinfo_t quot_cmd
;
48 " display a summary of filesystem ownership\n"
50 " -a -- summarise for all local XFS filesystem mount points\n"
51 " -c -- display three columns giving file size in kilobytes, number of files\n"
52 " of that size, and cumulative total of kilobytes in that size or\n"
53 " smaller file. The last row is used as an overflow bucket and is the\n"
54 " total of all files greater than 500 kilobytes.\n"
55 " -v -- display three columns containing the number of kilobytes not\n"
56 " accessed in the last 30, 60, and 90 days.\n"
57 " -g -- display group summary\n"
58 " -p -- display project summary\n"
59 " -u -- display user summary\n"
60 " -b -- display number of blocks used\n"
61 " -i -- display number of inodes used\n"
62 " -r -- display number of realtime blocks used\n"
63 " -n -- skip identifier-to-name translations, just report IDs\n"
64 " -N -- suppress the initial header\n"
65 " -f -- send output to a file\n"
66 " The (optional) user/group/project can be specified either by name or by\n"
67 " number (i.e. uid/gid/projid).\n"
73 struct xfs_bulkstat
*p
,
81 if ((p
->bs_mode
& S_IFMT
) == 0)
83 size
= howmany((p
->bs_blocks
* p
->bs_blksize
), 0x400ULL
);
85 if (flags
& HISTOGRAM_FLAG
) {
86 if (!(S_ISDIR(p
->bs_mode
) || S_ISREG(p
->bs_mode
)))
95 for (i
= 0; i
< 3; i
++) {
96 id
= (i
== 0) ? p
->bs_uid
: ((i
== 1) ?
97 p
->bs_gid
: p
->bs_projectid
);
98 hp
= &duhash
[i
][id
% DUHASH
];
99 for (dp
= *hp
; dp
; dp
= dp
->next
)
105 dp
= &du
[i
][(ndu
[i
]++)];
117 if (now
- p
->bs_atime
> 30 * (60*60*24))
118 dp
->blocks30
+= size
;
119 if (now
- p
->bs_atime
> 60 * (60*60*24))
120 dp
->blocks60
+= size
;
121 if (now
- p
->bs_atime
> 90 * (60*60*24))
122 dp
->blocks90
+= size
;
132 struct xfs_fd fsxfd
= XFS_FD_INIT_EMPTY
;
133 struct xfs_bulkstat_req
*breq
;
138 * Initialize tables between checks; because of the qsort
139 * in report() the hash tables must be rebuilt each time.
141 for (sts
= 0; sts
< TSIZE
; sts
++)
144 for (i
= 0; i
< 3; i
++)
145 for (dp
= duhash
[i
]; dp
< &duhash
[i
][DUHASH
]; dp
++)
147 ndu
[0] = ndu
[1] = ndu
[2] = 0;
149 ret
= -xfd_open(&fsxfd
, fsdir
, O_RDONLY
);
151 xfrog_perror(ret
, fsdir
);
155 breq
= xfrog_bulkstat_alloc_req(NBSTAT
, 0);
162 while ((sts
= xfrog_bulkstat(&fsxfd
, breq
)) == 0) {
163 if (breq
->hdr
.ocount
== 0)
165 for (i
= 0; i
< breq
->hdr
.ocount
; i
++)
166 quot_bulkstat_add(&breq
->bulkstat
[i
], flags
);
169 xfrog_perror(sts
, "XFS_IOC_FSBULKSTAT");
179 if (p1
->blocks
> p2
->blocks
)
181 if (p1
->blocks
< p2
->blocks
)
185 else if (p1
->id
< p2
->id
)
190 typedef char *(*idtoname_t
)(uint32_t);
193 quot_report_mount_any_type(
205 fprintf(fp
, _("%s (%s) %s:\n"),
206 mount
->fs_name
, mount
->fs_dir
, type_to_string(type
));
207 qsort(dp
, count
, sizeof(dp
[0]),
208 (int (*)(const void *, const void *))qcompare
);
209 for (; dp
< &dp
[count
]; dp
++) {
212 fprintf(fp
, "%8llu ", (unsigned long long) dp
->blocks
);
213 if (form
& XFS_INODE_QUOTA
)
214 fprintf(fp
, "%8llu ",
215 (unsigned long long) dp
->nfiles
);
216 if (!(flags
& NO_LOOKUP_FLAG
) &&
217 ((cp
= (names
)(dp
->id
)) != NULL
))
218 fprintf(fp
, "%-8.8s", cp
);
220 fprintf(fp
, "#%-7d", dp
->id
);
221 if (flags
& VERBOSE_FLAG
)
222 fprintf(fp
, " %8llu %8llu %8llu",
223 (unsigned long long) dp
->blocks30
,
224 (unsigned long long) dp
->blocks60
,
225 (unsigned long long) dp
->blocks90
);
239 case XFS_GROUP_QUOTA
:
240 quot_report_mount_any_type(fp
, du
[1], ndu
[1], gid_to_name
,
241 form
, type
, mount
, flags
);
244 quot_report_mount_any_type(fp
, du
[2], ndu
[2], prid_to_name
,
245 form
, type
, mount
, flags
);
248 quot_report_mount_any_type(fp
, du
[0], ndu
[0], uid_to_name
,
249 form
, type
, mount
, flags
);
265 fs_cursor_initialise(dir
, FS_MOUNT_POINT
, &cursor
);
266 while ((mount
= fs_cursor_next_entry(&cursor
))) {
267 quot_bulkstat_mount(mount
->fs_dir
, flags
);
268 quot_report_mount(fp
, form
, type
, mount
, flags
);
273 quot_histogram_mount(
281 fprintf(fp
, _("%s (%s):\n"), mount
->fs_name
, mount
->fs_dir
);
283 for (i
= 0; i
< TSIZE
- 1; i
++)
286 fprintf(fp
, _("%d\t%llu\t%llu\n"), i
,
287 (unsigned long long) sizes
[i
],
288 (unsigned long long) t
);
290 fprintf(fp
, _("%d\t%llu\t%llu\n"), TSIZE
- 1,
291 (unsigned long long) sizes
[TSIZE
- 1],
292 (unsigned long long) (overflow
+ t
));
304 fs_cursor_initialise(dir
, FS_MOUNT_POINT
, &cursor
);
305 while ((mount
= fs_cursor_next_entry(&cursor
))) {
306 quot_bulkstat_mount(mount
->fs_dir
, flags
);
307 quot_histogram_mount(fp
, mount
, flags
);
319 if (flags
& HISTOGRAM_FLAG
)
320 quot_histogram(fp
, dir
, flags
);
322 quot_report(fp
, form
, type
, dir
, flags
);
332 int c
, flags
= 0, type
= 0, form
= 0;
334 while ((c
= getopt(argc
, argv
, "abcf:ghinpruv")) != EOF
) {
340 form
|= XFS_BLOCK_QUOTA
;
343 form
|= XFS_INODE_QUOTA
;
346 form
|= XFS_RTBLOCK_QUOTA
;
349 type
|= XFS_GROUP_QUOTA
;
352 type
|= XFS_PROJ_QUOTA
;
355 type
|= XFS_USER_QUOTA
;
358 flags
|= ALL_MOUNTS_FLAG
;
361 flags
|= HISTOGRAM_FLAG
;
364 flags
|= NO_LOOKUP_FLAG
;
367 flags
|= VERBOSE_FLAG
;
370 return command_usage("_cmd
);
375 form
= XFS_BLOCK_QUOTA
;
378 type
= XFS_USER_QUOTA
;
379 } else if (type
!= XFS_GROUP_QUOTA
&&
380 type
!= XFS_PROJ_QUOTA
&&
381 type
!= XFS_USER_QUOTA
) {
382 return command_usage("_cmd
);
385 if ((fp
= fopen_write_secure(fname
)) == NULL
)
388 if (argc
== optind
) {
389 if (flags
& ALL_MOUNTS_FLAG
)
390 quot_any_type(fp
, form
, type
, NULL
, flags
);
391 else if (fs_path
->fs_flags
& FS_MOUNT_POINT
)
392 quot_any_type(fp
, form
, type
, fs_path
->fs_dir
, flags
);
393 } else while (argc
> optind
) {
394 quot_any_type(fp
, form
, type
, argv
[optind
++], flags
);
405 quot_cmd
.name
= "quot";
406 quot_cmd
.cfunc
= quot_f
;
408 quot_cmd
.argmax
= -1;
409 quot_cmd
.args
= _("[-bir] [-g|-p|-u] [-acv] [-f file]");
410 quot_cmd
.oneline
= _("summarize filesystem ownership");
411 quot_cmd
.help
= quot_help
;
414 add_command("_cmd
);