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
40 #include <linux/errno.h>
42 #include <linux/mount.h>
43 #include <linux/kernel.h>
44 #include <linux/init.h>
45 #include <linux/module.h>
46 #include <linux/slab.h>
47 #ifdef HAVE_QUOTAIO_V1_H
48 # include <linux/quotaio_v1.h>
51 #include <asm/byteorder.h>
52 #include <asm/uaccess.h>
54 #include <lustre_quota.h>
55 #include <obd_support.h>
56 #include "lustre_quota_fmt.h"
58 #ifdef HAVE_QUOTA_SUPPORT
60 static const uint lustre_initqversions[][MAXQUOTAS] = {
61 [LUSTRE_QUOTA_V2] = LUSTRE_INITQVERSIONS_V2
64 static const int lustre_dqstrinblk[] = {
65 [LUSTRE_QUOTA_V2] = LUSTRE_DQSTRINBLK_V2
68 static const int lustre_disk_dqblk_sz[] = {
69 [LUSTRE_QUOTA_V2] = sizeof(struct lustre_disk_dqblk_v2)
74 struct lustre_disk_dqblk_v2 r1;
76 [LUSTRE_QUOTA_V2] = {.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)}}
81 struct lustre_disk_dqblk_v2 r1;
83 [LUSTRE_QUOTA_V2] = {.r1 = { 0 }}
86 extern void *lustre_quota_journal_start(struct inode *inode, int delete);
87 extern void lustre_quota_journal_stop(void *handle);
88 extern ssize_t lustre_read_quota(struct file *f, struct inode *inode, int type,
89 char *buf, int count, loff_t pos);
90 extern ssize_t lustre_write_quota(struct file *f, char *buf, int count, loff_t pos);
92 int check_quota_file(struct file *f, struct inode *inode, int type,
93 lustre_quota_version_t version)
95 struct lustre_disk_dqheader dqhead;
97 static const uint quota_magics[] = LUSTRE_INITQMAGICS;
98 const uint *quota_versions = lustre_initqversions[version];
100 size = lustre_read_quota(f, inode, type, (char *)&dqhead,
101 sizeof(struct lustre_disk_dqheader), 0);
102 if (size != sizeof(struct lustre_disk_dqheader))
104 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
105 le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
111 * Check whether given file is really lustre admin quotafile
113 int lustre_check_quota_file(struct lustre_quota_info *lqi, int type)
115 struct file *f = lqi->qi_files[type];
116 return check_quota_file(f, NULL, type, lqi->qi_version);
118 EXPORT_SYMBOL(lustre_check_quota_file);
120 int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info)
122 struct lustre_disk_dqinfo dinfo;
125 size = lustre_read_quota(f, NULL, 0, (char *)&dinfo,
126 sizeof(struct lustre_disk_dqinfo),
129 if (size != sizeof(struct lustre_disk_dqinfo)) {
130 CDEBUG(D_ERROR, "Can't read info structure on device %s.\n",
131 f->f_vfsmnt->mnt_sb->s_id);
134 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
135 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
136 info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
137 info->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
138 info->dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
139 info->dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
144 * Read information header from quota file
146 int lustre_read_quota_info(struct lustre_quota_info *lqi, int type)
148 return lustre_read_quota_file_info(lqi->qi_files[type],
149 &lqi->qi_info[type]);
151 EXPORT_SYMBOL(lustre_read_quota_info);
154 * Write information header to quota file
156 int lustre_write_quota_info(struct lustre_quota_info *lqi, int type)
158 struct lustre_disk_dqinfo dinfo;
159 struct lustre_mem_dqinfo *info = &lqi->qi_info[type];
160 struct file *f = lqi->qi_files[type];
163 info->dqi_flags &= ~DQF_INFO_DIRTY;
164 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
165 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
166 dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
167 dinfo.dqi_blocks = cpu_to_le32(info->dqi_blocks);
168 dinfo.dqi_free_blk = cpu_to_le32(info->dqi_free_blk);
169 dinfo.dqi_free_entry = cpu_to_le32(info->dqi_free_entry);
171 size = lustre_write_quota(f, (char *)&dinfo,
172 sizeof(struct lustre_disk_dqinfo),
175 if (size != sizeof(struct lustre_disk_dqinfo)) {
177 "Can't write info structure on device %s.\n",
178 f->f_vfsmnt->mnt_sb->s_id);
183 EXPORT_SYMBOL(lustre_write_quota_info);
185 void disk2memdqb(struct lustre_mem_dqblk *m, void *d,
186 lustre_quota_version_t version)
188 struct lustre_disk_dqblk_v2 *dqblk = (struct lustre_disk_dqblk_v2 *)d;
190 LASSERT(version == LUSTRE_QUOTA_V2);
192 m->dqb_ihardlimit = le64_to_cpu(dqblk->dqb_ihardlimit);
193 m->dqb_isoftlimit = le64_to_cpu(dqblk->dqb_isoftlimit);
194 m->dqb_curinodes = le64_to_cpu(dqblk->dqb_curinodes);
195 m->dqb_itime = le64_to_cpu(dqblk->dqb_itime);
196 m->dqb_bhardlimit = le64_to_cpu(dqblk->dqb_bhardlimit);
197 m->dqb_bsoftlimit = le64_to_cpu(dqblk->dqb_bsoftlimit);
198 m->dqb_curspace = le64_to_cpu(dqblk->dqb_curspace);
199 m->dqb_btime = le64_to_cpu(dqblk->dqb_btime);
202 static int mem2diskdqb(void *d, struct lustre_mem_dqblk *m,
203 qid_t id, lustre_quota_version_t version)
205 struct lustre_disk_dqblk_v2 *dqblk = (struct lustre_disk_dqblk_v2 *)d;
207 LASSERT(version == LUSTRE_QUOTA_V2);
209 dqblk->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
210 dqblk->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
211 dqblk->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
212 dqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
213 dqblk->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
214 dqblk->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
215 dqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
216 dqblk->dqb_btime = cpu_to_le64(m->dqb_btime);
217 dqblk->dqb_id = cpu_to_le32(id);
222 dqbuf_t getdqbuf(void)
224 dqbuf_t buf = kmalloc(LUSTRE_DQBLKSIZE, GFP_NOFS);
227 "VFS: Not enough memory for quota buffers.\n");
231 void freedqbuf(dqbuf_t buf)
236 ssize_t read_blk(struct file *filp, struct inode *inode, int type,
237 uint blk, dqbuf_t buf)
241 memset(buf, 0, LUSTRE_DQBLKSIZE);
242 ret = lustre_read_quota(filp, inode, type, (char *)buf, LUSTRE_DQBLKSIZE,
243 blk << LUSTRE_DQBLKSIZE_BITS);
245 /* Reading past EOF just returns a block of zeros */
252 ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
256 ret = lustre_write_quota(filp, (char *)buf, LUSTRE_DQBLKSIZE,
257 blk << LUSTRE_DQBLKSIZE_BITS);
262 void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info)
264 cfs_set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
268 * Remove empty block from list and return it
270 int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info)
272 dqbuf_t buf = getdqbuf();
273 struct lustre_disk_dqdbheader *dh =
274 (struct lustre_disk_dqdbheader *)buf;
279 if (info->dqi_free_blk) {
280 blk = info->dqi_free_blk;
281 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0)
283 info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
285 memset(buf, 0, LUSTRE_DQBLKSIZE);
286 /* Assure block allocation... */
287 if ((ret = write_blk(filp, info->dqi_blocks, buf)) < 0)
289 blk = info->dqi_blocks++;
291 lustre_mark_info_dirty(info);
299 * Insert empty block to the list
301 int put_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info,
302 dqbuf_t buf, uint blk)
304 struct lustre_disk_dqdbheader *dh =
305 (struct lustre_disk_dqdbheader *)buf;
308 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);
309 dh->dqdh_prev_free = cpu_to_le32(0);
310 dh->dqdh_entries = cpu_to_le16(0);
311 info->dqi_free_blk = blk;
312 lustre_mark_info_dirty(info);
313 if ((err = write_blk(filp, blk, buf)) < 0)
314 /* Some strange block. We had better leave it... */
320 * Remove given block from the list of blocks with free entries
322 int remove_free_dqentry(struct file *filp,
323 struct lustre_mem_dqinfo *info, dqbuf_t buf,
326 dqbuf_t tmpbuf = getdqbuf();
327 struct lustre_disk_dqdbheader *dh =
328 (struct lustre_disk_dqdbheader *)buf;
329 uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk =
330 le32_to_cpu(dh->dqdh_prev_free);
336 if ((err = read_blk(filp, NULL, 0, nextblk, tmpbuf)) < 0)
338 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
340 if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
344 if ((err = read_blk(filp, NULL, 0, prevblk, tmpbuf)) < 0)
346 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
348 if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
351 info->dqi_free_entry = nextblk;
352 lustre_mark_info_dirty(info);
355 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
356 if (write_blk(filp, blk, buf) < 0)
357 /* No matter whether write succeeds block is out of list */
359 "VFS: Can't write block (%u) with free entries.\n", blk);
367 * Insert given block to the beginning of list with free entries
369 int insert_free_dqentry(struct file *filp,
370 struct lustre_mem_dqinfo *info, dqbuf_t buf,
373 dqbuf_t tmpbuf = getdqbuf();
374 struct lustre_disk_dqdbheader *dh =
375 (struct lustre_disk_dqdbheader *)buf;
380 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);
381 dh->dqdh_prev_free = cpu_to_le32(0);
382 if ((err = write_blk(filp, blk, buf)) < 0)
384 if (info->dqi_free_entry) {
385 if ((err = read_blk(filp, NULL, 0, info->dqi_free_entry, tmpbuf)) < 0)
387 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
389 if ((err = write_blk(filp, info->dqi_free_entry, tmpbuf)) < 0)
393 info->dqi_free_entry = blk;
394 lustre_mark_info_dirty(info);
404 * Find space for dquot
406 static uint find_free_dqentry(struct lustre_dquot *dquot, int *err,
407 lustre_quota_version_t version)
409 struct lustre_quota_info *lqi = dquot->dq_info;
410 struct file *filp = lqi->qi_files[dquot->dq_type];
411 struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];
413 struct lustre_disk_dqdbheader *dh;
415 int dqblk_sz = lustre_disk_dqblk_sz[version];
416 int dqstrinblk = lustre_dqstrinblk[version];
420 if (!(buf = getdqbuf())) {
424 dh = (struct lustre_disk_dqdbheader *)buf;
425 ddquot = GETENTRIES(buf, version);
426 if (info->dqi_free_entry) {
427 blk = info->dqi_free_entry;
428 if ((*err = read_blk(filp, NULL, 0, blk, buf)) < 0)
431 blk = get_free_dqblk(filp, info);
437 memset(buf, 0, LUSTRE_DQBLKSIZE);
438 info->dqi_free_entry = blk; /* This is enough as block is
439 already zeroed and entry list
441 lustre_mark_info_dirty(info);
444 /* Will block be full */
445 if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk)
446 if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
448 "VFS: find_free_dqentry(): Can't remove block "
449 "(%u) from entry free list.\n", blk);
452 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) + 1);
453 /* Find free structure in block */
454 for (i = 0; i < dqstrinblk &&
455 memcmp((char *)&emptydquot[version],
456 (char *)ddquot + i * dqblk_sz, dqblk_sz);
459 if (i == dqstrinblk) {
461 "VFS: find_free_dqentry(): Data block full but it "
467 if ((*err = write_blk(filp, blk, buf)) < 0) {
469 "VFS: find_free_dqentry(): Can't write quota data "
474 (blk << LUSTRE_DQBLKSIZE_BITS) +
475 sizeof(struct lustre_disk_dqdbheader) +
485 * Insert reference to structure into the trie
487 static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth,
488 lustre_quota_version_t version)
490 struct lustre_quota_info *lqi = dquot->dq_info;
491 struct file *filp = lqi->qi_files[dquot->dq_type];
492 struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];
494 int ret = 0, newson = 0, newact = 0;
498 if (!(buf = getdqbuf()))
501 ret = get_free_dqblk(filp, info);
505 memset(buf, 0, LUSTRE_DQBLKSIZE);
508 if ((ret = read_blk(filp, NULL, 0, *treeblk, buf)) < 0) {
509 CERROR("VFS: Can't read tree quota block %u.\n",
515 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
518 if (depth == LUSTRE_DQTREEDEPTH - 1) {
522 "VFS: Inserting already present quota entry "
524 ref[GETIDINDEX(dquot->dq_id, depth)]);
529 newblk = find_free_dqentry(dquot, &ret, version);
531 ret = do_insert_tree(dquot, &newblk, depth + 1, version);
532 if (newson && ret >= 0) {
533 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
534 ret = write_blk(filp, *treeblk, buf);
535 } else if (newact && ret < 0)
536 put_free_dqblk(filp, info, buf, *treeblk);
543 * Wrapper for inserting quota structure into tree
545 static inline int dq_insert_tree(struct lustre_dquot *dquot,
546 lustre_quota_version_t version)
548 int tmp = LUSTRE_DQTREEOFF;
549 return do_insert_tree(dquot, &tmp, 0, version);
553 * We don't have to be afraid of deadlocks as we never have quotas on
556 static int lustre_write_dquot(struct lustre_dquot *dquot,
557 lustre_quota_version_t version)
559 int type = dquot->dq_type;
563 int dqblk_sz = lustre_disk_dqblk_sz[version];
564 struct lustre_disk_dqblk_v2 ddquot;
566 ret = mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, version);
571 if ((ret = dq_insert_tree(dquot, version)) < 0) {
573 "VFS: Error %Zd occurred while creating "
577 filp = dquot->dq_info->qi_files[type];
578 offset = dquot->dq_off;
579 /* Argh... We may need to write structure full of zeroes but that would
580 * be treated as an empty place by the rest of the code. Format change
581 * would be definitely cleaner but the problems probably are not worth
583 if (!memcmp((char *)&emptydquot[version], (char *)&ddquot, dqblk_sz))
584 ddquot.dqb_itime = cpu_to_le64(1);
586 ret = lustre_write_quota(filp, (char *)&ddquot, dqblk_sz, offset);
587 if (ret != dqblk_sz) {
588 CDEBUG(D_WARNING, "VFS: dquota write failed on dev %s\n",
589 filp->f_dentry->d_sb->s_id);
599 * Free dquot entry in data block
601 static int free_dqentry(struct lustre_dquot *dquot, uint blk,
602 lustre_quota_version_t version)
604 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
605 struct lustre_mem_dqinfo *info =
606 &dquot->dq_info->qi_info[dquot->dq_type];
607 struct lustre_disk_dqdbheader *dh;
608 dqbuf_t buf = getdqbuf();
609 int dqstrinblk = lustre_dqstrinblk[version];
614 if (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS != blk) {
616 "VFS: Quota structure has offset to other block (%u) "
617 "than it should (%u).\n",
618 blk, (uint) (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS));
621 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
622 CDEBUG(D_ERROR, "VFS: Can't read quota data block %u\n", blk);
625 dh = (struct lustre_disk_dqdbheader *)buf;
626 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) - 1);
627 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
628 if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
629 (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
631 "VFS: Can't move quota data block (%u) to free "
636 memset(buf + (dquot->dq_off & ((1<<LUSTRE_DQBLKSIZE_BITS) - 1)),
637 0, lustre_disk_dqblk_sz[version]);
638 if (le16_to_cpu(dh->dqdh_entries) == dqstrinblk - 1) {
639 /* Insert will write block itself */
641 insert_free_dqentry(filp, info, buf, blk)) < 0) {
643 "VFS: Can't insert quota data block "
644 "(%u) to free entry list.\n", blk);
647 } else if ((ret = write_blk(filp, blk, buf)) < 0) {
649 "VFS: Can't write quota data block %u\n", blk);
653 dquot->dq_off = 0; /* Quota is now unattached */
660 * Remove reference to dquot from tree
662 static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth,
663 lustre_quota_version_t version)
665 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
666 struct lustre_mem_dqinfo *info =
667 &dquot->dq_info->qi_info[dquot->dq_type];
668 dqbuf_t buf = getdqbuf();
671 u32 *ref = (u32 *) buf;
675 if ((ret = read_blk(filp, NULL, 0, *blk, buf)) < 0) {
676 CERROR("VFS: Can't read quota data block %u\n", *blk);
679 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
680 if (depth == LUSTRE_DQTREEDEPTH - 1) {
681 ret = free_dqentry(dquot, newblk, version);
684 ret = remove_tree(dquot, &newblk, depth + 1, version);
685 if (ret >= 0 && !newblk) {
687 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
688 for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++)
689 /* Block got empty? */ ;
690 /* don't put the root block into free blk list! */
691 if (i == LUSTRE_DQBLKSIZE && *blk != LUSTRE_DQTREEOFF) {
692 put_free_dqblk(filp, info, buf, *blk);
694 } else if ((ret = write_blk(filp, *blk, buf)) < 0)
696 "VFS: Can't write quota tree block %u.\n", *blk);
704 * Delete dquot from tree
706 static int lustre_delete_dquot(struct lustre_dquot *dquot,
707 lustre_quota_version_t version)
709 uint tmp = LUSTRE_DQTREEOFF;
711 if (!dquot->dq_off) /* Even not allocated? */
713 return remove_tree(dquot, &tmp, 0, version);
717 * Find entry in block
719 static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk,
720 lustre_quota_version_t version)
722 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
723 dqbuf_t buf = getdqbuf();
726 struct lustre_disk_dqblk_v2 *ddquot =
727 (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
728 int dqblk_sz = lustre_disk_dqblk_sz[version];
729 int dqstrinblk = lustre_dqstrinblk[version];
731 LASSERT(version == LUSTRE_QUOTA_V2);
735 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
736 CERROR("VFS: Can't read quota tree block %u.\n", blk);
740 for (i = 0; i < dqstrinblk &&
741 le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id;
743 else { /* ID 0 as a bit more complicated searching... */
744 for (i = 0; i < dqstrinblk; i++)
745 if (!le32_to_cpu(ddquot[i].dqb_id)
746 && memcmp((char *)&emptydquot[version],
747 (char *)&ddquot[i], dqblk_sz))
750 if (i == dqstrinblk) {
752 "VFS: Quota for id %u referenced but not present.\n",
758 (blk << LUSTRE_DQBLKSIZE_BITS) +
759 sizeof(struct lustre_disk_dqdbheader) +
767 * Find entry for given id in the tree
769 static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth,
770 lustre_quota_version_t version)
772 struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
773 dqbuf_t buf = getdqbuf();
775 u32 *ref = (u32 *) buf;
779 if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
780 CERROR("VFS: Can't read quota tree block %u.\n", blk);
784 blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
785 if (!blk) /* No reference? */
787 if (depth < LUSTRE_DQTREEDEPTH - 1)
788 ret = find_tree_dqentry(dquot, blk, depth + 1, version);
790 ret = find_block_dqentry(dquot, blk, version);
797 * Find entry for given id in the tree - wrapper function
799 static inline loff_t find_dqentry(struct lustre_dquot *dquot,
800 lustre_quota_version_t version)
802 return find_tree_dqentry(dquot, LUSTRE_DQTREEOFF, 0, version);
805 int lustre_read_dquot(struct lustre_dquot *dquot)
807 int type = dquot->dq_type;
810 int ret = 0, dqblk_sz;
811 lustre_quota_version_t version;
813 /* Invalidated quota? */
814 if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) {
815 CDEBUG(D_ERROR, "VFS: Quota invalidated while reading!\n");
819 version = dquot->dq_info->qi_version;
820 LASSERT(version == LUSTRE_QUOTA_V2);
821 dqblk_sz = lustre_disk_dqblk_sz[version];
823 offset = find_dqentry(dquot, version);
824 if (offset <= 0) { /* Entry not present? */
827 "VFS: Can't read quota structure for id %u.\n",
830 cfs_set_bit(DQ_FAKE_B, &dquot->dq_flags);
831 memset(&dquot->dq_dqb, 0, sizeof(struct lustre_mem_dqblk));
834 struct lustre_disk_dqblk_v2 ddquot;
836 dquot->dq_off = offset;
837 if ((ret = lustre_read_quota(filp, NULL, type, (char *)&ddquot,
838 dqblk_sz, offset)) != dqblk_sz) {
842 "VFS: Error while reading quota structure for id "
843 "%u.\n", dquot->dq_id);
844 memset((char *)&ddquot, 0, dqblk_sz);
847 /* We need to escape back all-zero structure */
848 if (!memcmp((char *)&fakedquot[version],
849 (char *)&ddquot, dqblk_sz))
850 ddquot.dqb_itime = cpu_to_le64(0);
852 disk2memdqb(&dquot->dq_dqb, &ddquot, version);
857 EXPORT_SYMBOL(lustre_read_dquot);
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);
900 EXPORT_SYMBOL(lustre_commit_dquot);
902 int lustre_init_quota_header(struct lustre_quota_info *lqi, int type,
905 static const uint quota_magics[] = LUSTRE_INITQMAGICS;
906 static const uint fake_magics[] = LUSTRE_BADQMAGICS;
907 const uint* quota_versions = lustre_initqversions[lqi->qi_version];
908 struct lustre_disk_dqheader dqhead;
910 struct file *fp = lqi->qi_files[type];
913 /* write quotafile header */
914 dqhead.dqh_magic = cpu_to_le32(fakemagics ?
915 fake_magics[type] : quota_magics[type]);
916 dqhead.dqh_version = cpu_to_le32(quota_versions[type]);
917 size = lustre_write_quota(fp, (char *)&dqhead,
918 sizeof(struct lustre_disk_dqheader), 0);
920 if (size != sizeof(struct lustre_disk_dqheader)) {
921 CDEBUG(D_ERROR, "error writing quoafile header (rc:%d)\n", rc);
929 * We need to export this function to initialize quotafile, because we haven't
930 * user level check utility
932 int lustre_init_quota_info_generic(struct lustre_quota_info *lqi, int type,
935 struct lustre_mem_dqinfo *dqinfo = &lqi->qi_info[type];
938 rc = lustre_init_quota_header(lqi, type, fakemagics);
942 /* write init quota info */
943 memset(dqinfo, 0, sizeof(*dqinfo));
944 dqinfo->dqi_bgrace = MAX_DQ_TIME;
945 dqinfo->dqi_igrace = MAX_IQ_TIME;
946 dqinfo->dqi_blocks = LUSTRE_DQTREEOFF + 1;
948 return lustre_write_quota_info(lqi, type);
951 int lustre_init_quota_info(struct lustre_quota_info *lqi, int type)
953 return lustre_init_quota_info_generic(lqi, type, 0);
955 EXPORT_SYMBOL(lustre_init_quota_info);
957 static int walk_block_dqentry(struct file *filp, struct inode *inode, int type,
958 uint blk, cfs_list_t *list)
960 dqbuf_t buf = getdqbuf();
962 struct lustre_disk_dqdbheader *dqhead =
963 (struct lustre_disk_dqdbheader *)buf;
964 struct dqblk *blk_item;
970 if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
971 CERROR("VFS: Can't read quota tree block %u.\n", blk);
976 if (!le32_to_cpu(dqhead->dqdh_entries))
979 if (cfs_list_empty(list)) {
984 cfs_list_for_each_entry(pos, list, link) {
985 if (blk == pos->blk) /* we got this blk already */
993 blk_item = kmalloc(sizeof(*blk_item), GFP_NOFS);
999 CFS_INIT_LIST_HEAD(&blk_item->link);
1001 cfs_list_add_tail(&blk_item->link, tmp);
1008 int walk_tree_dqentry(struct file *filp, struct inode *inode, int type,
1009 uint blk, int depth, cfs_list_t *list)
1011 dqbuf_t buf = getdqbuf();
1014 u32 *ref = (u32 *) buf;
1018 if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
1019 CERROR("VFS: Can't read quota tree block %u.\n", blk);
1024 for (index = 0; index <= 0xff && !ret; index++) {
1025 blk = le32_to_cpu(ref[index]);
1026 if (!blk) /* No reference */
1029 if (depth < LUSTRE_DQTREEDEPTH - 1)
1030 ret = walk_tree_dqentry(filp, inode, type, blk,
1033 ret = walk_block_dqentry(filp, inode, type, blk, list);
1041 * Walk through the quota file (v2 format) to get all ids with quota limit
1043 int lustre_get_qids(struct file *fp, struct inode *inode, int type,
1046 cfs_list_t blk_list;
1047 struct dqblk *blk_item, *tmp;
1049 struct lustre_disk_dqblk_v2 *ddquot;
1051 lustre_quota_version_t version;
1055 LASSERT(ergo(fp == NULL, inode != NULL));
1057 if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V2) == 0)
1058 version = LUSTRE_QUOTA_V2;
1060 CDEBUG(D_ERROR, "unknown quota file format!\n");
1064 if (!cfs_list_empty(list)) {
1065 CDEBUG(D_ERROR, "not empty list\n");
1069 CFS_INIT_LIST_HEAD(&blk_list);
1070 rc = walk_tree_dqentry(fp, inode, type, LUSTRE_DQTREEOFF, 0, &blk_list);
1072 CDEBUG(D_ERROR, "walk through quota file failed!(%d)\n", rc);
1075 if (cfs_list_empty(&blk_list))
1081 ddquot = (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
1083 cfs_list_for_each_entry(blk_item, &blk_list, link) {
1085 int i, dqblk_sz = lustre_disk_dqblk_sz[version];
1087 memset(buf, 0, LUSTRE_DQBLKSIZE);
1088 if ((ret = read_blk(fp, inode, type, blk_item->blk, buf)) < 0) {
1089 CERROR("VFS: Can't read quota tree block %u.\n",
1091 GOTO(out_free, rc = ret);
1094 for (i = 0; i < lustre_dqstrinblk[version]; i++) {
1095 struct dquot_id *dqid;
1096 /* skip empty entry */
1097 if (!memcmp((char *)&emptydquot[version],
1098 (char *)&ddquot[i], dqblk_sz))
1101 OBD_ALLOC_GFP(dqid, sizeof(*dqid), CFS_ALLOC_NOFS);
1103 GOTO(out_free, rc = -ENOMEM);
1105 dqid->di_id = le32_to_cpu(ddquot[i].dqb_id);
1106 dqid->di_flag = le64_to_cpu(ddquot[i].dqb_ihardlimit) ?
1108 dqid->di_flag |= le64_to_cpu(ddquot[i].dqb_bhardlimit) ?
1111 CFS_INIT_LIST_HEAD(&dqid->di_link);
1112 cfs_list_add(&dqid->di_link, list);
1117 cfs_list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
1118 cfs_list_del_init(&blk_item->link);
1126 EXPORT_SYMBOL(lustre_get_qids);