1 /* 2 * vfsv0 quota IO operations on file 3 */ 4 5 #include <linux/errno.h> 6 #include <linux/fs.h> 7 #include <linux/mount.h> 8 #include <linux/dqblk_v2.h> 9 #include <linux/kernel.h> 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/slab.h> 13 #include <linux/quotaops.h> 14 15 #include <asm/byteorder.h> 16 17 #include "quota_tree.h" 18 19 MODULE_AUTHOR("Jan Kara"); 20 MODULE_DESCRIPTION("Quota trie support"); 21 MODULE_LICENSE("GPL"); 22 23 #define __QUOTA_QT_PARANOIA 24 25 static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth) 26 { 27 unsigned int epb = info->dqi_usable_bs >> 2; 28 qid_t id = from_kqid(&init_user_ns, qid); 29 30 depth = info->dqi_qtree_depth - depth - 1; 31 while (depth--) 32 id /= epb; 33 return id % epb; 34 } 35 36 /* Number of entries in one blocks */ 37 static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info) 38 { 39 return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader)) 40 / info->dqi_entry_size; 41 } 42 43 static char *getdqbuf(size_t size) 44 { 45 char *buf = kmalloc(size, GFP_NOFS); 46 if (!buf) 47 printk(KERN_WARNING 48 "VFS: Not enough memory for quota buffers.\n"); 49 return buf; 50 } 51 52 static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) 53 { 54 struct super_block *sb = info->dqi_sb; 55 56 memset(buf, 0, info->dqi_usable_bs); 57 return sb->s_op->quota_read(sb, info->dqi_type, buf, 58 info->dqi_usable_bs, blk << info->dqi_blocksize_bits); 59 } 60 61 static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) 62 { 63 struct super_block *sb = info->dqi_sb; 64 ssize_t ret; 65 66 ret = sb->s_op->quota_write(sb, info->dqi_type, buf, 67 info->dqi_usable_bs, blk << info->dqi_blocksize_bits); 68 if (ret != info->dqi_usable_bs) { 69 quota_error(sb, "dquota write failed"); 70 if (ret >= 0) 71 ret = -EIO; 72 } 73 return ret; 74 } 75 76 /* Remove empty block from list and return it */ 77 static int get_free_dqblk(struct qtree_mem_dqinfo *info) 78 { 79 char *buf = getdqbuf(info->dqi_usable_bs); 80 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 81 int ret, blk; 82 83 if (!buf) 84 return -ENOMEM; 85 if (info->dqi_free_blk) { 86 blk = info->dqi_free_blk; 87 ret = read_blk(info, blk, buf); 88 if (ret < 0) 89 goto out_buf; 90 info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free); 91 } 92 else { 93 memset(buf, 0, info->dqi_usable_bs); 94 /* Assure block allocation... */ 95 ret = write_blk(info, info->dqi_blocks, buf); 96 if (ret < 0) 97 goto out_buf; 98 blk = info->dqi_blocks++; 99 } 100 mark_info_dirty(info->dqi_sb, info->dqi_type); 101 ret = blk; 102 out_buf: 103 kfree(buf); 104 return ret; 105 } 106 107 /* Insert empty block to the list */ 108 static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk) 109 { 110 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 111 int err; 112 113 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk); 114 dh->dqdh_prev_free = cpu_to_le32(0); 115 dh->dqdh_entries = cpu_to_le16(0); 116 err = write_blk(info, blk, buf); 117 if (err < 0) 118 return err; 119 info->dqi_free_blk = blk; 120 mark_info_dirty(info->dqi_sb, info->dqi_type); 121 return 0; 122 } 123 124 /* Remove given block from the list of blocks with free entries */ 125 static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, 126 uint blk) 127 { 128 char *tmpbuf = getdqbuf(info->dqi_usable_bs); 129 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 130 uint nextblk = le32_to_cpu(dh->dqdh_next_free); 131 uint prevblk = le32_to_cpu(dh->dqdh_prev_free); 132 int err; 133 134 if (!tmpbuf) 135 return -ENOMEM; 136 if (nextblk) { 137 err = read_blk(info, nextblk, tmpbuf); 138 if (err < 0) 139 goto out_buf; 140 ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = 141 dh->dqdh_prev_free; 142 err = write_blk(info, nextblk, tmpbuf); 143 if (err < 0) 144 goto out_buf; 145 } 146 if (prevblk) { 147 err = read_blk(info, prevblk, tmpbuf); 148 if (err < 0) 149 goto out_buf; 150 ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free = 151 dh->dqdh_next_free; 152 err = write_blk(info, prevblk, tmpbuf); 153 if (err < 0) 154 goto out_buf; 155 } else { 156 info->dqi_free_entry = nextblk; 157 mark_info_dirty(info->dqi_sb, info->dqi_type); 158 } 159 kfree(tmpbuf); 160 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0); 161 /* No matter whether write succeeds block is out of list */ 162 if (write_blk(info, blk, buf) < 0) 163 quota_error(info->dqi_sb, "Can't write block (%u) " 164 "with free entries", blk); 165 return 0; 166 out_buf: 167 kfree(tmpbuf); 168 return err; 169 } 170 171 /* Insert given block to the beginning of list with free entries */ 172 static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, 173 uint blk) 174 { 175 char *tmpbuf = getdqbuf(info->dqi_usable_bs); 176 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 177 int err; 178 179 if (!tmpbuf) 180 return -ENOMEM; 181 dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry); 182 dh->dqdh_prev_free = cpu_to_le32(0); 183 err = write_blk(info, blk, buf); 184 if (err < 0) 185 goto out_buf; 186 if (info->dqi_free_entry) { 187 err = read_blk(info, info->dqi_free_entry, tmpbuf); 188 if (err < 0) 189 goto out_buf; 190 ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = 191 cpu_to_le32(blk); 192 err = write_blk(info, info->dqi_free_entry, tmpbuf); 193 if (err < 0) 194 goto out_buf; 195 } 196 kfree(tmpbuf); 197 info->dqi_free_entry = blk; 198 mark_info_dirty(info->dqi_sb, info->dqi_type); 199 return 0; 200 out_buf: 201 kfree(tmpbuf); 202 return err; 203 } 204 205 /* Is the entry in the block free? */ 206 int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk) 207 { 208 int i; 209 210 for (i = 0; i < info->dqi_entry_size; i++) 211 if (disk[i]) 212 return 0; 213 return 1; 214 } 215 EXPORT_SYMBOL(qtree_entry_unused); 216 217 /* Find space for dquot */ 218 static uint find_free_dqentry(struct qtree_mem_dqinfo *info, 219 struct dquot *dquot, int *err) 220 { 221 uint blk, i; 222 struct qt_disk_dqdbheader *dh; 223 char *buf = getdqbuf(info->dqi_usable_bs); 224 char *ddquot; 225 226 *err = 0; 227 if (!buf) { 228 *err = -ENOMEM; 229 return 0; 230 } 231 dh = (struct qt_disk_dqdbheader *)buf; 232 if (info->dqi_free_entry) { 233 blk = info->dqi_free_entry; 234 *err = read_blk(info, blk, buf); 235 if (*err < 0) 236 goto out_buf; 237 } else { 238 blk = get_free_dqblk(info); 239 if ((int)blk < 0) { 240 *err = blk; 241 kfree(buf); 242 return 0; 243 } 244 memset(buf, 0, info->dqi_usable_bs); 245 /* This is enough as the block is already zeroed and the entry 246 * list is empty... */ 247 info->dqi_free_entry = blk; 248 mark_info_dirty(dquot->dq_sb, dquot->dq_id.type); 249 } 250 /* Block will be full? */ 251 if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) { 252 *err = remove_free_dqentry(info, buf, blk); 253 if (*err < 0) { 254 quota_error(dquot->dq_sb, "Can't remove block (%u) " 255 "from entry free list", blk); 256 goto out_buf; 257 } 258 } 259 le16_add_cpu(&dh->dqdh_entries, 1); 260 /* Find free structure in block */ 261 ddquot = buf + sizeof(struct qt_disk_dqdbheader); 262 for (i = 0; i < qtree_dqstr_in_blk(info); i++) { 263 if (qtree_entry_unused(info, ddquot)) 264 break; 265 ddquot += info->dqi_entry_size; 266 } 267 #ifdef __QUOTA_QT_PARANOIA 268 if (i == qtree_dqstr_in_blk(info)) { 269 quota_error(dquot->dq_sb, "Data block full but it shouldn't"); 270 *err = -EIO; 271 goto out_buf; 272 } 273 #endif 274 *err = write_blk(info, blk, buf); 275 if (*err < 0) { 276 quota_error(dquot->dq_sb, "Can't write quota data block %u", 277 blk); 278 goto out_buf; 279 } 280 dquot->dq_off = (blk << info->dqi_blocksize_bits) + 281 sizeof(struct qt_disk_dqdbheader) + 282 i * info->dqi_entry_size; 283 kfree(buf); 284 return blk; 285 out_buf: 286 kfree(buf); 287 return 0; 288 } 289 290 /* Insert reference to structure into the trie */ 291 static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, 292 uint *treeblk, int depth) 293 { 294 char *buf = getdqbuf(info->dqi_usable_bs); 295 int ret = 0, newson = 0, newact = 0; 296 __le32 *ref; 297 uint newblk; 298 299 if (!buf) 300 return -ENOMEM; 301 if (!*treeblk) { 302 ret = get_free_dqblk(info); 303 if (ret < 0) 304 goto out_buf; 305 *treeblk = ret; 306 memset(buf, 0, info->dqi_usable_bs); 307 newact = 1; 308 } else { 309 ret = read_blk(info, *treeblk, buf); 310 if (ret < 0) { 311 quota_error(dquot->dq_sb, "Can't read tree quota " 312 "block %u", *treeblk); 313 goto out_buf; 314 } 315 } 316 ref = (__le32 *)buf; 317 newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); 318 if (!newblk) 319 newson = 1; 320 if (depth == info->dqi_qtree_depth - 1) { 321 #ifdef __QUOTA_QT_PARANOIA 322 if (newblk) { 323 quota_error(dquot->dq_sb, "Inserting already present " 324 "quota entry (block %u)", 325 le32_to_cpu(ref[get_index(info, 326 dquot->dq_id, depth)])); 327 ret = -EIO; 328 goto out_buf; 329 } 330 #endif 331 newblk = find_free_dqentry(info, dquot, &ret); 332 } else { 333 ret = do_insert_tree(info, dquot, &newblk, depth+1); 334 } 335 if (newson && ret >= 0) { 336 ref[get_index(info, dquot->dq_id, depth)] = 337 cpu_to_le32(newblk); 338 ret = write_blk(info, *treeblk, buf); 339 } else if (newact && ret < 0) { 340 put_free_dqblk(info, buf, *treeblk); 341 } 342 out_buf: 343 kfree(buf); 344 return ret; 345 } 346 347 /* Wrapper for inserting quota structure into tree */ 348 static inline int dq_insert_tree(struct qtree_mem_dqinfo *info, 349 struct dquot *dquot) 350 { 351 int tmp = QT_TREEOFF; 352 353 #ifdef __QUOTA_QT_PARANOIA 354 if (info->dqi_blocks <= QT_TREEOFF) { 355 quota_error(dquot->dq_sb, "Quota tree root isn't allocated!"); 356 return -EIO; 357 } 358 #endif 359 return do_insert_tree(info, dquot, &tmp, 0); 360 } 361 362 /* 363 * We don't have to be afraid of deadlocks as we never have quotas on quota 364 * files... 365 */ 366 int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) 367 { 368 int type = dquot->dq_id.type; 369 struct super_block *sb = dquot->dq_sb; 370 ssize_t ret; 371 char *ddquot = getdqbuf(info->dqi_entry_size); 372 373 if (!ddquot) 374 return -ENOMEM; 375 376 /* dq_off is guarded by dqio_mutex */ 377 if (!dquot->dq_off) { 378 ret = dq_insert_tree(info, dquot); 379 if (ret < 0) { 380 quota_error(sb, "Error %zd occurred while creating " 381 "quota", ret); 382 kfree(ddquot); 383 return ret; 384 } 385 } 386 spin_lock(&dq_data_lock); 387 info->dqi_ops->mem2disk_dqblk(ddquot, dquot); 388 spin_unlock(&dq_data_lock); 389 ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, 390 dquot->dq_off); 391 if (ret != info->dqi_entry_size) { 392 quota_error(sb, "dquota write failed"); 393 if (ret >= 0) 394 ret = -ENOSPC; 395 } else { 396 ret = 0; 397 } 398 dqstats_inc(DQST_WRITES); 399 kfree(ddquot); 400 401 return ret; 402 } 403 EXPORT_SYMBOL(qtree_write_dquot); 404 405 /* Free dquot entry in data block */ 406 static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, 407 uint blk) 408 { 409 struct qt_disk_dqdbheader *dh; 410 char *buf = getdqbuf(info->dqi_usable_bs); 411 int ret = 0; 412 413 if (!buf) 414 return -ENOMEM; 415 if (dquot->dq_off >> info->dqi_blocksize_bits != blk) { 416 quota_error(dquot->dq_sb, "Quota structure has offset to " 417 "other block (%u) than it should (%u)", blk, 418 (uint)(dquot->dq_off >> info->dqi_blocksize_bits)); 419 goto out_buf; 420 } 421 ret = read_blk(info, blk, buf); 422 if (ret < 0) { 423 quota_error(dquot->dq_sb, "Can't read quota data block %u", 424 blk); 425 goto out_buf; 426 } 427 dh = (struct qt_disk_dqdbheader *)buf; 428 le16_add_cpu(&dh->dqdh_entries, -1); 429 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */ 430 ret = remove_free_dqentry(info, buf, blk); 431 if (ret >= 0) 432 ret = put_free_dqblk(info, buf, blk); 433 if (ret < 0) { 434 quota_error(dquot->dq_sb, "Can't move quota data block " 435 "(%u) to free list", blk); 436 goto out_buf; 437 } 438 } else { 439 memset(buf + 440 (dquot->dq_off & ((1 << info->dqi_blocksize_bits) - 1)), 441 0, info->dqi_entry_size); 442 if (le16_to_cpu(dh->dqdh_entries) == 443 qtree_dqstr_in_blk(info) - 1) { 444 /* Insert will write block itself */ 445 ret = insert_free_dqentry(info, buf, blk); 446 if (ret < 0) { 447 quota_error(dquot->dq_sb, "Can't insert quota " 448 "data block (%u) to free entry list", blk); 449 goto out_buf; 450 } 451 } else { 452 ret = write_blk(info, blk, buf); 453 if (ret < 0) { 454 quota_error(dquot->dq_sb, "Can't write quota " 455 "data block %u", blk); 456 goto out_buf; 457 } 458 } 459 } 460 dquot->dq_off = 0; /* Quota is now unattached */ 461 out_buf: 462 kfree(buf); 463 return ret; 464 } 465 466 /* Remove reference to dquot from tree */ 467 static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, 468 uint *blk, int depth) 469 { 470 char *buf = getdqbuf(info->dqi_usable_bs); 471 int ret = 0; 472 uint newblk; 473 __le32 *ref = (__le32 *)buf; 474 475 if (!buf) 476 return -ENOMEM; 477 ret = read_blk(info, *blk, buf); 478 if (ret < 0) { 479 quota_error(dquot->dq_sb, "Can't read quota data block %u", 480 *blk); 481 goto out_buf; 482 } 483 newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); 484 if (depth == info->dqi_qtree_depth - 1) { 485 ret = free_dqentry(info, dquot, newblk); 486 newblk = 0; 487 } else { 488 ret = remove_tree(info, dquot, &newblk, depth+1); 489 } 490 if (ret >= 0 && !newblk) { 491 int i; 492 ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0); 493 /* Block got empty? */ 494 for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++) 495 ; 496 /* Don't put the root block into the free block list */ 497 if (i == (info->dqi_usable_bs >> 2) 498 && *blk != QT_TREEOFF) { 499 put_free_dqblk(info, buf, *blk); 500 *blk = 0; 501 } else { 502 ret = write_blk(info, *blk, buf); 503 if (ret < 0) 504 quota_error(dquot->dq_sb, 505 "Can't write quota tree block %u", 506 *blk); 507 } 508 } 509 out_buf: 510 kfree(buf); 511 return ret; 512 } 513 514 /* Delete dquot from tree */ 515 int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) 516 { 517 uint tmp = QT_TREEOFF; 518 519 if (!dquot->dq_off) /* Even not allocated? */ 520 return 0; 521 return remove_tree(info, dquot, &tmp, 0); 522 } 523 EXPORT_SYMBOL(qtree_delete_dquot); 524 525 /* Find entry in block */ 526 static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, 527 struct dquot *dquot, uint blk) 528 { 529 char *buf = getdqbuf(info->dqi_usable_bs); 530 loff_t ret = 0; 531 int i; 532 char *ddquot; 533 534 if (!buf) 535 return -ENOMEM; 536 ret = read_blk(info, blk, buf); 537 if (ret < 0) { 538 quota_error(dquot->dq_sb, "Can't read quota tree " 539 "block %u", blk); 540 goto out_buf; 541 } 542 ddquot = buf + sizeof(struct qt_disk_dqdbheader); 543 for (i = 0; i < qtree_dqstr_in_blk(info); i++) { 544 if (info->dqi_ops->is_id(ddquot, dquot)) 545 break; 546 ddquot += info->dqi_entry_size; 547 } 548 if (i == qtree_dqstr_in_blk(info)) { 549 quota_error(dquot->dq_sb, 550 "Quota for id %u referenced but not present", 551 from_kqid(&init_user_ns, dquot->dq_id)); 552 ret = -EIO; 553 goto out_buf; 554 } else { 555 ret = (blk << info->dqi_blocksize_bits) + sizeof(struct 556 qt_disk_dqdbheader) + i * info->dqi_entry_size; 557 } 558 out_buf: 559 kfree(buf); 560 return ret; 561 } 562 563 /* Find entry for given id in the tree */ 564 static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, 565 struct dquot *dquot, uint blk, int depth) 566 { 567 char *buf = getdqbuf(info->dqi_usable_bs); 568 loff_t ret = 0; 569 __le32 *ref = (__le32 *)buf; 570 571 if (!buf) 572 return -ENOMEM; 573 ret = read_blk(info, blk, buf); 574 if (ret < 0) { 575 quota_error(dquot->dq_sb, "Can't read quota tree block %u", 576 blk); 577 goto out_buf; 578 } 579 ret = 0; 580 blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); 581 if (!blk) /* No reference? */ 582 goto out_buf; 583 if (depth < info->dqi_qtree_depth - 1) 584 ret = find_tree_dqentry(info, dquot, blk, depth+1); 585 else 586 ret = find_block_dqentry(info, dquot, blk); 587 out_buf: 588 kfree(buf); 589 return ret; 590 } 591 592 /* Find entry for given id in the tree - wrapper function */ 593 static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info, 594 struct dquot *dquot) 595 { 596 return find_tree_dqentry(info, dquot, QT_TREEOFF, 0); 597 } 598 599 int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) 600 { 601 int type = dquot->dq_id.type; 602 struct super_block *sb = dquot->dq_sb; 603 loff_t offset; 604 char *ddquot; 605 int ret = 0; 606 607 #ifdef __QUOTA_QT_PARANOIA 608 /* Invalidated quota? */ 609 if (!sb_dqopt(dquot->dq_sb)->files[type]) { 610 quota_error(sb, "Quota invalidated while reading!"); 611 return -EIO; 612 } 613 #endif 614 /* Do we know offset of the dquot entry in the quota file? */ 615 if (!dquot->dq_off) { 616 offset = find_dqentry(info, dquot); 617 if (offset <= 0) { /* Entry not present? */ 618 if (offset < 0) 619 quota_error(sb,"Can't read quota structure " 620 "for id %u", 621 from_kqid(&init_user_ns, 622 dquot->dq_id)); 623 dquot->dq_off = 0; 624 set_bit(DQ_FAKE_B, &dquot->dq_flags); 625 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); 626 ret = offset; 627 goto out; 628 } 629 dquot->dq_off = offset; 630 } 631 ddquot = getdqbuf(info->dqi_entry_size); 632 if (!ddquot) 633 return -ENOMEM; 634 ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size, 635 dquot->dq_off); 636 if (ret != info->dqi_entry_size) { 637 if (ret >= 0) 638 ret = -EIO; 639 quota_error(sb, "Error while reading quota structure for id %u", 640 from_kqid(&init_user_ns, dquot->dq_id)); 641 set_bit(DQ_FAKE_B, &dquot->dq_flags); 642 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); 643 kfree(ddquot); 644 goto out; 645 } 646 spin_lock(&dq_data_lock); 647 info->dqi_ops->disk2mem_dqblk(dquot, ddquot); 648 if (!dquot->dq_dqb.dqb_bhardlimit && 649 !dquot->dq_dqb.dqb_bsoftlimit && 650 !dquot->dq_dqb.dqb_ihardlimit && 651 !dquot->dq_dqb.dqb_isoftlimit) 652 set_bit(DQ_FAKE_B, &dquot->dq_flags); 653 spin_unlock(&dq_data_lock); 654 kfree(ddquot); 655 out: 656 dqstats_inc(DQST_READS); 657 return ret; 658 } 659 EXPORT_SYMBOL(qtree_read_dquot); 660 661 /* Check whether dquot should not be deleted. We know we are 662 * the only one operating on dquot (thanks to dq_lock) */ 663 int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) 664 { 665 if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && 666 !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace)) 667 return qtree_delete_dquot(info, dquot); 668 return 0; 669 } 670 EXPORT_SYMBOL(qtree_release_dquot); 671