bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
a35cbba04d0a2823da98e693bd09a051addffdb2Timo Sirainen/* Only for reporting filesystem quota */
5e4c116a411967f1a012ac4f79732a724b5f6cc1Timo Sirainen# include <xfs/xqm.h> /* CentOS 4.x at least uses this */
39eefc53d06cf9790c6e3180a67b68e89eb71313Timo Sirainen/* Very old sys/quota.h doesn't define _LINUX_QUOTA_VERSION at all, which means
39eefc53d06cf9790c6e3180a67b68e89eb71313Timo Sirainen it supports only v1 quota. However, new sys/quota.h (glibc 2.25) removes
39eefc53d06cf9790c6e3180a67b68e89eb71313Timo Sirainen support for v1 entirely and again it doesn't define it. I guess we can just
39eefc53d06cf9790c6e3180a67b68e89eb71313Timo Sirainen assume v2 now, and if someone still wants v1 support they can add
39eefc53d06cf9790c6e3180a67b68e89eb71313Timo Sirainen -D_LINUX_QUOTA_VERSION=1 to CFLAGS. */
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitovstatic void handle_user_param(struct quota_root *_root, const char *param_value ATTR_UNUSED)
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov ((struct fs_quota_root *)_root)->group_disabled = TRUE;
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitovstatic void handle_group_param(struct quota_root *_root, const char *param_value ATTR_UNUSED)
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov ((struct fs_quota_root *)_root)->user_disabled = TRUE;
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitovstatic void handle_inode_param(struct quota_root *_root, const char *param_value ATTR_UNUSED)
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov ((struct fs_quota_root *)_root)->inode_per_mail = TRUE;
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitovstatic void handle_mount_param(struct quota_root *_root, const char *param_value)
d32f4c43ddfe51fd757c15fe1821287ab5b3caf5Martti Rannanjärvi struct fs_quota_root *root = (struct fs_quota_root *)_root;
d32f4c43ddfe51fd757c15fe1821287ab5b3caf5Martti Rannanjärvi root->storage_mount_path = i_strdup(param_value);
9b61a6db87c026656f8d2ae214e4486b98a069c0Timo Sirainenstatic int fs_quota_init(struct quota_root *_root, const char *args,
9b61a6db87c026656f8d2ae214e4486b98a069c0Timo Sirainen const char **error_r)
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov const struct quota_param_parser fs_params[] = {
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov {.param_name = "user", .param_handler = handle_user_param},
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov {.param_name = "group", .param_handler = handle_group_param},
d32f4c43ddfe51fd757c15fe1821287ab5b3caf5Martti Rannanjärvi {.param_name = "mount=", .param_handler = handle_mount_param},
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov {.param_name = "inode_per_mail", .param_handler = handle_inode_param},
efbb018262400ca272ae1d173b2db6f068516d71Sergey Kitov quota_param_hidden, quota_param_noenforcing, quota_param_ns,
fde14422caabc3c4ac4a6c5e3e5cf176cedd90a6Timo Sirainen if (quota_parse_parameters(_root, &args, error_r, fs_params, TRUE) < 0)
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstatic void fs_quota_mountpoint_free(struct fs_quota_mountpoint *mount)
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek i_close_fd_path(&mount->fd, mount->path);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstatic void fs_quota_deinit(struct quota_root *_root)
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)_root;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstatic struct fs_quota_mountpoint *fs_quota_mountpoint_get(const char *dir)
11ead0d848f1751c8274e3422fa48fc7d9aee2e9Timo Sirainen ret = mountpoint_get(dir, default_pool, &point);
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen if (strchr(mount->device_path, ':') == NULL) {
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen i_error("quota-fs: %s is not a valid NFS device path",
5670571cacaeb192fdc26ca2efd79734381796c0Timo Sirainen ((root)->root.backend.name == quota_backend_fs.name && \
5670571cacaeb192fdc26ca2efd79734381796c0Timo Sirainen strcmp((root)->storage_mount_path, (mount)->mount_path) == 0))
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenfs_quota_root_find_mountpoint(struct quota *quota,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen for (i = 0; i < count; i++) {
5670571cacaeb192fdc26ca2efd79734381796c0Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)roots[i];
079a251730d3ede9b1243fe3c2a15c1ff2c57094Timo Sirainenfs_quota_mount_init(struct fs_quota_root *root,
079a251730d3ede9b1243fe3c2a15c1ff2c57094Timo Sirainen struct fs_quota_mountpoint *mount, const char *dir)
10ae1846ac55dda424467e7230f0f77e3434fa5cTimo Sirainen /* using rquota for this mount */
3aaf560f83bd578d951b5026b5b0ffb58f86dccbTimo Sirainen mount->path = i_strconcat(mount->mount_path, "/quotas", NULL);
079a251730d3ede9b1243fe3c2a15c1ff2c57094Timo Sirainen i_debug("fs quota add mailbox dir = %s", dir);
079a251730d3ede9b1243fe3c2a15c1ff2c57094Timo Sirainen i_debug("fs quota block device = %s", mount->device_path);
079a251730d3ede9b1243fe3c2a15c1ff2c57094Timo Sirainen i_debug("fs quota mount point = %s", mount->mount_path);
079a251730d3ede9b1243fe3c2a15c1ff2c57094Timo Sirainen i_debug("fs quota mount type = %s", mount->type);
3aaf560f83bd578d951b5026b5b0ffb58f86dccbTimo Sirainen /* if there are more unused quota roots, copy this mount to them */
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen roots = array_get(&root->root.quota->roots, &count);
3aaf560f83bd578d951b5026b5b0ffb58f86dccbTimo Sirainen for (i = 0; i < count; i++) {
5670571cacaeb192fdc26ca2efd79734381796c0Timo Sirainen if (QUOTA_ROOT_MATCH(root, mount) && root->mount == NULL) {
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainenstatic void fs_quota_add_missing_mounts(struct quota *quota)
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen for (i = 0; i < count; i++) {
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)roots[i];
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen if (root->root.backend.name != quota_backend_fs.name ||
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen root->storage_mount_path == NULL || root->mount != NULL)
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen mount = fs_quota_mountpoint_get(root->storage_mount_path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void fs_quota_namespace_added(struct quota *quota,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (!mailbox_list_get_root_path(ns->list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
b19feb85569a6ad96e60d8246723561331213b8aTimo Sirainen root = fs_quota_root_find_mountpoint(quota, mount);
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen /* we would actually want to do this only once after all quota roots
ceb88add1fc9f7f25e1ce75f7dae947bb63ae0a0Timo Sirainen are created, but there's no way to do this right now */
a35cbba04d0a2823da98e693bd09a051addffdb2Timo Sirainenstatic const char *const *
e4cbaae481f5e980dca4df1a819d8df127456e4dTimo Sirainenfs_quota_root_get_resources(struct quota_root *_root)
e4cbaae481f5e980dca4df1a819d8df127456e4dTimo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)_root;
e4cbaae481f5e980dca4df1a819d8df127456e4dTimo Sirainen static const char *resources_kb_messages[] = {
e4cbaae481f5e980dca4df1a819d8df127456e4dTimo Sirainen return root->inode_per_mail ? resources_kb_messages : resources_kb;
738bdc36e50f5acb829e8fbeed9b77afee0c6de0Timo Sirainen#if defined(FS_QUOTA_LINUX) || defined(FS_QUOTA_BSDAIX) || \
738bdc36e50f5acb829e8fbeed9b77afee0c6de0Timo Sirainen defined(FS_QUOTA_NETBSD) || defined(HAVE_RQUOTA)
738bdc36e50f5acb829e8fbeed9b77afee0c6de0Timo Sirainenstatic void fs_quota_root_disable(struct fs_quota_root *root, bool group)
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *count_value_r, uint64_t *count_limit_r)
f5f9099ac93110513bb18f366d1536d174dcfad8Timo Sirainen /* use soft limits if they exist, fallback to hard limits */
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen /* convert the results from blocks to bytes */
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)rq->rq_bsoftlimit *
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)rq->rq_bhardlimit *
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi uint64_t *count_value_r, uint64_t *count_limit_r,
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen struct fs_quota_mountpoint *mount = root->mount;
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen host = t_strdup_until(mount->device_path, path);
f9b62248553c15ed6e3297a23390f79bdc03d416Timo Sirainen /* For NFSv4, we send the filesystem path without initial /. Server
f9b62248553c15ed6e3297a23390f79bdc03d416Timo Sirainen prepends proper NFS pseudoroot automatically and uses this for
f9b62248553c15ed6e3297a23390f79bdc03d416Timo Sirainen detection of NFSv4 mounts. */
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen /* clnt_create() polls for a while to establish a connection */
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen cl = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp");
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "could not contact RPC service on %s", host);
21aa3c764494fc308e8fdb1a9b4f9df3f260e4f8Timo Sirainen /* Establish some RPC credentials */
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen /* make the rquota call on the remote host */
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS;
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen call_status = clnt_call(cl, RQUOTAPROC_GETQUOTA,
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen (xdrproc_t)xdr_getquota_rslt, (char *)&result,
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen /* the result has been deserialized, let the client go */
9e96947aa6185341cbdd1140cb216fab3270ccbaTimo Sirainen const char *rpc_error_msg = clnt_sperrno(call_status);
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "remote rquota call failed: %s",
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen rquota_get_result(&result.getquota_rslt_u.gqr_rquota,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi i_debug("quota-fs: uid=%s, bytes=%"PRIu64"/%"PRIu64" "
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi *error_r = "permission denied to rquota service";
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "unrecognized status code (%d) from rquota service",
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainendo_rquota_group(struct fs_quota_root *root ATTR_UNUSED,
6dddf1d27c0f72756c790735d1dedde6591cc15dTimo Sirainen#if defined(EXT_RQUOTAVERS) && defined(GRPQUOTA)
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen struct fs_quota_mountpoint *mount = root->mount;
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen host = t_strdup_until(mount->device_path, path);
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen /* clnt_create() polls for a while to establish a connection */
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen cl = clnt_create(host, RQUOTAPROG, EXT_RQUOTAVERS, "udp");
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "could not contact RPC service on %s (group)", host);
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen /* Establish some RPC credentials */
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen /* make the rquota call on the remote host */
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS;
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen call_status = clnt_call(cl, RQUOTAPROC_GETQUOTA,
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen (xdrproc_t)xdr_ext_getquota_args, (char *)&args,
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen (xdrproc_t)xdr_getquota_rslt, (char *)&result,
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen /* the result has been deserialized, let the client go */
4c7caf83adc56d54e2ecec0a803f5ca9b6d0498dTimo Sirainen const char *rpc_error_msg = clnt_sperrno(call_status);
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "remote ext rquota call failed: %s", rpc_error_msg);
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen rquota_get_result(&result.getquota_rslt_u.gqr_rquota,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi i_debug("quota-fs: gid=%s, bytes=%"PRIu64"/%"PRIu64" "
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi *error_r = "permission denied to ext rquota service";
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "unrecognized status code (%d) from ext rquota service",
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi *error_r = "rquota not compiled with group support";
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainenfs_quota_get_linux(struct fs_quota_root *root, bool group,
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi uint64_t *count_value_r, uint64_t *count_limit_r,
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "errno=%d, quotactl(Q_XGETQUOTA, %s) failed: %m",
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen /* values always returned in 512 byte blocks */
15c365ef8fadf433160deb3f59442616ed0569dcTimo Sirainen *bytes_limit_r = xdqblk.d_blk_softlimit * 512ULL;
15c365ef8fadf433160deb3f59442616ed0569dcTimo Sirainen *bytes_limit_r = xdqblk.d_blk_hardlimit * 512ULL;
a2871d937a75288bcd7177b2680d4e5096a7f3cbTimo Sirainen /* ext2, ext3 */
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "quotactl(Q_GETQUOTA, %s) failed: %m",
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi "Dovecot was compiled with Linux quota "
2e0e52f27469bf4eba8d7e88f1716f0a19824ba5Timo Sirainen "v%d support, try changing it "
64e33505784bb6f6ab83ce062d82870868751eb5Timo Sirainen "(CPPFLAGS=-D_LINUX_QUOTA_VERSION=%d configure)",
15c365ef8fadf433160deb3f59442616ed0569dcTimo Sirainen *bytes_value_r = dqblk.dqb_curblocks * 1024ULL;
15c365ef8fadf433160deb3f59442616ed0569dcTimo Sirainen *bytes_limit_r = dqblk.dqb_bsoftlimit * 1024ULL;
15c365ef8fadf433160deb3f59442616ed0569dcTimo Sirainen *bytes_limit_r = dqblk.dqb_bhardlimit * 1024ULL;
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainenfs_quota_get_bsdaix(struct fs_quota_root *root, bool group,
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi uint64_t *count_value_r, uint64_t *count_limit_r,
4bbac9612c0b16bd4c7f03326a7a2cdc163014d8Timo Sirainen if (quotactl(root->mount->mount_path, QCMD(Q_GETQUOTA, type),
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "quotactl(Q_GETQUOTA, %s) failed: %m",
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_value_r = (uint64_t)dqblk.dqb_curblocks * DEV_BSIZE;
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)dqblk.dqb_bsoftlimit * DEV_BSIZE;
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)dqblk.dqb_bhardlimit * DEV_BSIZE;
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainenfs_quota_get_netbsd(struct fs_quota_root *root, bool group,
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi uint64_t *count_value_r, uint64_t *count_limit_r,
5f83be0c55c71e15b62cbc275f8dd4b3e80e18b6Timo Sirainen if ((qh = quota_open(root->mount->mount_path)) == NULL) {
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi *error_r = t_strdup_printf("cannot open quota for %s: %m",
26ada766cfff6ebfb91d100936118cf8aa51e3aeTimo Sirainen qk.qk_idtype = group ? QUOTA_IDTYPE_GROUP : QUOTA_IDTYPE_USER;
4adefdb40c7ffcac3d8f8279cdf52d9f72d39636Teemu Huovila for (int i = 0; i < 2; i++) {
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen qk.qk_objtype = i == 0 ? QUOTA_OBJTYPE_BLOCKS : QUOTA_OBJTYPE_FILES;
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "quotactl(Q_GETQUOTA, %s) failed: %m",
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen if (i == 0) {
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi uint64_t *count_value_r, uint64_t *count_limit_r,
45031ba153608eb33af22ee0d242c3e5e426486dTimo Sirainen if (quotactl(Q_GETQUOTA, root->mount->device_path,
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "quotactl(Q_GETQUOTA, %s) failed: %m",
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_value_r = (uint64_t)dqblk.dqb_curblocks *
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)dqblk.dqb_bsoftlimit *
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)dqblk.dqb_bhardlimit *
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainenfs_quota_get_solaris(struct fs_quota_root *root,
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi uint64_t *count_value_r, uint64_t *count_limit_r,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen if (ioctl(root->mount->fd, Q_QUOTACTL, &ctl) < 0) {
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi "ioctl(%s, Q_QUOTACTL) failed: %m",
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_value_r = (uint64_t)dqblk.dqb_curblocks * DEV_BSIZE;
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)dqblk.dqb_bsoftlimit * DEV_BSIZE;
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen *bytes_limit_r = (uint64_t)dqblk.dqb_bhardlimit * DEV_BSIZE;
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainenfs_quota_get_resources(struct fs_quota_root *root, bool group,
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen uint64_t *bytes_value_r, uint64_t *bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi uint64_t *count_value_r, uint64_t *count_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi return fs_quota_get_linux(root, group, bytes_value_r, bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi return fs_quota_get_netbsd(root, group, bytes_value_r, bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi return fs_quota_get_bsdaix(root, group, bytes_value_r, bytes_limit_r,
4bbac9612c0b16bd4c7f03326a7a2cdc163014d8Timo Sirainen /* not supported */
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi return fs_quota_get_hpux(root, bytes_value_r, bytes_limit_r,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi return fs_quota_get_solaris(root, bytes_value_r, bytes_limit_r,
6d6bbe8787354bbb69d0c03187adfe0f497d70b8Timo Sirainenstatic bool fs_quota_match_box(struct quota_root *_root, struct mailbox *box)
6d6bbe8787354bbb69d0c03187adfe0f497d70b8Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)_root;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
6d6bbe8787354bbb69d0c03187adfe0f497d70b8Timo Sirainen if (stat(root->storage_mount_path, &rst) < 0) {
73cdeeae4ccae9930973dfb6a5b4835c79bdba49Sergey Kitov i_debug("box=%s mount=%s match=%s", mailbox_path,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk root->storage_mount_path, match ? "yes" : "no");
29fe652c01b24298ee9e5825a103279106f0e263Timo Sirainenfs_quota_get_resource(struct quota_root *_root, const char *name,
29fe652c01b24298ee9e5825a103279106f0e263Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)_root;
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi "Mount point unknown for path %s",
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi if (strcasecmp(name, QUOTA_NAME_STORAGE_BYTES) != 0 &&
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi strcasecmp(name, QUOTA_NAME_MESSAGES) != 0) {
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi *error_r = QUOTA_UNKNOWN_RESOURCE_ERROR_STRING;
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi return QUOTA_GET_RESULT_UNKNOWN_RESOURCE;
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi do_rquota_user(root, &bytes_value, &bytes_limit,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi ret = do_rquota_group(root, &bytes_value,
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi ret = fs_quota_get_resources(root, FALSE, &bytes_value,
3851ad9fcb25635f02b46d44586742ef1081876bTimo Sirainen /* fallback to group quota */
9a603e8651212925bc15ba89abdbe9ea92a0d903Martti Rannanjärvi ret = fs_quota_get_resources(root, TRUE, &bytes_value,
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi else if (ret == 0)
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen if (strcasecmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen if (_root->bytes_limit != (int64_t)bytes_limit ||
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen /* update limit */
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen /* limits have changed, so we'll need to recalculate
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen relative quota rules */
47c4991dc627010c92674cb3af6bc9d5089720e7Timo Sirainen quota_root_recalculate_relative_rules(_root->set, bytes_limit, count_limit);
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenfs_quota_update(struct quota_root *root ATTR_UNUSED,
7b3b617e946d5b32078baa821f5fc05f775e1dfeMartti Rannanjärvi struct quota_transaction_context *ctx ATTR_UNUSED,
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .namespace_added = fs_quota_namespace_added,