1e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 2e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * mkquota.c --- create quota files for a filesystem 3e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 4e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Aditya Kali <adityakali@google.com> 5e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 6e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/types.h> 7e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/stat.h> 8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <unistd.h> 9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <errno.h> 10e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <string.h> 11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <fcntl.h> 12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "ext2fs/ext2_fs.h" 14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "ext2fs/ext2fs.h" 15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "e2p/e2p.h" 16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "quotaio.h" 18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "quotaio_v2.h" 19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "quotaio_tree.h" 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "mkquota.h" 21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "common.h" 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Needed for architectures where sizeof(int) != sizeof(void *) */ 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define UINT_TO_VOIDPTR(val) ((void *)(intptr_t)(val)) 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define VOIDPTR_TO_UINT(ptr) ((unsigned int)(intptr_t)(ptr)) 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if DEBUG_QUOTA 28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void print_inode(struct ext2_inode *inode) 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!inode) 31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_mode = %d\n", inode->i_mode); 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_uid = %d\n", inode->i_uid); 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_size = %d\n", inode->i_size); 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_atime = %d\n", inode->i_atime); 37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_ctime = %d\n", inode->i_ctime); 38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_mtime = %d\n", inode->i_mtime); 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_dtime = %d\n", inode->i_dtime); 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_gid = %d\n", inode->i_gid); 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_links_count = %d\n", inode->i_links_count); 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_blocks = %d\n", inode->i_blocks); 43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, " i_flags = %d\n", inode->i_flags); 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Returns 0 if not able to find the quota file, otherwise returns its 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * inode number. 52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint quota_file_exists(ext2_filsys fs, int qtype, int fmt) 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char qf_name[256]; 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t ret; 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t ino; 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (qtype >= MAXQUOTAS) 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -EINVAL; 61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name); 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ext2fs_lookup(fs, EXT2_ROOT_INO, qf_name, strlen(qf_name), 0, 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &ino); 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret) 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ino; 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Set the value for reserved quota inode number field in superblock. 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, int qtype) 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t *inump; 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inump = (qtype == USRQUOTA) ? &fs->super->s_usr_quota_inum : 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &fs->super->s_grp_quota_inum; 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_debug("setting quota ino in superblock: ino=%u, type=%d", ino, 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qtype); 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *inump = ino; 85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_super_dirty(fs); 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_remove_inode(ext2_filsys fs, int qtype) 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t qf_ino; 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_read_bitmaps(fs); 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qf_ino = (qtype == USRQUOTA) ? fs->super->s_usr_quota_inum : 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_grp_quota_inum; 95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_set_sb_inum(fs, 0, qtype); 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Truncate the inode only if its a reserved one. */ 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (qf_ino < EXT2_FIRST_INODE(fs->super)) 98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_inode_truncate(fs, qf_ino); 99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_super_dirty(fs); 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->flags &= ~EXT2_FLAG_SUPER_ONLY; 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_write_bitmaps(fs); 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void write_dquots(dict_t *dict, struct quota_handle *qh) 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dnode_t *n; 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dquot *dq; 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (n = dict_first(dict); n; n = dict_next(dict, n)) { 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq = dnode_get(n); 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dq) { 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_h = qh; 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall update_grace_times(dq); 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qh->qh_ops->commit_dquot(dq); 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_write_inode(quota_ctx_t qctx, int qtype) 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int retval = 0, i; 124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *dict; 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_filsys fs; 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct quota_handle *h = NULL; 127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int fmt = QFMT_VFS_V1; 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx) 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs = qctx->fs; 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_get_mem(sizeof(struct quota_handle), &h); 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) { 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Unable to allocate quota handle"); 136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_read_bitmaps(fs); 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < MAXQUOTAS; i++) { 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((qtype != -1) && (i != qtype)) 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict = qctx->quota_dict[i]; 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!dict) 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = quota_file_create(h, fs, i, fmt); 150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval < 0) { 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Cannot initialize io on quotafile"); 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall write_dquots(dict, h); 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = quota_file_close(h); 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval < 0) { 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Cannot finish IO on new quotafile: %s", 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strerror(errno)); 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_qf.e2_file) 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_close(h->qh_qf.e2_file); 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_inode_truncate(fs, h->qh_qf.ino); 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Set quota inode numbers in superblock. */ 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_set_sb_inum(fs, h->qh_qf.ino, i); 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_super_dirty(fs); 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_bb_dirty(fs); 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->flags &= ~EXT2_FLAG_SUPER_ONLY; 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_write_bitmaps(fs); 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h) 176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_mem(&h); 177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/******************************************************************/ 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Helper functions for computing quota in memory. */ 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/******************************************************************/ 183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int dict_uint_cmp(const void *a, const void *b) 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int c, d; 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall c = VOIDPTR_TO_UINT(a); 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall d = VOIDPTR_TO_UINT(b); 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return c - d; 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic inline qid_t get_qid(struct ext2_inode *inode, int qtype) 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (qtype == USRQUOTA) 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return inode_uid(*inode); 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return inode_gid(*inode); 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void quota_dnode_free(dnode_t *node, 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *context EXT2FS_ATTR((unused))) 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *ptr = node ? dnode_get(node) : 0; 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_mem(&ptr); 207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(node); 208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Set up the quota tracking data structures. 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, int qtype) 214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i, err = 0; 216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *dict; 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_ctx_t ctx; 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_get_mem(sizeof(struct quota_ctx), &ctx); 220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Failed to allocate quota context"); 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(ctx, 0, sizeof(struct quota_ctx)); 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < MAXQUOTAS; i++) { 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((qtype != -1) && (i != qtype)) 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_get_mem(sizeof(dict_t), &dict); 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Failed to allocate dictionary"); 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_release_context(&ctx); 233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ctx->quota_dict[i] = dict; 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_init(dict, DICTCOUNT_T_MAX, dict_uint_cmp); 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_set_allocator(dict, NULL, quota_dnode_free, NULL); 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ctx->fs = fs; 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *qctx = ctx; 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid quota_release_context(quota_ctx_t *qctx) 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *dict; 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i; 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_ctx_t ctx; 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx) 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ctx = *qctx; 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < MAXQUOTAS; i++) { 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict = ctx->quota_dict[i]; 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ctx->quota_dict[i] = 0; 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dict) { 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_free_nodes(dict); 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(dict); 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *qctx = NULL; 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(ctx); 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic struct dquot *get_dq(dict_t *dict, __u32 key) 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dquot *dq; 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dnode_t *n; 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall n = dict_lookup(dict, UINT_TO_VOIDPTR(key)); 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (n) 274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq = dnode_get(n); 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else { 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_get_mem(sizeof(struct dquot), &dq)) { 277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Unable to allocate dquot"); 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return NULL; 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(dq, 0, sizeof(struct dquot)); 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_alloc_insert(dict, UINT_TO_VOIDPTR(key), dq); 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_id = key; 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return dq; 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Called to update the blocks used by a particular inode 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid quota_data_add(quota_ctx_t qctx, struct ext2_inode *inode, ext2_ino_t ino, 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qsize_t space) 293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dquot *dq; 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *dict; 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i; 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx) 299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_debug("ADD_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino, 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode_uid(*inode), 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode_gid(*inode), space); 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < MAXQUOTAS; i++) { 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict = qctx->quota_dict[i]; 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dict) { 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq = get_dq(dict, get_qid(inode, i)); 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dq) 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_curspace += space; 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Called to remove some blocks used by a particular inode 316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid quota_data_sub(quota_ctx_t qctx, struct ext2_inode *inode, ext2_ino_t ino, 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qsize_t space) 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dquot *dq; 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *dict; 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i; 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx) 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_debug("SUB_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino, 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode_uid(*inode), 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode_gid(*inode), space); 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < MAXQUOTAS; i++) { 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict = qctx->quota_dict[i]; 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dict) { 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq = get_dq(dict, get_qid(inode, i)); 334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_curspace -= space; 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 338e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 340e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Called to count the files used by an inode's user/group 341e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 342e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid quota_data_inodes(quota_ctx_t qctx, struct ext2_inode *inode, 343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t ino, int adjust) 344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dquot *dq; 346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *dict; 347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i; 348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx) 350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_debug("ADJ_INODE: Inode: %u, UID/GID: %u/%u, adjust: %d", ino, 353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode_uid(*inode), 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode_gid(*inode), adjust); 355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < MAXQUOTAS; i++) { 356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict = qctx->quota_dict[i]; 357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dict) { 358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq = get_dq(dict, get_qid(inode, i)); 359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_curinodes += adjust; 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_compute_usage(quota_ctx_t qctx) 365e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 366e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_filsys fs; 367e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t ino; 368e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t ret; 369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode inode; 370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qsize_t space; 371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_inode_scan scan; 372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx) 374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs = qctx->fs; 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ext2fs_open_inode_scan(fs, 0, &scan); 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret) { 379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("while opening inode scan. ret=%ld", ret); 380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ret; 381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (1) { 384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ext2fs_get_next_inode(scan, &ino, &inode); 385e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret) { 386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("while getting next inode. ret=%ld", ret); 387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_close_inode_scan(scan); 388e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ret; 389e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 390e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ino == 0) 391e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 392e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (inode.i_links_count && 393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (ino == EXT2_ROOT_INO || 394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ino >= EXT2_FIRST_INODE(fs->super))) { 395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall space = ext2fs_inode_i_blocks(fs, &inode) << 9; 396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_data_add(qctx, &inode, ino, space); 397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_data_inodes(qctx, &inode, ino, +1); 398e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_close_inode_scan(scan); 402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 403e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 405e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct scan_dquots_data { 407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *quota_dict; 408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int update_limits; /* update limits from disk */ 409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int update_usage; 410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int usage_is_inconsistent; 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 413e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int scan_dquots_callback(struct dquot *dquot, void *cb_data) 414e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct scan_dquots_data *scan_data = cb_data; 416e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dict_t *quota_dict = scan_data->quota_dict; 417e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dquot *dq; 418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 419e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq = get_dq(quota_dict, dquot->dq_id); 420e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_id = dquot->dq_id; 421e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.u.v2_mdqb.dqb_off = dquot->dq_dqb.u.v2_mdqb.dqb_off; 422e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 423e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Check if there is inconsistancy. */ 424e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dq->dq_dqb.dqb_curspace != dquot->dq_dqb.dqb_curspace || 425e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_curinodes != dquot->dq_dqb.dqb_curinodes) { 426e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data->usage_is_inconsistent = 1; 427e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "[QUOTA WARNING] Usage inconsistent for ID %d:" 428e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "actual (%llu, %llu) != expected (%llu, %llu)\n", 429e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_id, (long long)dq->dq_dqb.dqb_curspace, 430e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (long long)dq->dq_dqb.dqb_curinodes, 431e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (long long)dquot->dq_dqb.dqb_curspace, 432e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (long long)dquot->dq_dqb.dqb_curinodes); 433e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 434e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 435e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (scan_data->update_limits) { 436e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit; 437e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit; 438e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit; 439e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit; 440e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 441e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 442e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (scan_data->update_usage) { 443e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_curspace = dquot->dq_dqb.dqb_curspace; 444e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dq->dq_dqb.dqb_curinodes = dquot->dq_dqb.dqb_curinodes; 445e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 446e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 447e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 448e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 449e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 450e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 451e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Read all dquots from quota file into memory 452e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 453e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t quota_read_all_dquots(struct quota_handle *qh, 454e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_ctx_t qctx, int update_limits) 455e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 456e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct scan_dquots_data scan_data; 457e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 458e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data.quota_dict = qctx->quota_dict[qh->qh_type]; 459e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data.update_limits = update_limits; 460e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data.update_usage = 0; 461e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return qh->qh_ops->scan_dquots(qh, scan_dquots_callback, &scan_data); 463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 466e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Write all memory dquots into quota file 467e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 468e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if 0 /* currently unused, but may be useful in the future? */ 469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t quota_write_all_dquots(struct quota_handle *qh, 470e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_ctx_t qctx) 471e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 472e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err; 473e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 474e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_read_bitmaps(qctx->fs); 475e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) 476e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 477e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall write_dquots(qctx->quota_dict[qh->qh_type], qh); 478e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_bb_dirty(qctx->fs); 479e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qctx->fs->flags &= ~EXT2_FLAG_SUPER_ONLY; 480e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_write_bitmaps(qctx->fs); 481e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 482e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 483e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 484e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 485e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 486e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Updates the in-memory quota limits from the given quota inode. 487e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 488e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, int type) 489e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 490e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct quota_handle *qh; 491e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err; 492e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 493e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx) 494e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 495e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 496e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_get_mem(sizeof(struct quota_handle), &qh); 497e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 498e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Unable to allocate quota handle"); 499e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 500e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 501e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 502e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = quota_file_open(qh, qctx->fs, qf_ino, type, -1, 0); 503e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 504e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Open quota file failed"); 505e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 506e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 507e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 508e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_read_all_dquots(qh, qctx, 1); 509e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = quota_file_close(qh); 511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Cannot finish IO on new quotafile: %s", 513e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strerror(errno)); 514e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (qh->qh_qf.e2_file) 515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_close(qh->qh_qf.e2_file); 516e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 517e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 518e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_mem(&qh); 519e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 520e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 522e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Compares the measured quota in qctx->quota_dict with that in the quota inode 524e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * on disk and updates the limits in qctx->quota_dict. 'usage_inconsistent' is 525e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * set to 1 if the supplied and on-disk quota usage values are not identical. 526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_compare_and_update(quota_ctx_t qctx, int qtype, 528e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int *usage_inconsistent) 529e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 530e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_filsys fs = qctx->fs; 531e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct quota_handle qh; 532e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct scan_dquots_data scan_data; 533e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t qf_ino; 534e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err = 0; 535e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 536e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!qctx->quota_dict[qtype]) 537e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 538e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 539e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qf_ino = qtype == USRQUOTA ? fs->super->s_usr_quota_inum : 540e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_grp_quota_inum; 541e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = quota_file_open(&qh, fs, qf_ino, qtype, -1, 0); 542e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 543e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Open quota file failed"); 544e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 545e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 546e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 547e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data.quota_dict = qctx->quota_dict[qtype]; 548e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data.update_limits = 1; 549e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data.update_usage = 0; 550e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall scan_data.usage_is_inconsistent = 0; 551e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = qh.qh_ops->scan_dquots(&qh, scan_dquots_callback, &scan_data); 552e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 553e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Error scanning dquots"); 554e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 555e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 556e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *usage_inconsistent = scan_data.usage_is_inconsistent; 557e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 558e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 559e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 560e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 561