quota-fs.c revision 0dffa25d211be541ee3c953b23566a1a990789df
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainen/* Only for reporting filesystem quota */
5e9a39da0a9aba60b50e2c1d401f102703431b73Timo Sirainen# include <xfs/xqm.h> /* CentOS 4.x at least uses this */
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainen/* Older sys/quota.h doesn't define _LINUX_QUOTA_VERSION at all, which means
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainen it supports only v1 quota */
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainenstatic int fs_quota_init(struct quota_root *_root, const char *args,
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainen const char **error_r)
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)_root;
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainen const char *const *tmp;
5e9a39da0a9aba60b50e2c1d401f102703431b73Timo Sirainen for (tmp = t_strsplit(args, ":"); *tmp != NULL; tmp++) {
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainen root->storage_mount_path = i_strdup(*tmp + 6);
4dfaf598d6f2539caaab7ff0dd51d24a20928db8Timo Sirainen *error_r = t_strdup_printf("Invalid parameter: %s", *tmp);
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainenstatic void fs_quota_mountpoint_free(struct fs_quota_mountpoint *mount)
5e9a39da0a9aba60b50e2c1d401f102703431b73Timo Sirainenstatic void fs_quota_deinit(struct quota_root *_root)
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)_root;
37c4359391810bc5bab0d2c72d7d25d8335b2858Timo Sirainenstatic struct fs_quota_mountpoint *fs_quota_mountpoint_get(const char *dir)
761c440316cc003817b3375b627287eceb6f6dceTimo Sirainen ret = mountpoint_get(dir, default_pool, &point);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (strchr(mount->device_path, ':') == NULL) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen i_error("quota-fs: %s is not a valid NFS device path",
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen ((root)->root.backend.name == quota_backend_fs.name && \
f3ef6fdc790caf67352a07829bedb117bc56fb78Timo Sirainen strcmp((root)->storage_mount_path, (mount)->mount_path) == 0))
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenfs_quota_root_find_mountpoint(struct quota *quota,
37c4359391810bc5bab0d2c72d7d25d8335b2858Timo Sirainen unsigned int i, count;
37c4359391810bc5bab0d2c72d7d25d8335b2858Timo Sirainen for (i = 0; i < count; i++) {
37c4359391810bc5bab0d2c72d7d25d8335b2858Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)roots[i];
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainenfs_quota_mount_init(struct fs_quota_root *root,
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainen struct fs_quota_mountpoint *mount, const char *dir)
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainen unsigned int i, count;
93e742e81653922361ce61f38319bd53e9bcad91Timo Sirainen /* using rquota for this mount */
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainen mount->path = i_strconcat(mount->mount_path, "/quotas", NULL);
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainen i_debug("fs quota add mailbox dir = %s", dir);
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainen i_debug("fs quota block device = %s", mount->device_path);
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainen i_debug("fs quota mount point = %s", mount->mount_path);
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainen i_debug("fs quota mount type = %s", mount->type);
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainen /* if there are more unused quota roots, copy this mount to them */
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainen roots = array_get(&root->root.quota->roots, &count);
37c4359391810bc5bab0d2c72d7d25d8335b2858Timo Sirainen for (i = 0; i < count; i++) {
49dc101839b5f37a1a3c000421796f162e0017d9Timo Sirainen if (QUOTA_ROOT_MATCH(root, mount) && root->mount == NULL) {
a497e8b94b55e035a1ebd28cf1368a8869ddaa62Timo Sirainenstatic void fs_quota_add_missing_mounts(struct quota *quota)
37c4359391810bc5bab0d2c72d7d25d8335b2858Timo Sirainen unsigned int i, count;
49dc101839b5f37a1a3c000421796f162e0017d9Timo Sirainen for (i = 0; i < count; i++) {
37c4359391810bc5bab0d2c72d7d25d8335b2858Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)roots[i];
7ca397e910d2b267bcfaecbcdf9b23523c639776Timo Sirainen if (root->root.backend.name != quota_backend_fs.name ||
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainen root->storage_mount_path == NULL || root->mount != NULL)
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainen mount = fs_quota_mountpoint_get(root->storage_mount_path);
5cdd1691e5185ecfe424f5de7b6f697813b88ba2Timo Sirainenstatic void fs_quota_namespace_added(struct quota *quota,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen const char *dir;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen if (!mailbox_list_get_root_path(ns->list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
4a3e6e01ea368e9a90dc32abc40aea46fe93f926Timo Sirainen root = fs_quota_root_find_mountpoint(quota, mount);
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen /* we would actually want to do this only once after all quota roots
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen are created, but there's no way to do this right now */
0622f54c063d2dca88f6b95daa6822cb386068caTimo Sirainenstatic const char *const *
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenfs_quota_root_get_resources(struct quota_root *_root)
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen struct fs_quota_root *root = (struct fs_quota_root *)_root;
static const char *resources_kb[] = {
static const char *resources_kb_messages[] = {
if (group)
#ifdef HAVE_RQUOTA
const char *host;
char *path;
path++;
path++;
host);
timeout);
case Q_OK: {
(unsigned long long)*bytes_value_r,
(unsigned long long)*bytes_limit_r,
(unsigned long long)*count_value_r,
(unsigned long long)*count_limit_r);
case Q_NOQUOTA:
case Q_EPERM:
const char *host;
char *path;
path++;
host);
timeout);
case Q_OK: {
(unsigned long long)*bytes_value_r,
(unsigned long long)*bytes_limit_r,
(unsigned long long)*count_value_r,
(unsigned long long)*count_limit_r);
case Q_NOQUOTA:
case Q_EPERM:
#ifdef FS_QUOTA_LINUX
#ifdef HAVE_XFS_QUOTA
if (*bytes_limit_r == 0) {
if (*count_limit_r == 0) {
if (*bytes_limit_r == 0) {
if (*count_limit_r == 0) {
#ifdef FS_QUOTA_BSDAIX
if (*bytes_limit_r == 0) {
if (*count_limit_r == 0) {
#ifdef FS_QUOTA_NETBSD
int ret;
return ret;
#ifdef FS_QUOTA_HPUX
if (*bytes_limit_r == 0) {
if (*count_limit_r == 0) {
#ifdef FS_QUOTA_SOLARIS
if (*bytes_limit_r == 0) {
if (*count_limit_r == 0) {
if (group) {
#ifdef FS_QUOTA_LINUX
return fs_quota_get_netbsd(root, group, bytes_value_r, bytes_limit_r, count_value_r, count_limit_r);
return fs_quota_get_bsdaix(root, group, bytes_value_r, bytes_limit_r, count_value_r, count_limit_r);
if (group) {
#ifdef FS_QUOTA_HPUX
const char *mailbox_path;
bool match;
return TRUE;
&mailbox_path) <= 0)
return FALSE;
return FALSE;
return FALSE;
return match;
int ret;
*value_r = 0;
#ifdef HAVE_RQUOTA
T_BEGIN {
} T_END;
if (ret == 0) {
if (ret <= 0)
return ret;
NULL,
NULL,