4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
34 * lustre/lvfs/lustre_quota_fmt.c
36 * Lustre administrative quota format.
37 * from linux/fs/quota_v2.c
41 # define EXPORT_SYMTAB
44 #include <linux/errno.h>
46 #include <linux/mount.h>
47 #include <linux/kernel.h>
48 #include <linux/init.h>
49 #include <linux/module.h>
50 #include <linux/slab.h>
51 #ifdef HAVE_QUOTAIO_V1_H
52 # include <linux/quotaio_v1.h>
55 #include <asm/byteorder.h>
56 #include <asm/uaccess.h>
58 #include <lustre_quota.h>
59 #include <obd_support.h>
60 #include "lustre_quota_fmt.h"
62 #ifdef HAVE_QUOTA_SUPPORT
64 static const uint lustre_initqversions[][MAXQUOTAS] = {
65 [LUSTRE_QUOTA_V2] = LUSTRE_INITQVERSIONS_V2
68 static const int lustre_dqstrinblk[] = {
69 [LUSTRE_QUOTA_V2] = LUSTRE_DQSTRINBLK_V2
72 static const int lustre_disk_dqblk_sz[] = {
73 [LUSTRE_QUOTA_V2] = sizeof(struct lustre_disk_dqblk_v2)
78 struct lustre_disk_dqblk_v2 r1;
80 [LUSTRE_QUOTA_V2] = {.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)}}
85 struct lustre_disk_dqblk_v2 r1;
87 [LUSTRE_QUOTA_V2] = {.r1 = { 0 }}
90 extern void *lustre_quota_journal_start(struct inode *inode, int delete);
91 extern void lustre_quota_journal_stop(void *handle);
92 extern ssize_t lustre_read_quota(struct file *f, struct inode *inode, int type,
93 char *buf, int count, loff_t pos);
94 extern ssize_t lustre_write_quota(struct file *f, char *buf, int count, loff_t pos);
96 int check_quota_file(struct file *f, struct inode *inode, int type,
97 lustre_quota_version_t version)
99 struct lustre_disk_dqheader dqhead;
101 static const uint quota_magics[] = LUSTRE_INITQMAGICS;
102 const uint *quota_versions = lustre_initqversions[version];
104 size = lustre_read_quota(f, inode, type, (char *)&dqhead,
105 sizeof(struct lustre_disk_dqheader), 0);
106 if (size != sizeof(struct lustre_disk_dqheader))
108 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
109 le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
115 * Check whether given file is really lustre admin quotafile
117 int lustre_check_quota_file(struct lustre_quota_info *lqi, int type)
119 struct file *f = lqi->qi_files[type];
120 return check_quota_file(f, NULL, type, lqi->qi_version);
123 int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info)
125 struct lustre_disk_dqinfo dinfo;
128 size = lustre_read_quota(f, NULL, 0, (char *)&dinfo,
129 sizeof(struct lustre_disk_dqinfo),
132 if (size != sizeof(struct lustre_disk_dqinfo)) {
133 CDEBUG(D_ERROR, "Can't read info structure on device %s.\n",
134 f->f_vfsmnt->mnt_sb->s_id);
137 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
138 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
139 info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
140 info->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
141 info->dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
142 info->dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
147 * Read information header from quota file
149 int lustre_read_quota_info(struct lustre_quota_info *lqi, int type)
151 return lustre_read_quota_file_info(lqi->qi_files[type],
152 &lqi->qi_info[type]);
156 * Write information header to quota file
158 int lustre_write_quota_info(struct lustre_quota_info *lqi, int type)
160 struct lustre_disk_dqinfo dinfo;
161 struct lustre_mem_dqinfo *info = &lqi->qi_info[type];
162 struct file *f = lqi->qi_files[type];
165 info->dqi_flags &= ~DQF_INFO_DIRTY;
166 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
167 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
168 dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
169 dinfo.dqi_blocks = cpu_to_le32(info->dqi_blocks);
170 dinfo.dqi_free_blk = cpu_to_le32(info->dqi_free_blk);
171 dinfo.dqi_free_entry = cpu_to_le32(info->dqi_free_entry);
173 size = lustre_write_quota(f, (char *)&dinfo,
174 sizeof(struct lustre_disk_dqinfo),
177 if (size != sizeof(struct lustre_disk_dqinfo)) {
179 "Can't write info structure on device %s.\n",
180 f->f_vfsmnt->mnt_sb->s_id);
186 void disk2memdqb(struct lustre_mem_dqblk *m, void *d,
187 lustre_quota_version_t version)
189 struct lustre_disk_dqblk_v2 *dqblk = (struct lustre_disk_dqblk_v2 *)d;
191 LASSERT(version == LUSTRE_QUOTA_V2);
193 m->dqb_ihardlimit = le64_to_cpu(dqblk->dqb_ihardlimit);
194 m->dqb_isoftlimit = le64_to_cpu(dqblk->dqb_isoftlimit);
195 m->dqb_curinodes = le64_to_cpu(dqblk->dqb_curinodes);
196 m->dqb_itime = le64_to_cpu(dqblk->dqb_itime);
197 m->dqb_bhardlimit = le64_to_cpu(dqblk->dqb_bhardlimit);
198 m->dqb_bsoftlimit = le64_to_cpu(dqblk->dqb_bsoftlimit);
199 m->dqb_curspace = le64_to_cpu(dqblk->dqb_curspace);
200 m->dqb_btime = le64_to_cpu(dqblk->dqb_btime);
203 static int mem2diskdqb(void *d, struct lustre_mem_dqblk *m,
204 qid_t id, lustre_quota_version_t version)
206 struct lustre_disk_dqblk_v2 *dqblk = (struct lustre_disk_dqblk_v2 *)d;
208 LASSERT(version == LUSTRE_QUOTA_V2);
210 dqblk->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
211 dqblk->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
212 dqblk->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
213 dqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
214 dqblk->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
215 dqblk->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
216 dqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
217 dqblk->dqb_btime = cpu_to_le64(m->dqb_btime);
218 dqblk->dqb_id = cpu_to_le32(id);
223 dqbuf_t getdqbuf(void)
225 dqbuf_t buf = kmalloc(LUSTRE_DQBLKSIZE, GFP_NOFS);
228 "VFS: Not enough memory for quota buffers.\n");
232 void freedqbuf(dqbuf_t buf)
237 ssize_t read_blk(struct file *filp, struct inode *inode, int type,
238 uint blk, dqbuf_t buf)
242 memset(buf, 0, LUSTRE_DQBLKSIZE);
243 ret = lustre_read_quota(filp, inode, type, (char *)buf, LUSTRE_DQBLKSIZE,
244 blk << LUSTRE_DQBLKSIZE_BITS);
246 /* Reading past EOF just returns a block of zeros */
253 ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
257 ret = lustre_write_quota(filp, (char *)buf, LUSTRE_DQBLKSIZE,
258 blk << LUSTRE_DQBLKSIZE_BITS);
263 void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info)
265 cfs_set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
269 * Remove empty block from list and return it
271 int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info)
273 dqbuf_t buf = getdqbuf();
274 struct lustre_disk_dqdbheader *dh =
275 (struct lustre_disk_dqdbheader *)buf;
280 if (info->dqi_free_blk) {
281 blk = info->dqi_free_blk;
282 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0)
284 info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
286 memset(buf, 0, LUSTRE_DQBLKSIZE);
287 /* Assure block allocation... */
288 if ((ret = write_blk(filp, info->dqi_blocks, buf)) < 0)
290 blk = info->dqi_blocks++;
292 lustre_mark_info_dirty(info);
300 * Insert empty block to the list
302 int put_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info,
303 dqbuf_t buf, uint blk)
305 struct lustre_disk_dqdbheader *dh =
306 (struct lustre_disk_dqdbheader *)buf;
309 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);
310 dh->dqdh_prev_free = cpu_to_le32(0);
311 dh->dqdh_entries = cpu_to_le16(0);
312 info->dqi_free_blk = blk;
313 lustre_mark_info_dirty(info);
314 if ((err = write_blk(filp, blk, buf)) < 0)
315 /* Some strange block. We had better leave it... */
321 * Remove given block from the list of blocks with free entries
323 int remove_free_dqentry(struct file *filp,
324 struct lustre_mem_dqinfo *info, dqbuf_t buf,
327 dqbuf_t tmpbuf = getdqbuf();
328 struct lustre_disk_dqdbheader *dh =
329 (struct lustre_disk_dqdbheader *)buf;
330 uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk =
331 le32_to_cpu(dh->dqdh_prev_free);
337 if ((err = read_blk(filp, NULL, 0, nextblk, tmpbuf)) < 0)
339 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
341 if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
345 if ((err = read_blk(filp, NULL, 0, prevblk, tmpbuf)) < 0)
347 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
349 if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
352 info->dqi_free_entry = nextblk;
353 lustre_mark_info_dirty(info);
356 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
357 if (write_blk(filp, blk, buf) < 0)
358 /* No matter whether write succeeds block is out of list */
360 "VFS: Can't write block (%u) with free entries.\n", blk);
368 * Insert given block to the beginning of list with free entries
370 int insert_free_dqentry(struct file *filp,
371 struct lustre_mem_dqinfo *info, dqbuf_t buf,
374 dqbuf_t tmpbuf = getdqbuf();
375 struct lustre_disk_dqdbheader *dh =
376 (struct lustre_disk_dqdbheader *)buf;
381 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);
382 dh->dqdh_prev_free = cpu_to_le32(0);
383 if ((err = write_blk(filp, blk, buf)) < 0)
385 if (info->dqi_free_entry) {
386 if ((err = read_blk(filp, NULL, 0, info->dqi_free_entry, tmpbuf)) < 0)
388 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
390 if ((err = write_blk(filp, info->dqi_free_entry, tmpbuf)) < 0)
394 info->dqi_free_entry = blk;
395 lustre_mark_info_dirty(info);
405 * Find space for dquot
407 static uint find_free_dqentry(struct lustre_dquot *dquot, int *err,
408 lustre_quota_version_t version)
410 struct lustre_quota_info *lqi = dquot->dq_info;
411 struct file *filp = lqi->qi_files[dquot->dq_type];
412 struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];
414 struct lustre_disk_dqdbheader *dh;
416 int dqblk_sz = lustre_disk_dqblk_sz[version];
417 int dqstrinblk = lustre_dqstrinblk[version];
421 if (!(buf = getdqbuf())) {
425 dh = (struct lustre_disk_dqdbheader *)buf;
426 ddquot = GETENTRIES(buf, version);
427 if (info->dqi_free_entry) {
428 blk = info->dqi_free_entry;
429 if ((*err = read_blk(filp, NULL, 0, blk, buf)) < 0)
432 blk = get_free_dqblk(filp, info);
438 memset(buf, 0, LUSTRE_DQBLKSIZE);
439 info->dqi_free_entry = blk; /* This is enough as block is
440 already zeroed and entry list
442 lustre_mark_info_dirty(info);
445 /* Will block be full */
446 if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk)
447 if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
449 "VFS: find_free_dqentry(): Can't remove block "
450 "(%u) from entry free list.\n", blk);
453 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) + 1);
454 /* Find free structure in block */
455 for (i = 0; i < dqstrinblk &&
456 memcmp((char *)&emptydquot[version],
457 (char *)ddquot + i * dqblk_sz, dqblk_sz);
460 if (i == dqstrinblk) {
462 "VFS: find_free_dqentry(): Data block full but it "
468 if ((*err = write_blk(filp, blk, buf)) < 0) {
470 "VFS: find_free_dqentry(): Can't write quota data "
475 (blk << LUSTRE_DQBLKSIZE_BITS) +
476 sizeof(struct lustre_disk_dqdbheader) +
486 * Insert reference to structure into the trie
488 static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth,
489 lustre_quota_version_t version)
491 struct lustre_quota_info *lqi = dquot->dq_info;
492 struct file *filp = lqi->qi_files[dquot->dq_type];
493 struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];
495 int ret = 0, newson = 0, newact = 0;
499 if (!(buf = getdqbuf()))
502 ret = get_free_dqblk(filp, info);
506 memset(buf, 0, LUSTRE_DQBLKSIZE);
509 if ((ret = read_blk(filp, NULL, 0, *treeblk, buf)) < 0) {
510 CERROR("VFS: Can't read tree quota block %u.\n",
516 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
519 if (depth == LUSTRE_DQTREEDEPTH - 1) {
523 "VFS: Inserting already present quota entry "
525 ref[GETIDINDEX(dquot->dq_id, depth)]);
530 newblk = find_free_dqentry(dquot, &ret, version);
532 ret = do_insert_tree(dquot, &newblk, depth + 1, version);
533 if (newson && ret >= 0) {
534 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
535 ret = write_blk(filp, *treeblk, buf);
536 } else if (newact && ret < 0)
537 put_free_dqblk(filp, info, buf, *treeblk);
544 * Wrapper for inserting quota structure into tree
546 static inline int dq_insert_tree(struct lustre_dquot *dquot,
547 lustre_quota_version_t version)
549 int tmp = LUSTRE_DQTREEOFF;
550 return do_insert_tree(dquot, &tmp, 0, version);
554 * We don't have to be afraid of deadlocks as we never have quotas on
557 static int lustre_write_dquot(struct lustre_dquot *dquot,
558 lustre_quota_version_t version)
560 int type = dquot->dq_type;
564 int dqblk_sz = lustre_disk_dqblk_sz[version];
565 struct lustre_disk_dqblk_v2 ddquot;
567 ret = mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, version);
572 if ((ret = dq_insert_tree(dquot, version)) < 0) {
574 "VFS: Error %Zd occurred while creating "
578 filp = dquot->dq_info->qi_files[type];
579 offset = dquot->dq_off;
580 /* Argh... We may need to write structure full of zeroes but that would
581 * be treated as an empty place by the rest of the code. Format change
582 * would be definitely cleaner but the problems probably are not worth
584 if (!memcmp((char *)&emptydquot[version], (char *)&ddquot, dqblk_sz))
585 ddquot.dqb_itime = cpu_to_le64(1);
587 ret = lustre_write_quota(filp, (char *)&ddquot, dqblk_sz, offset);
588 if (ret != dqblk_sz) {
589 CDEBUG(D_WARNING, "VFS: dquota write failed on dev %s\n",
590 filp->f_dentry->d_sb->s_id);
600 * Free dquot entry in data block
602 static int free_dqentry(struct lustre_dquot *dquot, uint blk,
603 lustre_quota_version_t version)
605 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
606 struct lustre_mem_dqinfo *info =
607 &dquot->dq_info->qi_info[dquot->dq_type];
608 struct lustre_disk_dqdbheader *dh;
609 dqbuf_t buf = getdqbuf();
610 int dqstrinblk = lustre_dqstrinblk[version];
615 if (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS != blk) {
617 "VFS: Quota structure has offset to other block (%u) "
618 "than it should (%u).\n",
619 blk, (uint) (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS));
622 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
623 CDEBUG(D_ERROR, "VFS: Can't read quota data block %u\n", blk);
626 dh = (struct lustre_disk_dqdbheader *)buf;
627 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) - 1);
628 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
629 if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
630 (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
632 "VFS: Can't move quota data block (%u) to free "
637 memset(buf + (dquot->dq_off & ((1<<LUSTRE_DQBLKSIZE_BITS) - 1)),
638 0, lustre_disk_dqblk_sz[version]);
639 if (le16_to_cpu(dh->dqdh_entries) == dqstrinblk - 1) {
640 /* Insert will write block itself */
642 insert_free_dqentry(filp, info, buf, blk)) < 0) {
644 "VFS: Can't insert quota data block "
645 "(%u) to free entry list.\n", blk);
648 } else if ((ret = write_blk(filp, blk, buf)) < 0) {
650 "VFS: Can't write quota data block %u\n", blk);
654 dquot->dq_off = 0; /* Quota is now unattached */
661 * Remove reference to dquot from tree
663 static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth,
664 lustre_quota_version_t version)
666 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
667 struct lustre_mem_dqinfo *info =
668 &dquot->dq_info->qi_info[dquot->dq_type];
669 dqbuf_t buf = getdqbuf();
672 u32 *ref = (u32 *) buf;
676 if ((ret = read_blk(filp, NULL, 0, *blk, buf)) < 0) {
677 CERROR("VFS: Can't read quota data block %u\n", *blk);
680 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
681 if (depth == LUSTRE_DQTREEDEPTH - 1) {
682 ret = free_dqentry(dquot, newblk, version);
685 ret = remove_tree(dquot, &newblk, depth + 1, version);
686 if (ret >= 0 && !newblk) {
688 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
689 for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++)
690 /* Block got empty? */ ;
691 /* don't put the root block into free blk list! */
692 if (i == LUSTRE_DQBLKSIZE && *blk != LUSTRE_DQTREEOFF) {
693 put_free_dqblk(filp, info, buf, *blk);
695 } else if ((ret = write_blk(filp, *blk, buf)) < 0)
697 "VFS: Can't write quota tree block %u.\n", *blk);
705 * Delete dquot from tree
707 static int lustre_delete_dquot(struct lustre_dquot *dquot,
708 lustre_quota_version_t version)
710 uint tmp = LUSTRE_DQTREEOFF;
712 if (!dquot->dq_off) /* Even not allocated? */
714 return remove_tree(dquot, &tmp, 0, version);
718 * Find entry in block
720 static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk,
721 lustre_quota_version_t version)
723 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
724 dqbuf_t buf = getdqbuf();
727 struct lustre_disk_dqblk_v2 *ddquot =
728 (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
729 int dqblk_sz = lustre_disk_dqblk_sz[version];
730 int dqstrinblk = lustre_dqstrinblk[version];
732 LASSERT(version == LUSTRE_QUOTA_V2);
736 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
737 CERROR("VFS: Can't read quota tree block %u.\n", blk);
741 for (i = 0; i < dqstrinblk &&
742 le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id;
744 else { /* ID 0 as a bit more complicated searching... */
745 for (i = 0; i < dqstrinblk; i++)
746 if (!le32_to_cpu(ddquot[i].dqb_id)
747 && memcmp((char *)&emptydquot[version],
748 (char *)&ddquot[i], dqblk_sz))
751 if (i == dqstrinblk) {
753 "VFS: Quota for id %u referenced but not present.\n",
759 (blk << LUSTRE_DQBLKSIZE_BITS) +
760 sizeof(struct lustre_disk_dqdbheader) +
768 * Find entry for given id in the tree
770 static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth,
771 lustre_quota_version_t version)
773 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
774 dqbuf_t buf = getdqbuf();
776 u32 *ref = (u32 *) buf;
780 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
781 CERROR("VFS: Can't read quota tree block %u.\n", blk);
785 blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
786 if (!blk) /* No reference? */
788 if (depth < LUSTRE_DQTREEDEPTH - 1)
789 ret = find_tree_dqentry(dquot, blk, depth + 1, version);
791 ret = find_block_dqentry(dquot, blk, version);
798 * Find entry for given id in the tree - wrapper function
800 static inline loff_t find_dqentry(struct lustre_dquot *dquot,
801 lustre_quota_version_t version)
803 return find_tree_dqentry(dquot, LUSTRE_DQTREEOFF, 0, version);
806 int lustre_read_dquot(struct lustre_dquot *dquot)
808 int type = dquot->dq_type;
811 int ret = 0, dqblk_sz;
812 lustre_quota_version_t version;
814 /* Invalidated quota? */
815 if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) {
816 CDEBUG(D_ERROR, "VFS: Quota invalidated while reading!\n");
820 version = dquot->dq_info->qi_version;
821 LASSERT(version == LUSTRE_QUOTA_V2);
822 dqblk_sz = lustre_disk_dqblk_sz[version];
824 offset = find_dqentry(dquot, version);
825 if (offset <= 0) { /* Entry not present? */
828 "VFS: Can't read quota structure for id %u.\n",
831 cfs_set_bit(DQ_FAKE_B, &dquot->dq_flags);
832 memset(&dquot->dq_dqb, 0, sizeof(struct lustre_mem_dqblk));
835 struct lustre_disk_dqblk_v2 ddquot;
837 dquot->dq_off = offset;
838 if ((ret = lustre_read_quota(filp, NULL, type, (char *)&ddquot,
839 dqblk_sz, offset)) != dqblk_sz) {
843 "VFS: Error while reading quota structure for id "
844 "%u.\n", dquot->dq_id);
845 memset((char *)&ddquot, 0, dqblk_sz);
848 /* We need to escape back all-zero structure */
849 if (!memcmp((char *)&fakedquot[version],
850 (char *)&ddquot, dqblk_sz))
851 ddquot.dqb_itime = cpu_to_le64(0);
853 disk2memdqb(&dquot->dq_dqb, &ddquot, version);
860 * Commit changes of dquot to disk - it might also mean deleting
861 * it when quota became fake.
863 int lustre_commit_dquot(struct lustre_dquot *dquot)
866 lustre_quota_version_t version = dquot->dq_info->qi_version;
868 struct inode *inode = dquot->dq_info->qi_files[dquot->dq_type]->f_dentry->d_inode;
871 /* always clear the flag so we don't loop on an IO error... */
872 cfs_clear_bit(DQ_MOD_B, &dquot->dq_flags);
874 /* The block/inode usage in admin quotafile isn't the real usage
875 * over all cluster, so keep the fake dquot entry on disk is
876 * meaningless, just remove it */
877 if (cfs_test_bit(DQ_FAKE_B, &dquot->dq_flags))
879 handle = lustre_quota_journal_start(inode, delete);
880 if (unlikely(IS_ERR(handle))) {
881 rc = PTR_ERR(handle);
882 CERROR("fail to lustre_quota_journal_start: rc = %d\n", rc);
887 rc = lustre_delete_dquot(dquot, version);
889 rc = lustre_write_dquot(dquot, version);
890 lustre_quota_journal_stop(handle);
895 if (lustre_info_dirty(&dquot->dq_info->qi_info[dquot->dq_type]))
896 rc = lustre_write_quota_info(dquot->dq_info, dquot->dq_type);
901 int lustre_init_quota_header(struct lustre_quota_info *lqi, int type,
904 static const uint quota_magics[] = LUSTRE_INITQMAGICS;
905 static const uint fake_magics[] = LUSTRE_BADQMAGICS;
906 const uint* quota_versions = lustre_initqversions[lqi->qi_version];
907 struct lustre_disk_dqheader dqhead;
909 struct file *fp = lqi->qi_files[type];
912 /* write quotafile header */
913 dqhead.dqh_magic = cpu_to_le32(fakemagics ?
914 fake_magics[type] : quota_magics[type]);
915 dqhead.dqh_version = cpu_to_le32(quota_versions[type]);
916 size = lustre_write_quota(fp, (char *)&dqhead,
917 sizeof(struct lustre_disk_dqheader), 0);
919 if (size != sizeof(struct lustre_disk_dqheader)) {
920 CDEBUG(D_ERROR, "error writing quoafile header (rc:%d)\n", rc);
928 * We need to export this function to initialize quotafile, because we haven't
929 * user level check utility
931 int lustre_init_quota_info_generic(struct lustre_quota_info *lqi, int type,
934 struct lustre_mem_dqinfo *dqinfo = &lqi->qi_info[type];
937 rc = lustre_init_quota_header(lqi, type, fakemagics);
941 /* write init quota info */
942 memset(dqinfo, 0, sizeof(*dqinfo));
943 dqinfo->dqi_bgrace = MAX_DQ_TIME;
944 dqinfo->dqi_igrace = MAX_IQ_TIME;
945 dqinfo->dqi_blocks = LUSTRE_DQTREEOFF + 1;
947 return lustre_write_quota_info(lqi, type);
950 int lustre_init_quota_info(struct lustre_quota_info *lqi, int type)
952 return lustre_init_quota_info_generic(lqi, type, 0);
955 static int walk_block_dqentry(struct file *filp, struct inode *inode, int type,
956 uint blk, cfs_list_t *list)
958 dqbuf_t buf = getdqbuf();
960 struct lustre_disk_dqdbheader *dqhead =
961 (struct lustre_disk_dqdbheader *)buf;
962 struct dqblk *blk_item;
968 if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
969 CERROR("VFS: Can't read quota tree block %u.\n", blk);
974 if (!le32_to_cpu(dqhead->dqdh_entries))
977 if (cfs_list_empty(list)) {
982 cfs_list_for_each_entry(pos, list, link) {
983 if (blk == pos->blk) /* we got this blk already */
991 blk_item = kmalloc(sizeof(*blk_item), GFP_NOFS);
997 CFS_INIT_LIST_HEAD(&blk_item->link);
999 cfs_list_add_tail(&blk_item->link, tmp);
1006 int walk_tree_dqentry(struct file *filp, struct inode *inode, int type,
1007 uint blk, int depth, cfs_list_t *list)
1009 dqbuf_t buf = getdqbuf();
1012 u32 *ref = (u32 *) buf;
1016 if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
1017 CERROR("VFS: Can't read quota tree block %u.\n", blk);
1022 for (index = 0; index <= 0xff && !ret; index++) {
1023 blk = le32_to_cpu(ref[index]);
1024 if (!blk) /* No reference */
1027 if (depth < LUSTRE_DQTREEDEPTH - 1)
1028 ret = walk_tree_dqentry(filp, inode, type, blk,
1031 ret = walk_block_dqentry(filp, inode, type, blk, list);
1039 * Walk through the quota file (v2 format) to get all ids with quota limit
1041 int lustre_get_qids(struct file *fp, struct inode *inode, int type,
1044 cfs_list_t blk_list;
1045 struct dqblk *blk_item, *tmp;
1047 struct lustre_disk_dqblk_v2 *ddquot;
1049 lustre_quota_version_t version;
1053 LASSERT(ergo(fp == NULL, inode != NULL));
1055 if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V2) == 0)
1056 version = LUSTRE_QUOTA_V2;
1058 CDEBUG(D_ERROR, "unknown quota file format!\n");
1062 if (!cfs_list_empty(list)) {
1063 CDEBUG(D_ERROR, "not empty list\n");
1067 CFS_INIT_LIST_HEAD(&blk_list);
1068 rc = walk_tree_dqentry(fp, inode, type, LUSTRE_DQTREEOFF, 0, &blk_list);
1070 CDEBUG(D_ERROR, "walk through quota file failed!(%d)\n", rc);
1073 if (cfs_list_empty(&blk_list))
1079 ddquot = (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
1081 cfs_list_for_each_entry(blk_item, &blk_list, link) {
1083 int i, dqblk_sz = lustre_disk_dqblk_sz[version];
1085 memset(buf, 0, LUSTRE_DQBLKSIZE);
1086 if ((ret = read_blk(fp, inode, type, blk_item->blk, buf)) < 0) {
1087 CERROR("VFS: Can't read quota tree block %u.\n",
1089 GOTO(out_free, rc = ret);
1092 for (i = 0; i < lustre_dqstrinblk[version]; i++) {
1093 struct dquot_id *dqid;
1094 /* skip empty entry */
1095 if (!memcmp((char *)&emptydquot[version],
1096 (char *)&ddquot[i], dqblk_sz))
1099 OBD_ALLOC_GFP(dqid, sizeof(*dqid), GFP_NOFS);
1101 GOTO(out_free, rc = -ENOMEM);
1103 dqid->di_id = le32_to_cpu(ddquot[i].dqb_id);
1104 dqid->di_flag = le64_to_cpu(ddquot[i].dqb_ihardlimit) ?
1106 dqid->di_flag |= le64_to_cpu(ddquot[i].dqb_bhardlimit) ?
1109 CFS_INIT_LIST_HEAD(&dqid->di_link);
1110 cfs_list_add(&dqid->di_link, list);
1115 cfs_list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
1116 cfs_list_del_init(&blk_item->link);
1126 EXPORT_SYMBOL(lustre_read_quota_info);
1127 EXPORT_SYMBOL(lustre_write_quota_info);
1128 EXPORT_SYMBOL(lustre_check_quota_file);
1129 EXPORT_SYMBOL(lustre_read_dquot);
1130 EXPORT_SYMBOL(lustre_commit_dquot);
1131 EXPORT_SYMBOL(lustre_init_quota_info);
1132 EXPORT_SYMBOL(lustre_get_qids);