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);
122 EXPORT_SYMBOL(lustre_check_quota_file);
124 int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info)
126 struct lustre_disk_dqinfo dinfo;
129 size = lustre_read_quota(f, NULL, 0, (char *)&dinfo,
130 sizeof(struct lustre_disk_dqinfo),
133 if (size != sizeof(struct lustre_disk_dqinfo)) {
134 CDEBUG(D_ERROR, "Can't read info structure on device %s.\n",
135 f->f_vfsmnt->mnt_sb->s_id);
138 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
139 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
140 info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
141 info->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
142 info->dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
143 info->dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
148 * Read information header from quota file
150 int lustre_read_quota_info(struct lustre_quota_info *lqi, int type)
152 return lustre_read_quota_file_info(lqi->qi_files[type],
153 &lqi->qi_info[type]);
155 EXPORT_SYMBOL(lustre_read_quota_info);
158 * Write information header to quota file
160 int lustre_write_quota_info(struct lustre_quota_info *lqi, int type)
162 struct lustre_disk_dqinfo dinfo;
163 struct lustre_mem_dqinfo *info = &lqi->qi_info[type];
164 struct file *f = lqi->qi_files[type];
167 info->dqi_flags &= ~DQF_INFO_DIRTY;
168 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
169 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
170 dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
171 dinfo.dqi_blocks = cpu_to_le32(info->dqi_blocks);
172 dinfo.dqi_free_blk = cpu_to_le32(info->dqi_free_blk);
173 dinfo.dqi_free_entry = cpu_to_le32(info->dqi_free_entry);
175 size = lustre_write_quota(f, (char *)&dinfo,
176 sizeof(struct lustre_disk_dqinfo),
179 if (size != sizeof(struct lustre_disk_dqinfo)) {
181 "Can't write info structure on device %s.\n",
182 f->f_vfsmnt->mnt_sb->s_id);
187 EXPORT_SYMBOL(lustre_write_quota_info);
189 void disk2memdqb(struct lustre_mem_dqblk *m, void *d,
190 lustre_quota_version_t version)
192 struct lustre_disk_dqblk_v2 *dqblk = (struct lustre_disk_dqblk_v2 *)d;
194 LASSERT(version == LUSTRE_QUOTA_V2);
196 m->dqb_ihardlimit = le64_to_cpu(dqblk->dqb_ihardlimit);
197 m->dqb_isoftlimit = le64_to_cpu(dqblk->dqb_isoftlimit);
198 m->dqb_curinodes = le64_to_cpu(dqblk->dqb_curinodes);
199 m->dqb_itime = le64_to_cpu(dqblk->dqb_itime);
200 m->dqb_bhardlimit = le64_to_cpu(dqblk->dqb_bhardlimit);
201 m->dqb_bsoftlimit = le64_to_cpu(dqblk->dqb_bsoftlimit);
202 m->dqb_curspace = le64_to_cpu(dqblk->dqb_curspace);
203 m->dqb_btime = le64_to_cpu(dqblk->dqb_btime);
206 static int mem2diskdqb(void *d, struct lustre_mem_dqblk *m,
207 qid_t id, lustre_quota_version_t version)
209 struct lustre_disk_dqblk_v2 *dqblk = (struct lustre_disk_dqblk_v2 *)d;
211 LASSERT(version == LUSTRE_QUOTA_V2);
213 dqblk->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
214 dqblk->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
215 dqblk->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
216 dqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
217 dqblk->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
218 dqblk->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
219 dqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
220 dqblk->dqb_btime = cpu_to_le64(m->dqb_btime);
221 dqblk->dqb_id = cpu_to_le32(id);
226 dqbuf_t getdqbuf(void)
228 dqbuf_t buf = kmalloc(LUSTRE_DQBLKSIZE, GFP_NOFS);
231 "VFS: Not enough memory for quota buffers.\n");
235 void freedqbuf(dqbuf_t buf)
240 ssize_t read_blk(struct file *filp, struct inode *inode, int type,
241 uint blk, dqbuf_t buf)
245 memset(buf, 0, LUSTRE_DQBLKSIZE);
246 ret = lustre_read_quota(filp, inode, type, (char *)buf, LUSTRE_DQBLKSIZE,
247 blk << LUSTRE_DQBLKSIZE_BITS);
249 /* Reading past EOF just returns a block of zeros */
256 ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
260 ret = lustre_write_quota(filp, (char *)buf, LUSTRE_DQBLKSIZE,
261 blk << LUSTRE_DQBLKSIZE_BITS);
266 void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info)
268 cfs_set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
272 * Remove empty block from list and return it
274 int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info)
276 dqbuf_t buf = getdqbuf();
277 struct lustre_disk_dqdbheader *dh =
278 (struct lustre_disk_dqdbheader *)buf;
283 if (info->dqi_free_blk) {
284 blk = info->dqi_free_blk;
285 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0)
287 info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
289 memset(buf, 0, LUSTRE_DQBLKSIZE);
290 /* Assure block allocation... */
291 if ((ret = write_blk(filp, info->dqi_blocks, buf)) < 0)
293 blk = info->dqi_blocks++;
295 lustre_mark_info_dirty(info);
303 * Insert empty block to the list
305 int put_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info,
306 dqbuf_t buf, uint blk)
308 struct lustre_disk_dqdbheader *dh =
309 (struct lustre_disk_dqdbheader *)buf;
312 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);
313 dh->dqdh_prev_free = cpu_to_le32(0);
314 dh->dqdh_entries = cpu_to_le16(0);
315 info->dqi_free_blk = blk;
316 lustre_mark_info_dirty(info);
317 if ((err = write_blk(filp, blk, buf)) < 0)
318 /* Some strange block. We had better leave it... */
324 * Remove given block from the list of blocks with free entries
326 int remove_free_dqentry(struct file *filp,
327 struct lustre_mem_dqinfo *info, dqbuf_t buf,
330 dqbuf_t tmpbuf = getdqbuf();
331 struct lustre_disk_dqdbheader *dh =
332 (struct lustre_disk_dqdbheader *)buf;
333 uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk =
334 le32_to_cpu(dh->dqdh_prev_free);
340 if ((err = read_blk(filp, NULL, 0, nextblk, tmpbuf)) < 0)
342 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
344 if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
348 if ((err = read_blk(filp, NULL, 0, prevblk, tmpbuf)) < 0)
350 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
352 if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
355 info->dqi_free_entry = nextblk;
356 lustre_mark_info_dirty(info);
359 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
360 if (write_blk(filp, blk, buf) < 0)
361 /* No matter whether write succeeds block is out of list */
363 "VFS: Can't write block (%u) with free entries.\n", blk);
371 * Insert given block to the beginning of list with free entries
373 int insert_free_dqentry(struct file *filp,
374 struct lustre_mem_dqinfo *info, dqbuf_t buf,
377 dqbuf_t tmpbuf = getdqbuf();
378 struct lustre_disk_dqdbheader *dh =
379 (struct lustre_disk_dqdbheader *)buf;
384 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);
385 dh->dqdh_prev_free = cpu_to_le32(0);
386 if ((err = write_blk(filp, blk, buf)) < 0)
388 if (info->dqi_free_entry) {
389 if ((err = read_blk(filp, NULL, 0, info->dqi_free_entry, tmpbuf)) < 0)
391 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
393 if ((err = write_blk(filp, info->dqi_free_entry, tmpbuf)) < 0)
397 info->dqi_free_entry = blk;
398 lustre_mark_info_dirty(info);
408 * Find space for dquot
410 static uint find_free_dqentry(struct lustre_dquot *dquot, int *err,
411 lustre_quota_version_t version)
413 struct lustre_quota_info *lqi = dquot->dq_info;
414 struct file *filp = lqi->qi_files[dquot->dq_type];
415 struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];
417 struct lustre_disk_dqdbheader *dh;
419 int dqblk_sz = lustre_disk_dqblk_sz[version];
420 int dqstrinblk = lustre_dqstrinblk[version];
424 if (!(buf = getdqbuf())) {
428 dh = (struct lustre_disk_dqdbheader *)buf;
429 ddquot = GETENTRIES(buf, version);
430 if (info->dqi_free_entry) {
431 blk = info->dqi_free_entry;
432 if ((*err = read_blk(filp, NULL, 0, blk, buf)) < 0)
435 blk = get_free_dqblk(filp, info);
441 memset(buf, 0, LUSTRE_DQBLKSIZE);
442 info->dqi_free_entry = blk; /* This is enough as block is
443 already zeroed and entry list
445 lustre_mark_info_dirty(info);
448 /* Will block be full */
449 if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk)
450 if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
452 "VFS: find_free_dqentry(): Can't remove block "
453 "(%u) from entry free list.\n", blk);
456 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) + 1);
457 /* Find free structure in block */
458 for (i = 0; i < dqstrinblk &&
459 memcmp((char *)&emptydquot[version],
460 (char *)ddquot + i * dqblk_sz, dqblk_sz);
463 if (i == dqstrinblk) {
465 "VFS: find_free_dqentry(): Data block full but it "
471 if ((*err = write_blk(filp, blk, buf)) < 0) {
473 "VFS: find_free_dqentry(): Can't write quota data "
478 (blk << LUSTRE_DQBLKSIZE_BITS) +
479 sizeof(struct lustre_disk_dqdbheader) +
489 * Insert reference to structure into the trie
491 static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth,
492 lustre_quota_version_t version)
494 struct lustre_quota_info *lqi = dquot->dq_info;
495 struct file *filp = lqi->qi_files[dquot->dq_type];
496 struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];
498 int ret = 0, newson = 0, newact = 0;
502 if (!(buf = getdqbuf()))
505 ret = get_free_dqblk(filp, info);
509 memset(buf, 0, LUSTRE_DQBLKSIZE);
512 if ((ret = read_blk(filp, NULL, 0, *treeblk, buf)) < 0) {
513 CERROR("VFS: Can't read tree quota block %u.\n",
519 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
522 if (depth == LUSTRE_DQTREEDEPTH - 1) {
526 "VFS: Inserting already present quota entry "
528 ref[GETIDINDEX(dquot->dq_id, depth)]);
533 newblk = find_free_dqentry(dquot, &ret, version);
535 ret = do_insert_tree(dquot, &newblk, depth + 1, version);
536 if (newson && ret >= 0) {
537 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
538 ret = write_blk(filp, *treeblk, buf);
539 } else if (newact && ret < 0)
540 put_free_dqblk(filp, info, buf, *treeblk);
547 * Wrapper for inserting quota structure into tree
549 static inline int dq_insert_tree(struct lustre_dquot *dquot,
550 lustre_quota_version_t version)
552 int tmp = LUSTRE_DQTREEOFF;
553 return do_insert_tree(dquot, &tmp, 0, version);
557 * We don't have to be afraid of deadlocks as we never have quotas on
560 static int lustre_write_dquot(struct lustre_dquot *dquot,
561 lustre_quota_version_t version)
563 int type = dquot->dq_type;
567 int dqblk_sz = lustre_disk_dqblk_sz[version];
568 struct lustre_disk_dqblk_v2 ddquot;
570 ret = mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, version);
575 if ((ret = dq_insert_tree(dquot, version)) < 0) {
577 "VFS: Error %Zd occurred while creating "
581 filp = dquot->dq_info->qi_files[type];
582 offset = dquot->dq_off;
583 /* Argh... We may need to write structure full of zeroes but that would
584 * be treated as an empty place by the rest of the code. Format change
585 * would be definitely cleaner but the problems probably are not worth
587 if (!memcmp((char *)&emptydquot[version], (char *)&ddquot, dqblk_sz))
588 ddquot.dqb_itime = cpu_to_le64(1);
590 ret = lustre_write_quota(filp, (char *)&ddquot, dqblk_sz, offset);
591 if (ret != dqblk_sz) {
592 CDEBUG(D_WARNING, "VFS: dquota write failed on dev %s\n",
593 filp->f_dentry->d_sb->s_id);
603 * Free dquot entry in data block
605 static int free_dqentry(struct lustre_dquot *dquot, uint blk,
606 lustre_quota_version_t version)
608 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
609 struct lustre_mem_dqinfo *info =
610 &dquot->dq_info->qi_info[dquot->dq_type];
611 struct lustre_disk_dqdbheader *dh;
612 dqbuf_t buf = getdqbuf();
613 int dqstrinblk = lustre_dqstrinblk[version];
618 if (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS != blk) {
620 "VFS: Quota structure has offset to other block (%u) "
621 "than it should (%u).\n",
622 blk, (uint) (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS));
625 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
626 CDEBUG(D_ERROR, "VFS: Can't read quota data block %u\n", blk);
629 dh = (struct lustre_disk_dqdbheader *)buf;
630 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) - 1);
631 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
632 if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
633 (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
635 "VFS: Can't move quota data block (%u) to free "
640 memset(buf + (dquot->dq_off & ((1<<LUSTRE_DQBLKSIZE_BITS) - 1)),
641 0, lustre_disk_dqblk_sz[version]);
642 if (le16_to_cpu(dh->dqdh_entries) == dqstrinblk - 1) {
643 /* Insert will write block itself */
645 insert_free_dqentry(filp, info, buf, blk)) < 0) {
647 "VFS: Can't insert quota data block "
648 "(%u) to free entry list.\n", blk);
651 } else if ((ret = write_blk(filp, blk, buf)) < 0) {
653 "VFS: Can't write quota data block %u\n", blk);
657 dquot->dq_off = 0; /* Quota is now unattached */
664 * Remove reference to dquot from tree
666 static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth,
667 lustre_quota_version_t version)
669 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
670 struct lustre_mem_dqinfo *info =
671 &dquot->dq_info->qi_info[dquot->dq_type];
672 dqbuf_t buf = getdqbuf();
675 u32 *ref = (u32 *) buf;
679 if ((ret = read_blk(filp, NULL, 0, *blk, buf)) < 0) {
680 CERROR("VFS: Can't read quota data block %u\n", *blk);
683 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
684 if (depth == LUSTRE_DQTREEDEPTH - 1) {
685 ret = free_dqentry(dquot, newblk, version);
688 ret = remove_tree(dquot, &newblk, depth + 1, version);
689 if (ret >= 0 && !newblk) {
691 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
692 for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++)
693 /* Block got empty? */ ;
694 /* don't put the root block into free blk list! */
695 if (i == LUSTRE_DQBLKSIZE && *blk != LUSTRE_DQTREEOFF) {
696 put_free_dqblk(filp, info, buf, *blk);
698 } else if ((ret = write_blk(filp, *blk, buf)) < 0)
700 "VFS: Can't write quota tree block %u.\n", *blk);
708 * Delete dquot from tree
710 static int lustre_delete_dquot(struct lustre_dquot *dquot,
711 lustre_quota_version_t version)
713 uint tmp = LUSTRE_DQTREEOFF;
715 if (!dquot->dq_off) /* Even not allocated? */
717 return remove_tree(dquot, &tmp, 0, version);
721 * Find entry in block
723 static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk,
724 lustre_quota_version_t version)
726 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
727 dqbuf_t buf = getdqbuf();
730 struct lustre_disk_dqblk_v2 *ddquot =
731 (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
732 int dqblk_sz = lustre_disk_dqblk_sz[version];
733 int dqstrinblk = lustre_dqstrinblk[version];
735 LASSERT(version == LUSTRE_QUOTA_V2);
739 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
740 CERROR("VFS: Can't read quota tree block %u.\n", blk);
744 for (i = 0; i < dqstrinblk &&
745 le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id;
747 else { /* ID 0 as a bit more complicated searching... */
748 for (i = 0; i < dqstrinblk; i++)
749 if (!le32_to_cpu(ddquot[i].dqb_id)
750 && memcmp((char *)&emptydquot[version],
751 (char *)&ddquot[i], dqblk_sz))
754 if (i == dqstrinblk) {
756 "VFS: Quota for id %u referenced but not present.\n",
762 (blk << LUSTRE_DQBLKSIZE_BITS) +
763 sizeof(struct lustre_disk_dqdbheader) +
771 * Find entry for given id in the tree
773 static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth,
774 lustre_quota_version_t version)
776 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
777 dqbuf_t buf = getdqbuf();
779 u32 *ref = (u32 *) buf;
783 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
784 CERROR("VFS: Can't read quota tree block %u.\n", blk);
788 blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
789 if (!blk) /* No reference? */
791 if (depth < LUSTRE_DQTREEDEPTH - 1)
792 ret = find_tree_dqentry(dquot, blk, depth + 1, version);
794 ret = find_block_dqentry(dquot, blk, version);
801 * Find entry for given id in the tree - wrapper function
803 static inline loff_t find_dqentry(struct lustre_dquot *dquot,
804 lustre_quota_version_t version)
806 return find_tree_dqentry(dquot, LUSTRE_DQTREEOFF, 0, version);
809 int lustre_read_dquot(struct lustre_dquot *dquot)
811 int type = dquot->dq_type;
814 int ret = 0, dqblk_sz;
815 lustre_quota_version_t version;
817 /* Invalidated quota? */
818 if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) {
819 CDEBUG(D_ERROR, "VFS: Quota invalidated while reading!\n");
823 version = dquot->dq_info->qi_version;
824 LASSERT(version == LUSTRE_QUOTA_V2);
825 dqblk_sz = lustre_disk_dqblk_sz[version];
827 offset = find_dqentry(dquot, version);
828 if (offset <= 0) { /* Entry not present? */
831 "VFS: Can't read quota structure for id %u.\n",
834 cfs_set_bit(DQ_FAKE_B, &dquot->dq_flags);
835 memset(&dquot->dq_dqb, 0, sizeof(struct lustre_mem_dqblk));
838 struct lustre_disk_dqblk_v2 ddquot;
840 dquot->dq_off = offset;
841 if ((ret = lustre_read_quota(filp, NULL, type, (char *)&ddquot,
842 dqblk_sz, offset)) != dqblk_sz) {
846 "VFS: Error while reading quota structure for id "
847 "%u.\n", dquot->dq_id);
848 memset((char *)&ddquot, 0, dqblk_sz);
851 /* We need to escape back all-zero structure */
852 if (!memcmp((char *)&fakedquot[version],
853 (char *)&ddquot, dqblk_sz))
854 ddquot.dqb_itime = cpu_to_le64(0);
856 disk2memdqb(&dquot->dq_dqb, &ddquot, version);
861 EXPORT_SYMBOL(lustre_read_dquot);
864 * Commit changes of dquot to disk - it might also mean deleting
865 * it when quota became fake.
867 int lustre_commit_dquot(struct lustre_dquot *dquot)
870 lustre_quota_version_t version = dquot->dq_info->qi_version;
872 struct inode *inode = dquot->dq_info->qi_files[dquot->dq_type]->f_dentry->d_inode;
875 /* always clear the flag so we don't loop on an IO error... */
876 cfs_clear_bit(DQ_MOD_B, &dquot->dq_flags);
878 /* The block/inode usage in admin quotafile isn't the real usage
879 * over all cluster, so keep the fake dquot entry on disk is
880 * meaningless, just remove it */
881 if (cfs_test_bit(DQ_FAKE_B, &dquot->dq_flags))
883 handle = lustre_quota_journal_start(inode, delete);
884 if (unlikely(IS_ERR(handle))) {
885 rc = PTR_ERR(handle);
886 CERROR("fail to lustre_quota_journal_start: rc = %d\n", rc);
891 rc = lustre_delete_dquot(dquot, version);
893 rc = lustre_write_dquot(dquot, version);
894 lustre_quota_journal_stop(handle);
899 if (lustre_info_dirty(&dquot->dq_info->qi_info[dquot->dq_type]))
900 rc = lustre_write_quota_info(dquot->dq_info, dquot->dq_type);
904 EXPORT_SYMBOL(lustre_commit_dquot);
906 int lustre_init_quota_header(struct lustre_quota_info *lqi, int type,
909 static const uint quota_magics[] = LUSTRE_INITQMAGICS;
910 static const uint fake_magics[] = LUSTRE_BADQMAGICS;
911 const uint* quota_versions = lustre_initqversions[lqi->qi_version];
912 struct lustre_disk_dqheader dqhead;
914 struct file *fp = lqi->qi_files[type];
917 /* write quotafile header */
918 dqhead.dqh_magic = cpu_to_le32(fakemagics ?
919 fake_magics[type] : quota_magics[type]);
920 dqhead.dqh_version = cpu_to_le32(quota_versions[type]);
921 size = lustre_write_quota(fp, (char *)&dqhead,
922 sizeof(struct lustre_disk_dqheader), 0);
924 if (size != sizeof(struct lustre_disk_dqheader)) {
925 CDEBUG(D_ERROR, "error writing quoafile header (rc:%d)\n", rc);
933 * We need to export this function to initialize quotafile, because we haven't
934 * user level check utility
936 int lustre_init_quota_info_generic(struct lustre_quota_info *lqi, int type,
939 struct lustre_mem_dqinfo *dqinfo = &lqi->qi_info[type];
942 rc = lustre_init_quota_header(lqi, type, fakemagics);
946 /* write init quota info */
947 memset(dqinfo, 0, sizeof(*dqinfo));
948 dqinfo->dqi_bgrace = MAX_DQ_TIME;
949 dqinfo->dqi_igrace = MAX_IQ_TIME;
950 dqinfo->dqi_blocks = LUSTRE_DQTREEOFF + 1;
952 return lustre_write_quota_info(lqi, type);
955 int lustre_init_quota_info(struct lustre_quota_info *lqi, int type)
957 return lustre_init_quota_info_generic(lqi, type, 0);
959 EXPORT_SYMBOL(lustre_init_quota_info);
961 static int walk_block_dqentry(struct file *filp, struct inode *inode, int type,
962 uint blk, cfs_list_t *list)
964 dqbuf_t buf = getdqbuf();
966 struct lustre_disk_dqdbheader *dqhead =
967 (struct lustre_disk_dqdbheader *)buf;
968 struct dqblk *blk_item;
974 if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
975 CERROR("VFS: Can't read quota tree block %u.\n", blk);
980 if (!le32_to_cpu(dqhead->dqdh_entries))
983 if (cfs_list_empty(list)) {
988 cfs_list_for_each_entry(pos, list, link) {
989 if (blk == pos->blk) /* we got this blk already */
997 blk_item = kmalloc(sizeof(*blk_item), GFP_NOFS);
1002 blk_item->blk = blk;
1003 CFS_INIT_LIST_HEAD(&blk_item->link);
1005 cfs_list_add_tail(&blk_item->link, tmp);
1012 int walk_tree_dqentry(struct file *filp, struct inode *inode, int type,
1013 uint blk, int depth, cfs_list_t *list)
1015 dqbuf_t buf = getdqbuf();
1018 u32 *ref = (u32 *) buf;
1022 if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
1023 CERROR("VFS: Can't read quota tree block %u.\n", blk);
1028 for (index = 0; index <= 0xff && !ret; index++) {
1029 blk = le32_to_cpu(ref[index]);
1030 if (!blk) /* No reference */
1033 if (depth < LUSTRE_DQTREEDEPTH - 1)
1034 ret = walk_tree_dqentry(filp, inode, type, blk,
1037 ret = walk_block_dqentry(filp, inode, type, blk, list);
1045 * Walk through the quota file (v2 format) to get all ids with quota limit
1047 int lustre_get_qids(struct file *fp, struct inode *inode, int type,
1050 cfs_list_t blk_list;
1051 struct dqblk *blk_item, *tmp;
1053 struct lustre_disk_dqblk_v2 *ddquot;
1055 lustre_quota_version_t version;
1059 LASSERT(ergo(fp == NULL, inode != NULL));
1061 if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V2) == 0)
1062 version = LUSTRE_QUOTA_V2;
1064 CDEBUG(D_ERROR, "unknown quota file format!\n");
1068 if (!cfs_list_empty(list)) {
1069 CDEBUG(D_ERROR, "not empty list\n");
1073 CFS_INIT_LIST_HEAD(&blk_list);
1074 rc = walk_tree_dqentry(fp, inode, type, LUSTRE_DQTREEOFF, 0, &blk_list);
1076 CDEBUG(D_ERROR, "walk through quota file failed!(%d)\n", rc);
1079 if (cfs_list_empty(&blk_list))
1085 ddquot = (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
1087 cfs_list_for_each_entry(blk_item, &blk_list, link) {
1089 int i, dqblk_sz = lustre_disk_dqblk_sz[version];
1091 memset(buf, 0, LUSTRE_DQBLKSIZE);
1092 if ((ret = read_blk(fp, inode, type, blk_item->blk, buf)) < 0) {
1093 CERROR("VFS: Can't read quota tree block %u.\n",
1095 GOTO(out_free, rc = ret);
1098 for (i = 0; i < lustre_dqstrinblk[version]; i++) {
1099 struct dquot_id *dqid;
1100 /* skip empty entry */
1101 if (!memcmp((char *)&emptydquot[version],
1102 (char *)&ddquot[i], dqblk_sz))
1105 OBD_ALLOC_GFP(dqid, sizeof(*dqid), GFP_NOFS);
1107 GOTO(out_free, rc = -ENOMEM);
1109 dqid->di_id = le32_to_cpu(ddquot[i].dqb_id);
1110 dqid->di_flag = le64_to_cpu(ddquot[i].dqb_ihardlimit) ?
1112 dqid->di_flag |= le64_to_cpu(ddquot[i].dqb_bhardlimit) ?
1115 CFS_INIT_LIST_HEAD(&dqid->di_link);
1116 cfs_list_add(&dqid->di_link, list);
1121 cfs_list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
1122 cfs_list_del_init(&blk_item->link);
1130 EXPORT_SYMBOL(lustre_get_qids);