linux-bk/fs/dquot.c
<<
>>
Prefs
   1/*
   2 * Implementation of the diskquota system for the LINUX operating
   3 * system. QUOTA is implemented using the BSD system call interface as
   4 * the means of communication with the user level. Currently only the
   5 * ext2 filesystem has support for disk quotas. Other filesystems may
   6 * be added in the future. This file contains the generic routines
   7 * called by the different filesystems on allocation of an inode or
   8 * block. These routines take care of the administration needed to
   9 * have a consistent diskquota tracking system. The ideas of both
  10 * user and group quotas are based on the Melbourne quota system as
  11 * used on BSD derived systems. The internal implementation is 
  12 * based on one of the several variants of the LINUX inode-subsystem
  13 * with added complexity of the diskquota system.
  14 * 
  15 * Version: $Id: dquot.c,v 6.3 1996/11/17 18:35:34 mvw Exp mvw $
  16 * 
  17 * Author:      Marco van Wieringen <mvw@planets.elm.net>
  18 *
  19 * Fixes:   Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
  20 *
  21 *              Revised list management to avoid races
  22 *              -- Bill Hawes, <whawes@star.net>, 9/98
  23 *
  24 *              Fixed races in dquot_transfer(), dqget() and dquot_alloc_...().
  25 *              As the consequence the locking was moved from dquot_decr_...(),
  26 *              dquot_incr_...() to calling functions.
  27 *              invalidate_dquots() now writes modified dquots.
  28 *              Serialized quota_off() and quota_on() for mount point.
  29 *              Fixed a few bugs in grow_dquots().
  30 *              Fixed deadlock in write_dquot() - we no longer account quotas on
  31 *              quota files
  32 *              remove_dquot_ref() moved to inode.c - it now traverses through inodes
  33 *              add_dquot_ref() restarts after blocking
  34 *              Added check for bogus uid and fixed check for group in quotactl.
  35 *              Jan Kara, <jack@suse.cz>, sponsored by SuSE CR, 10-11/99
  36 *
  37 *              Used struct list_head instead of own list struct
  38 *              Invalidation of referenced dquots is no longer possible
  39 *              Improved free_dquots list management
  40 *              Quota and i_blocks are now updated in one place to avoid races
  41 *              Warnings are now delayed so we won't block in critical section
  42 *              Write updated not to require dquot lock
  43 *              Jan Kara, <jack@suse.cz>, 9/2000
  44 *
  45 *              Added dynamic quota structure allocation
  46 *              Jan Kara <jack@suse.cz> 12/2000
  47 *
  48 *              Rewritten quota interface. Implemented new quota format and
  49 *              formats registering.
  50 *              Jan Kara, <jack@suse.cz>, 2001,2002
  51 *
  52 * (C) Copyright 1994 - 1997 Marco van Wieringen 
  53 */
  54
  55#include <linux/errno.h>
  56#include <linux/kernel.h>
  57#include <linux/fs.h>
  58#include <linux/time.h>
  59#include <linux/types.h>
  60#include <linux/string.h>
  61#include <linux/fcntl.h>
  62#include <linux/stat.h>
  63#include <linux/tty.h>
  64#include <linux/file.h>
  65#include <linux/slab.h>
  66#include <linux/sysctl.h>
  67#include <linux/smp_lock.h>
  68#include <linux/init.h>
  69#include <linux/module.h>
  70#include <linux/proc_fs.h>
  71
  72#include <asm/uaccess.h>
  73
  74static char *quotatypes[] = INITQFNAMES;
  75static struct quota_format_type *quota_formats; /* List of registered formats */
  76
  77int register_quota_format(struct quota_format_type *fmt)
  78{
  79        lock_kernel();
  80        fmt->qf_next = quota_formats;
  81        quota_formats = fmt;
  82        unlock_kernel();
  83        return 0;
  84}
  85
  86void unregister_quota_format(struct quota_format_type *fmt)
  87{
  88        struct quota_format_type **actqf;
  89
  90        lock_kernel();
  91        for (actqf = &quota_formats; *actqf && *actqf != fmt; actqf = &(*actqf)->qf_next);
  92        if (*actqf)
  93                *actqf = (*actqf)->qf_next;
  94        unlock_kernel();
  95}
  96
  97static struct quota_format_type *find_quota_format(int id)
  98{
  99        struct quota_format_type *actqf;
 100
 101        lock_kernel();
 102        for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; actqf = actqf->qf_next);
 103        if (actqf && !try_inc_mod_count(actqf->qf_owner))
 104                actqf = NULL;
 105        unlock_kernel();
 106        return actqf;
 107}
 108
 109static void put_quota_format(struct quota_format_type *fmt)
 110{
 111        if (fmt->qf_owner)
 112                __MOD_DEC_USE_COUNT(fmt->qf_owner);
 113}
 114
 115/*
 116 * Dquot List Management:
 117 * The quota code uses three lists for dquot management: the inuse_list,
 118 * free_dquots, and dquot_hash[] array. A single dquot structure may be
 119 * on all three lists, depending on its current state.
 120 *
 121 * All dquots are placed to the end of inuse_list when first created, and this
 122 * list is used for the sync and invalidate operations, which must look
 123 * at every dquot.
 124 *
 125 * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
 126 * and this list is searched whenever we need an available dquot.  Dquots are
 127 * removed from the list as soon as they are used again, and
 128 * dqstats.free_dquots gives the number of dquots on the list. When
 129 * dquot is invalidated it's completely released from memory.
 130 *
 131 * Dquots with a specific identity (device, type and id) are placed on
 132 * one of the dquot_hash[] hash chains. The provides an efficient search
 133 * mechanism to locate a specific dquot.
 134 */
 135
 136/*
 137 * Note that any operation which operates on dquot data (ie. dq_dqb) mustn't
 138 * block while it's updating/reading it. Otherwise races would occur.
 139 *
 140 * Locked dquots might not be referenced in inodes - operations like
 141 * add_dquot_space() does dqduplicate() and would complain. Currently
 142 * dquot it locked only once in its existence - when it's being read
 143 * to memory on first dqget() and at that time it can't be referenced
 144 * from inode. Write operations on dquots don't hold dquot lock as they
 145 * copy data to internal buffers before writing anyway and copying as well
 146 * as any data update should be atomic. Also nobody can change used
 147 * entries in dquot structure as this is done only when quota is destroyed
 148 * and invalidate_dquots() waits for dquot to have dq_count == 0.
 149 */
 150
 151static LIST_HEAD(inuse_list);
 152static LIST_HEAD(free_dquots);
 153static struct list_head dquot_hash[NR_DQHASH];
 154
 155struct dqstats dqstats;
 156
 157static void dqput(struct dquot *);
 158static struct dquot *dqduplicate(struct dquot *);
 159
 160static inline void get_dquot_ref(struct dquot *dquot)
 161{
 162        dquot->dq_count++;
 163}
 164
 165static inline void put_dquot_ref(struct dquot *dquot)
 166{
 167        dquot->dq_count--;
 168}
 169
 170static inline void get_dquot_dup_ref(struct dquot *dquot)
 171{
 172        dquot->dq_dup_ref++;
 173}
 174
 175static inline void put_dquot_dup_ref(struct dquot *dquot)
 176{
 177        dquot->dq_dup_ref--;
 178}
 179
 180static inline int const hashfn(struct super_block *sb, unsigned int id, int type)
 181{
 182        return((((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
 183}
 184
 185static inline void insert_dquot_hash(struct dquot *dquot)
 186{
 187        struct list_head *head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type);
 188        list_add(&dquot->dq_hash, head);
 189}
 190
 191static inline void remove_dquot_hash(struct dquot *dquot)
 192{
 193        list_del(&dquot->dq_hash);
 194        INIT_LIST_HEAD(&dquot->dq_hash);
 195}
 196
 197static inline struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, unsigned int id, int type)
 198{
 199        struct list_head *head;
 200        struct dquot *dquot;
 201
 202        for (head = dquot_hash[hashent].next; head != dquot_hash+hashent; head = head->next) {
 203                dquot = list_entry(head, struct dquot, dq_hash);
 204                if (dquot->dq_sb == sb && dquot->dq_id == id && dquot->dq_type == type)
 205                        return dquot;
 206        }
 207        return NODQUOT;
 208}
 209
 210/* Add a dquot to the head of the free list */
 211static inline void put_dquot_head(struct dquot *dquot)
 212{
 213        list_add(&dquot->dq_free, &free_dquots);
 214        dqstats.free_dquots++;
 215}
 216
 217/* Add a dquot to the tail of the free list */
 218static inline void put_dquot_last(struct dquot *dquot)
 219{
 220        list_add(&dquot->dq_free, free_dquots.prev);
 221        dqstats.free_dquots++;
 222}
 223
 224/* Move dquot to the head of free list (it must be already on it) */
 225static inline void move_dquot_head(struct dquot *dquot)
 226{
 227        list_del(&dquot->dq_free);
 228        list_add(&dquot->dq_free, &free_dquots);
 229}
 230
 231static inline void remove_free_dquot(struct dquot *dquot)
 232{
 233        if (list_empty(&dquot->dq_free))
 234                return;
 235        list_del(&dquot->dq_free);
 236        INIT_LIST_HEAD(&dquot->dq_free);
 237        dqstats.free_dquots--;
 238}
 239
 240static inline void put_inuse(struct dquot *dquot)
 241{
 242        /* We add to the back of inuse list so we don't have to restart
 243         * when traversing this list and we block */
 244        list_add(&dquot->dq_inuse, inuse_list.prev);
 245        dqstats.allocated_dquots++;
 246}
 247
 248static inline void remove_inuse(struct dquot *dquot)
 249{
 250        dqstats.allocated_dquots--;
 251        list_del(&dquot->dq_inuse);
 252}
 253
 254static void __wait_on_dquot(struct dquot *dquot)
 255{
 256        DECLARE_WAITQUEUE(wait, current);
 257
 258        add_wait_queue(&dquot->dq_wait_lock, &wait);
 259repeat:
 260        set_current_state(TASK_UNINTERRUPTIBLE);
 261        if (dquot->dq_flags & DQ_LOCKED) {
 262                schedule();
 263                goto repeat;
 264        }
 265        remove_wait_queue(&dquot->dq_wait_lock, &wait);
 266        current->state = TASK_RUNNING;
 267}
 268
 269static inline void wait_on_dquot(struct dquot *dquot)
 270{
 271        if (dquot->dq_flags & DQ_LOCKED)
 272                __wait_on_dquot(dquot);
 273}
 274
 275static inline void lock_dquot(struct dquot *dquot)
 276{
 277        wait_on_dquot(dquot);
 278        dquot->dq_flags |= DQ_LOCKED;
 279}
 280
 281static inline void unlock_dquot(struct dquot *dquot)
 282{
 283        dquot->dq_flags &= ~DQ_LOCKED;
 284        wake_up(&dquot->dq_wait_lock);
 285}
 286
 287/* Wait for dquot to be unused */
 288static void __wait_dquot_unused(struct dquot *dquot)
 289{
 290        DECLARE_WAITQUEUE(wait, current);
 291
 292        add_wait_queue(&dquot->dq_wait_free, &wait);
 293repeat:
 294        set_current_state(TASK_UNINTERRUPTIBLE);
 295        if (dquot->dq_count) {
 296                schedule();
 297                goto repeat;
 298        }
 299        remove_wait_queue(&dquot->dq_wait_free, &wait);
 300        current->state = TASK_RUNNING;
 301}
 302
 303/* Wait for all duplicated dquot references to be dropped */
 304static void __wait_dup_drop(struct dquot *dquot)
 305{
 306        DECLARE_WAITQUEUE(wait, current);
 307
 308        add_wait_queue(&dquot->dq_wait_free, &wait);
 309repeat:
 310        set_current_state(TASK_UNINTERRUPTIBLE);
 311        if (dquot->dq_dup_ref) {
 312                schedule();
 313                goto repeat;
 314        }
 315        remove_wait_queue(&dquot->dq_wait_free, &wait);
 316        current->state = TASK_RUNNING;
 317}
 318
 319static int read_dqblk(struct dquot *dquot)
 320{
 321        int ret;
 322        struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 323
 324        lock_dquot(dquot);
 325        down(&dqopt->dqio_sem);
 326        ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
 327        up(&dqopt->dqio_sem);
 328        unlock_dquot(dquot);
 329        return ret;
 330}
 331
 332static int commit_dqblk(struct dquot *dquot)
 333{
 334        int ret;
 335        struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 336
 337        down(&dqopt->dqio_sem);
 338        ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
 339        up(&dqopt->dqio_sem);
 340        return ret;
 341}
 342
 343/* Invalidate all dquots on the list, wait for all users. Note that this function is called
 344 * after quota is disabled so no new quota might be created. As we only insert to the end of
 345 * inuse list, we don't have to restart searching... */
 346static void invalidate_dquots(struct super_block *sb, int type)
 347{
 348        struct dquot *dquot;
 349        struct list_head *head;
 350
 351restart:
 352        list_for_each(head, &inuse_list) {
 353                dquot = list_entry(head, struct dquot, dq_inuse);
 354                if (dquot->dq_sb != sb)
 355                        continue;
 356                if (dquot->dq_type != type)
 357                        continue;
 358                dquot->dq_flags |= DQ_INVAL;
 359                if (dquot->dq_count)
 360                        /*
 361                         *  Wait for any users of quota. As we have already cleared the flags in
 362                         *  superblock and cleared all pointers from inodes we are assured
 363                         *  that there will be no new users of this quota.
 364                         */
 365                        __wait_dquot_unused(dquot);
 366                /* Quota now have no users and it has been written on last dqput() */
 367                remove_dquot_hash(dquot);
 368                remove_free_dquot(dquot);
 369                remove_inuse(dquot);
 370                kmem_cache_free(dquot_cachep, dquot);
 371                goto restart;
 372        }
 373}
 374
 375static int vfs_quota_sync(struct super_block *sb, int type)
 376{
 377        struct list_head *head;
 378        struct dquot *dquot;
 379        struct quota_info *dqopt = sb_dqopt(sb);
 380        int cnt;
 381
 382restart:
 383        list_for_each(head, &inuse_list) {
 384                dquot = list_entry(head, struct dquot, dq_inuse);
 385                if (sb && dquot->dq_sb != sb)
 386                        continue;
 387                if (type != -1 && dquot->dq_type != type)
 388                        continue;
 389                if (!dquot->dq_sb)      /* Invalidated? */
 390                        continue;
 391                if (!dquot_dirty(dquot) && !(dquot->dq_flags & DQ_LOCKED))
 392                        continue;
 393                /* Get reference to quota so it won't be invalidated. get_dquot_ref()
 394                 * is enough since if dquot is locked/modified it can't be
 395                 * on the free list */
 396                get_dquot_ref(dquot);
 397                if (dquot->dq_flags & DQ_LOCKED)
 398                        wait_on_dquot(dquot);
 399                if (dquot_dirty(dquot))
 400                        commit_dqblk(dquot);
 401                dqput(dquot);
 402                goto restart;
 403        }
 404        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 405                if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt))
 406                        dqopt->info[cnt].dqi_flags &= ~DQF_ANY_DQUOT_DIRTY;
 407        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 408                if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) && info_dirty(&dqopt->info[cnt]))
 409                        dqopt->ops[cnt]->write_file_info(sb, cnt);
 410        dqstats.syncs++;
 411
 412        return 0;
 413}
 414
 415static struct super_block *get_super_to_sync(int type)
 416{
 417        struct list_head *head;
 418        int cnt, dirty;
 419
 420restart:
 421        spin_lock(&sb_lock);
 422        list_for_each(head, &super_blocks) {
 423                struct super_block *sb = list_entry(head, struct super_block, s_list);
 424
 425                for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
 426                        if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
 427                            && sb_dqopt(sb)->info[cnt].dqi_flags & DQF_ANY_DQUOT_DIRTY)
 428                                dirty = 1;
 429                if (!dirty)
 430                        continue;
 431                sb->s_count++;
 432                spin_unlock(&sb_lock);
 433                down_read(&sb->s_umount);
 434                if (!sb->s_root) {
 435                        drop_super(sb);
 436                        goto restart;
 437                }
 438                return sb;
 439        }
 440        spin_unlock(&sb_lock);
 441        return NULL;
 442}
 443
 444void sync_dquots(struct super_block *sb, int type)
 445{
 446        if (sb) {
 447                lock_kernel();
 448                if (sb->s_qcop->quota_sync)
 449                        sb->s_qcop->quota_sync(sb, type);
 450                unlock_kernel();
 451        }
 452        else {
 453                while ((sb = get_super_to_sync(type))) {
 454                        lock_kernel();
 455                        if (sb->s_qcop->quota_sync)
 456                                sb->s_qcop->quota_sync(sb, type);
 457                        unlock_kernel();
 458                        drop_super(sb);
 459                }
 460        }
 461}
 462
 463/* Free unused dquots from cache */
 464static void prune_dqcache(int count)
 465{
 466        struct list_head *head;
 467        struct dquot *dquot;
 468
 469        head = free_dquots.prev;
 470        while (head != &free_dquots && count) {
 471                dquot = list_entry(head, struct dquot, dq_free);
 472                remove_dquot_hash(dquot);
 473                remove_free_dquot(dquot);
 474                remove_inuse(dquot);
 475                kmem_cache_free(dquot_cachep, dquot);
 476                count--;
 477                head = free_dquots.prev;
 478        }
 479}
 480
 481/*
 482 * This is called from kswapd when we think we need some
 483 * more memory, but aren't really sure how much. So we
 484 * carefully try to free a _bit_ of our dqcache, but not
 485 * too much.
 486 *
 487 * Priority:
 488 *   1 - very urgent: shrink everything
 489 *   ...
 490 *   6 - base-level: try to shrink a bit.
 491 */
 492
 493int shrink_dqcache_memory(int priority, unsigned int gfp_mask)
 494{
 495        int count = 0;
 496
 497        lock_kernel();
 498        count = dqstats.free_dquots / priority;
 499        prune_dqcache(count);
 500        unlock_kernel();
 501        kmem_cache_shrink(dquot_cachep);
 502        return 0;
 503}
 504
 505/*
 506 * Put reference to dquot
 507 * NOTE: If you change this function please check whether dqput_blocks() works right...
 508 */
 509static void dqput(struct dquot *dquot)
 510{
 511        if (!dquot)
 512                return;
 513#ifdef __DQUOT_PARANOIA
 514        if (!dquot->dq_count) {
 515                printk("VFS: dqput: trying to free free dquot\n");
 516                printk("VFS: device %s, dquot of %s %d\n",
 517                        dquot->dq_sb->s_id,
 518                        quotatypes[dquot->dq_type],
 519                        dquot->dq_id);
 520                return;
 521        }
 522#endif
 523
 524        dqstats.drops++;
 525we_slept:
 526        if (dquot->dq_dup_ref && dquot->dq_count - dquot->dq_dup_ref <= 1) {    /* Last unduplicated reference? */
 527                __wait_dup_drop(dquot);
 528                goto we_slept;
 529        }
 530        if (dquot->dq_count > 1) {
 531                /* We have more than one user... We can simply decrement use count */
 532                put_dquot_ref(dquot);
 533                return;
 534        }
 535        if (dquot_dirty(dquot)) {
 536                commit_dqblk(dquot);
 537                goto we_slept;
 538        }
 539
 540        /* sanity check */
 541        if (!list_empty(&dquot->dq_free)) {
 542                printk(KERN_ERR "dqput: dquot already on free list??\n");
 543                put_dquot_ref(dquot);
 544                return;
 545        }
 546        put_dquot_ref(dquot);
 547        /* If dquot is going to be invalidated invalidate_dquots() is going to free it so */
 548        if (!(dquot->dq_flags & DQ_INVAL))
 549                put_dquot_last(dquot);  /* Place at end of LRU free queue */
 550        wake_up(&dquot->dq_wait_free);
 551}
 552
 553static struct dquot *get_empty_dquot(struct super_block *sb, int type)
 554{
 555        struct dquot *dquot;
 556
 557        dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL);
 558        if(!dquot)
 559                return NODQUOT;
 560
 561        memset((caddr_t)dquot, 0, sizeof(struct dquot));
 562        init_waitqueue_head(&dquot->dq_wait_free);
 563        init_waitqueue_head(&dquot->dq_wait_lock);
 564        INIT_LIST_HEAD(&dquot->dq_free);
 565        INIT_LIST_HEAD(&dquot->dq_inuse);
 566        INIT_LIST_HEAD(&dquot->dq_hash);
 567        dquot->dq_sb = sb;
 568        dquot->dq_type = type;
 569        dquot->dq_count = 1;
 570        /* all dquots go on the inuse_list */
 571        put_inuse(dquot);
 572
 573        return dquot;
 574}
 575
 576static struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
 577{
 578        unsigned int hashent = hashfn(sb, id, type);
 579        struct dquot *dquot, *empty = NODQUOT;
 580        struct quota_info *dqopt = sb_dqopt(sb);
 581
 582we_slept:
 583        if (!is_enabled(dqopt, type)) {
 584                if (empty)
 585                        dqput(empty);
 586                return NODQUOT;
 587        }
 588
 589        if ((dquot = find_dquot(hashent, sb, id, type)) == NODQUOT) {
 590                if (empty == NODQUOT) {
 591                        if ((empty = get_empty_dquot(sb, type)) == NODQUOT)
 592                                schedule();     /* Try to wait for a moment... */
 593                        goto we_slept;
 594                }
 595                dquot = empty;
 596                dquot->dq_id = id;
 597                /* hash it first so it can be found */
 598                insert_dquot_hash(dquot);
 599                read_dqblk(dquot);
 600        } else {
 601                if (!dquot->dq_count)
 602                        remove_free_dquot(dquot);
 603                get_dquot_ref(dquot);
 604                dqstats.cache_hits++;
 605                wait_on_dquot(dquot);
 606                if (empty)
 607                        dqput(empty);
 608        }
 609
 610        if (!dquot->dq_sb) {    /* Has somebody invalidated entry under us? */
 611                printk(KERN_ERR "VFS: dqget(): Quota invalidated in dqget()!\n");
 612                dqput(dquot);
 613                return NODQUOT;
 614        }
 615        ++dquot->dq_referenced;
 616        dqstats.lookups++;
 617
 618        return dquot;
 619}
 620
 621/* Duplicate reference to dquot got from inode */
 622static struct dquot *dqduplicate(struct dquot *dquot)
 623{
 624        if (dquot == NODQUOT)
 625                return NODQUOT;
 626        get_dquot_ref(dquot);
 627        if (!dquot->dq_sb) {
 628                printk(KERN_ERR "VFS: dqduplicate(): Invalidated quota to be duplicated!\n");
 629                put_dquot_ref(dquot);
 630                return NODQUOT;
 631        }
 632        if (dquot->dq_flags & DQ_LOCKED)
 633                printk(KERN_ERR "VFS: dqduplicate(): Locked quota to be duplicated!\n");
 634        get_dquot_dup_ref(dquot);
 635        dquot->dq_referenced++;
 636        dqstats.lookups++;
 637
 638        return dquot;
 639}
 640
 641/* Put duplicated reference */
 642static void dqputduplicate(struct dquot *dquot)
 643{
 644        if (!dquot->dq_dup_ref) {
 645                printk(KERN_ERR "VFS: dqputduplicate(): Duplicated dquot put without duplicate reference.\n");
 646                return;
 647        }
 648        put_dquot_dup_ref(dquot);
 649        if (!dquot->dq_dup_ref)
 650                wake_up(&dquot->dq_wait_free);
 651        put_dquot_ref(dquot);
 652        dqstats.drops++;
 653}
 654
 655static int dqinit_needed(struct inode *inode, int type)
 656{
 657        int cnt;
 658
 659        if (IS_NOQUOTA(inode))
 660                return 0;
 661        if (type != -1)
 662                return inode->i_dquot[type] == NODQUOT;
 663        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 664                if (inode->i_dquot[cnt] == NODQUOT)
 665                        return 1;
 666        return 0;
 667}
 668
 669static void add_dquot_ref(struct super_block *sb, int type)
 670{
 671        struct list_head *p;
 672
 673restart:
 674        file_list_lock();
 675        list_for_each(p, &sb->s_files) {
 676                struct file *filp = list_entry(p, struct file, f_list);
 677                struct inode *inode = filp->f_dentry->d_inode;
 678                if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
 679                        struct vfsmount *mnt = mntget(filp->f_vfsmnt);
 680                        struct dentry *dentry = dget(filp->f_dentry);
 681                        file_list_unlock();
 682                        sb->dq_op->initialize(inode, type);
 683                        dput(dentry);
 684                        mntput(mnt);
 685                        /* As we may have blocked we had better restart... */
 686                        goto restart;
 687                }
 688        }
 689        file_list_unlock();
 690}
 691
 692/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
 693static inline int dqput_blocks(struct dquot *dquot)
 694{
 695        if (dquot->dq_dup_ref && dquot->dq_count - dquot->dq_dup_ref <= 1)
 696                return 1;
 697        if (dquot->dq_count <= 1 && dquot->dq_flags & DQ_MOD)
 698                return 1;
 699        return 0;
 700}
 701
 702/* Remove references to dquots from inode - add dquot to list for freeing if needed */
 703int remove_inode_dquot_ref(struct inode *inode, int type, struct list_head *tofree_head)
 704{
 705        struct dquot *dquot = inode->i_dquot[type];
 706        int cnt;
 707
 708        inode->i_dquot[type] = NODQUOT;
 709        /* any other quota in use? */
 710        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 711                if (inode->i_dquot[cnt] != NODQUOT)
 712                        goto put_it;
 713        }
 714        inode->i_flags &= ~S_QUOTA;
 715put_it:
 716        if (dquot != NODQUOT) {
 717                if (dqput_blocks(dquot)) {
 718                        if (dquot->dq_count != 1)
 719                                printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", dquot->dq_count);
 720                        list_add(&dquot->dq_free, tofree_head); /* As dquot must have currently users it can't be on the free list... */
 721                        return 1;
 722                }
 723                else
 724                        dqput(dquot);   /* We have guaranteed we won't block */
 725        }
 726        return 0;
 727}
 728
 729/* Free list of dquots - called from inode.c */
 730void put_dquot_list(struct list_head *tofree_head)
 731{
 732        struct list_head *act_head;
 733        struct dquot *dquot;
 734
 735        lock_kernel();
 736        act_head = tofree_head->next;
 737        /* So now we have dquots on the list... Just free them */
 738        while (act_head != tofree_head) {
 739                dquot = list_entry(act_head, struct dquot, dq_free);
 740                act_head = act_head->next;
 741                list_del(&dquot->dq_free);      /* Remove dquot from the list so we won't have problems... */
 742                INIT_LIST_HEAD(&dquot->dq_free);
 743                dqput(dquot);
 744        }
 745        unlock_kernel();
 746}
 747
 748static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
 749{
 750        dquot->dq_dqb.dqb_curinodes += number;
 751        mark_dquot_dirty(dquot);
 752}
 753
 754static inline void dquot_incr_space(struct dquot *dquot, qsize_t number)
 755{
 756        dquot->dq_dqb.dqb_curspace += number;
 757        mark_dquot_dirty(dquot);
 758}
 759
 760static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
 761{
 762        if (dquot->dq_dqb.dqb_curinodes > number)
 763                dquot->dq_dqb.dqb_curinodes -= number;
 764        else
 765                dquot->dq_dqb.dqb_curinodes = 0;
 766        if (dquot->dq_dqb.dqb_curinodes < dquot->dq_dqb.dqb_isoftlimit)
 767                dquot->dq_dqb.dqb_itime = (time_t) 0;
 768        dquot->dq_flags &= ~DQ_INODES;
 769        mark_dquot_dirty(dquot);
 770}
 771
 772static inline void dquot_decr_space(struct dquot *dquot, qsize_t number)
 773{
 774        if (dquot->dq_dqb.dqb_curspace > number)
 775                dquot->dq_dqb.dqb_curspace -= number;
 776        else
 777                dquot->dq_dqb.dqb_curspace = 0;
 778        if (toqb(dquot->dq_dqb.dqb_curspace) < dquot->dq_dqb.dqb_bsoftlimit)
 779                dquot->dq_dqb.dqb_btime = (time_t) 0;
 780        dquot->dq_flags &= ~DQ_BLKS;
 781        mark_dquot_dirty(dquot);
 782}
 783
 784static inline int need_print_warning(struct dquot *dquot, int flag)
 785{
 786        switch (dquot->dq_type) {
 787                case USRQUOTA:
 788                        return current->fsuid == dquot->dq_id && !(dquot->dq_flags & flag);
 789                case GRPQUOTA:
 790                        return in_group_p(dquot->dq_id) && !(dquot->dq_flags & flag);
 791        }
 792        return 0;
 793}
 794
 795/* Values of warnings */
 796#define NOWARN 0
 797#define IHARDWARN 1
 798#define ISOFTLONGWARN 2
 799#define ISOFTWARN 3
 800#define BHARDWARN 4
 801#define BSOFTLONGWARN 5
 802#define BSOFTWARN 6
 803
 804/* Print warning to user which exceeded quota */
 805static void print_warning(struct dquot *dquot, const char warntype)
 806{
 807        char *msg = NULL;
 808        int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS :
 809          ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES : 0);
 810
 811        if (!need_print_warning(dquot, flag))
 812                return;
 813        dquot->dq_flags |= flag;
 814        tty_write_message(current->tty, dquot->dq_sb->s_id);
 815        if (warntype == ISOFTWARN || warntype == BSOFTWARN)
 816                tty_write_message(current->tty, ": warning, ");
 817        else
 818                tty_write_message(current->tty, ": write failed, ");
 819        tty_write_message(current->tty, quotatypes[dquot->dq_type]);
 820        switch (warntype) {
 821                case IHARDWARN:
 822                        msg = " file limit reached.\n";
 823                        break;
 824                case ISOFTLONGWARN:
 825                        msg = " file quota exceeded too long.\n";
 826                        break;
 827                case ISOFTWARN:
 828                        msg = " file quota exceeded.\n";
 829                        break;
 830                case BHARDWARN:
 831                        msg = " block limit reached.\n";
 832                        break;
 833                case BSOFTLONGWARN:
 834                        msg = " block quota exceeded too long.\n";
 835                        break;
 836                case BSOFTWARN:
 837                        msg = " block quota exceeded.\n";
 838                        break;
 839        }
 840        tty_write_message(current->tty, msg);
 841}
 842
 843static inline void flush_warnings(struct dquot **dquots, char *warntype)
 844{
 845        int i;
 846
 847        for (i = 0; i < MAXQUOTAS; i++)
 848                if (dquots[i] != NODQUOT && warntype[i] != NOWARN)
 849                        print_warning(dquots[i], warntype[i]);
 850}
 851
 852static inline char ignore_hardlimit(struct dquot *dquot)
 853{
 854        struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
 855
 856        return capable(CAP_SYS_RESOURCE) &&
 857            (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || !(info->dqi_flags & V1_DQF_RSQUASH));
 858}
 859
 860static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
 861{
 862        *warntype = NOWARN;
 863        if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
 864                return QUOTA_OK;
 865
 866        if (dquot->dq_dqb.dqb_ihardlimit &&
 867           (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_ihardlimit &&
 868            !ignore_hardlimit(dquot)) {
 869                *warntype = IHARDWARN;
 870                return NO_QUOTA;
 871        }
 872
 873        if (dquot->dq_dqb.dqb_isoftlimit &&
 874           (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit &&
 875            dquot->dq_dqb.dqb_itime && CURRENT_TIME >= dquot->dq_dqb.dqb_itime &&
 876            !ignore_hardlimit(dquot)) {
 877                *warntype = ISOFTLONGWARN;
 878                return NO_QUOTA;
 879        }
 880
 881        if (dquot->dq_dqb.dqb_isoftlimit &&
 882           (dquot->dq_dqb.dqb_curinodes + inodes) > dquot->dq_dqb.dqb_isoftlimit &&
 883            dquot->dq_dqb.dqb_itime == 0) {
 884                *warntype = ISOFTWARN;
 885                dquot->dq_dqb.dqb_itime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
 886        }
 887
 888        return QUOTA_OK;
 889}
 890
 891static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype)
 892{
 893        *warntype = 0;
 894        if (space <= 0 || dquot->dq_flags & DQ_FAKE)
 895                return QUOTA_OK;
 896
 897        if (dquot->dq_dqb.dqb_bhardlimit &&
 898           toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bhardlimit &&
 899            !ignore_hardlimit(dquot)) {
 900                if (!prealloc)
 901                        *warntype = BHARDWARN;
 902                return NO_QUOTA;
 903        }
 904
 905        if (dquot->dq_dqb.dqb_bsoftlimit &&
 906           toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
 907            dquot->dq_dqb.dqb_btime && CURRENT_TIME >= dquot->dq_dqb.dqb_btime &&
 908            !ignore_hardlimit(dquot)) {
 909                if (!prealloc)
 910                        *warntype = BSOFTLONGWARN;
 911                return NO_QUOTA;
 912        }
 913
 914        if (dquot->dq_dqb.dqb_bsoftlimit &&
 915           toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
 916            dquot->dq_dqb.dqb_btime == 0) {
 917                if (!prealloc) {
 918                        *warntype = BSOFTWARN;
 919                        dquot->dq_dqb.dqb_btime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
 920                }
 921                else
 922                        /*
 923                         * We don't allow preallocation to exceed softlimit so exceeding will
 924                         * be always printed
 925                         */
 926                        return NO_QUOTA;
 927        }
 928
 929        return QUOTA_OK;
 930}
 931
 932/*
 933 * Externally referenced functions through dquot_operations in inode.
 934 *
 935 * Note: this is a blocking operation.
 936 */
 937void dquot_initialize(struct inode *inode, int type)
 938{
 939        struct dquot *dquot[MAXQUOTAS];
 940        unsigned int id = 0;
 941        int cnt;
 942
 943        if (IS_NOQUOTA(inode))
 944                return;
 945        /* Build list of quotas to initialize... We can block here */
 946        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 947                dquot[cnt] = NODQUOT;
 948                if (type != -1 && cnt != type)
 949                        continue;
 950                if (!sb_has_quota_enabled(inode->i_sb, cnt))
 951                        continue;
 952                if (inode->i_dquot[cnt] == NODQUOT) {
 953                        switch (cnt) {
 954                                case USRQUOTA:
 955                                        id = inode->i_uid;
 956                                        break;
 957                                case GRPQUOTA:
 958                                        id = inode->i_gid;
 959                                        break;
 960                        }
 961                        dquot[cnt] = dqget(inode->i_sb, id, cnt);
 962                }
 963        }
 964        /* NOBLOCK START: Here we shouldn't block */
 965        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 966                if (dquot[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt) || inode->i_dquot[cnt] != NODQUOT)
 967                        continue;
 968                inode->i_dquot[cnt] = dquot[cnt];
 969                dquot[cnt] = NODQUOT;
 970                inode->i_flags |= S_QUOTA;
 971        }
 972        /* NOBLOCK END */
 973        /* Put quotas which we didn't use */
 974        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 975                if (dquot[cnt] != NODQUOT)
 976                        dqput(dquot[cnt]);
 977}
 978
 979/*
 980 * Release all quota for the specified inode.
 981 *
 982 * Note: this is a blocking operation.
 983 */
 984void dquot_drop(struct inode *inode)
 985{
 986        struct dquot *dquot;
 987        int cnt;
 988
 989        inode->i_flags &= ~S_QUOTA;
 990        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 991                if (inode->i_dquot[cnt] == NODQUOT)
 992                        continue;
 993                dquot = inode->i_dquot[cnt];
 994                inode->i_dquot[cnt] = NODQUOT;
 995                dqput(dquot);
 996        }
 997}
 998
 999/*
1000 * This operation can block, but only after everything is updated
1001 */
1002int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
1003{
1004        int cnt, ret = NO_QUOTA;
1005        struct dquot *dquot[MAXQUOTAS];
1006        char warntype[MAXQUOTAS];
1007
1008        lock_kernel();
1009        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1010                dquot[cnt] = NODQUOT;
1011                warntype[cnt] = NOWARN;
1012        }
1013        /* NOBLOCK Start */
1014        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1015                dquot[cnt] = dqduplicate(inode->i_dquot[cnt]);
1016                if (dquot[cnt] == NODQUOT)
1017                        continue;
1018                if (check_bdq(dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA)
1019                        goto warn_put_all;
1020        }
1021        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1022                if (dquot[cnt] == NODQUOT)
1023                        continue;
1024                dquot_incr_space(dquot[cnt], number);
1025        }
1026        inode_add_bytes(inode, number);
1027        /* NOBLOCK End */
1028        ret = QUOTA_OK;
1029warn_put_all:
1030        flush_warnings(dquot, warntype);
1031        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1032                if (dquot[cnt] != NODQUOT)
1033                        dqputduplicate(dquot[cnt]);
1034        unlock_kernel();
1035        return ret;
1036}
1037
1038/*
1039 * This operation can block, but only after everything is updated
1040 */
1041int dquot_alloc_inode(const struct inode *inode, unsigned long number)
1042{
1043        int cnt, ret = NO_QUOTA;
1044        struct dquot *dquot[MAXQUOTAS];
1045        char warntype[MAXQUOTAS];
1046
1047        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1048                dquot[cnt] = NODQUOT;
1049                warntype[cnt] = NOWARN;
1050        }
1051        /* NOBLOCK Start */
1052        lock_kernel();
1053        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1054                dquot[cnt] = dqduplicate(inode -> i_dquot[cnt]);
1055                if (dquot[cnt] == NODQUOT)
1056                        continue;
1057                if (check_idq(dquot[cnt], number, warntype+cnt) == NO_QUOTA)
1058                        goto warn_put_all;
1059        }
1060
1061        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1062                if (dquot[cnt] == NODQUOT)
1063                        continue;
1064                dquot_incr_inodes(dquot[cnt], number);
1065        }
1066        /* NOBLOCK End */
1067        ret = QUOTA_OK;
1068warn_put_all:
1069        flush_warnings(dquot, warntype);
1070        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1071                if (dquot[cnt] != NODQUOT)
1072                        dqputduplicate(dquot[cnt]);
1073        unlock_kernel();
1074        return ret;
1075}
1076
1077/*
1078 * This is a non-blocking operation.
1079 */
1080void dquot_free_space(struct inode *inode, qsize_t number)
1081{
1082        unsigned int cnt;
1083        struct dquot *dquot;
1084
1085        /* NOBLOCK Start */
1086        lock_kernel();
1087        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1088                dquot = dqduplicate(inode->i_dquot[cnt]);
1089                if (dquot == NODQUOT)
1090                        continue;
1091                dquot_decr_space(dquot, number);
1092                dqputduplicate(dquot);
1093        }
1094        inode_sub_bytes(inode, number);
1095        unlock_kernel();
1096        /* NOBLOCK End */
1097}
1098
1099/*
1100 * This is a non-blocking operation.
1101 */
1102void dquot_free_inode(const struct inode *inode, unsigned long number)
1103{
1104        unsigned int cnt;
1105        struct dquot *dquot;
1106
1107        /* NOBLOCK Start */
1108        lock_kernel();
1109        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1110                dquot = dqduplicate(inode->i_dquot[cnt]);
1111                if (dquot == NODQUOT)
1112                        continue;
1113                dquot_decr_inodes(dquot, number);
1114                dqputduplicate(dquot);
1115        }
1116        unlock_kernel();
1117        /* NOBLOCK End */
1118}
1119
1120/*
1121 * Transfer the number of inode and blocks from one diskquota to an other.
1122 *
1123 * This operation can block, but only after everything is updated
1124 */
1125int dquot_transfer(struct inode *inode, struct iattr *iattr)
1126{
1127        qsize_t space;
1128        struct dquot *transfer_from[MAXQUOTAS];
1129        struct dquot *transfer_to[MAXQUOTAS];
1130        int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,
1131            chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
1132        char warntype[MAXQUOTAS];
1133
1134        /* Clear the arrays */
1135        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1136                transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
1137                warntype[cnt] = NOWARN;
1138        }
1139        /* First build the transfer_to list - here we can block on reading of dquots... */
1140        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1141                if (!sb_has_quota_enabled(inode->i_sb, cnt))
1142                        continue;
1143                switch (cnt) {
1144                        case USRQUOTA:
1145                                if (!chuid)
1146                                        continue;
1147                                transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_uid, cnt);
1148                                break;
1149                        case GRPQUOTA:
1150                                if (!chgid)
1151                                        continue;
1152                                transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_gid, cnt);
1153                                break;
1154                }
1155        }
1156        /* NOBLOCK START: From now on we shouldn't block */
1157        space = inode_get_bytes(inode);
1158        /* Build the transfer_from list and check the limits */
1159        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1160                /* The second test can fail when quotaoff is in progress... */
1161                if (transfer_to[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt))
1162                        continue;
1163                transfer_from[cnt] = dqduplicate(inode->i_dquot[cnt]);
1164                if (transfer_from[cnt] == NODQUOT)      /* Can happen on quotafiles (quota isn't initialized on them)... */
1165                        continue;
1166                if (check_idq(transfer_to[cnt], 1, warntype+cnt) == NO_QUOTA ||
1167                    check_bdq(transfer_to[cnt], space, 0, warntype+cnt) == NO_QUOTA)
1168                        goto warn_put_all;
1169        }
1170
1171        /*
1172         * Finally perform the needed transfer from transfer_from to transfer_to
1173         */
1174        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1175                /*
1176                 * Skip changes for same uid or gid or for non-existing quota-type.
1177                 */
1178                if (transfer_from[cnt] == NODQUOT || transfer_to[cnt] == NODQUOT)
1179                        continue;
1180
1181                dquot_decr_inodes(transfer_from[cnt], 1);
1182                dquot_decr_space(transfer_from[cnt], space);
1183
1184                dquot_incr_inodes(transfer_to[cnt], 1);
1185                dquot_incr_space(transfer_to[cnt], space);
1186
1187                if (inode->i_dquot[cnt] == NODQUOT)
1188                        BUG();
1189                inode->i_dquot[cnt] = transfer_to[cnt];
1190                /*
1191                 * We've got to release transfer_from[] twice - once for dquot_transfer() and
1192                 * once for inode. We don't want to release transfer_to[] as it's now placed in inode
1193                 */
1194                transfer_to[cnt] = transfer_from[cnt];
1195        }
1196        /* NOBLOCK END. From now on we can block as we wish */
1197        ret = QUOTA_OK;
1198warn_put_all:
1199        flush_warnings(transfer_to, warntype);
1200        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1201                /* First we must put duplicate - otherwise we might deadlock */
1202                if (transfer_to[cnt] != NODQUOT)
1203                        dqputduplicate(transfer_to[cnt]);
1204                if (transfer_from[cnt] != NODQUOT)
1205                        dqput(transfer_from[cnt]);
1206        }
1207        return ret;
1208}
1209
1210/*
1211 * Definitions of diskquota operations.
1212 */
1213struct dquot_operations dquot_operations = {
1214        .initialize     = dquot_initialize,             /* mandatory */
1215        .drop           = dquot_drop,                   /* mandatory */
1216        .alloc_space    = dquot_alloc_space,
1217        .alloc_inode    = dquot_alloc_inode,
1218        .free_space     = dquot_free_space,
1219        .free_inode     = dquot_free_inode,
1220        .transfer       = dquot_transfer
1221};
1222
1223static inline void set_enable_flags(struct quota_info *dqopt, int type)
1224{
1225        switch (type) {
1226                case USRQUOTA:
1227                        dqopt->flags |= DQUOT_USR_ENABLED;
1228                        break;
1229                case GRPQUOTA:
1230                        dqopt->flags |= DQUOT_GRP_ENABLED;
1231                        break;
1232        }
1233}
1234
1235static inline void reset_enable_flags(struct quota_info *dqopt, int type)
1236{
1237        switch (type) {
1238                case USRQUOTA:
1239                        dqopt->flags &= ~DQUOT_USR_ENABLED;
1240                        break;
1241                case GRPQUOTA:
1242                        dqopt->flags &= ~DQUOT_GRP_ENABLED;
1243                        break;
1244        }
1245}
1246
1247/* Function in inode.c - remove pointers to dquots in icache */
1248extern void remove_dquot_ref(struct super_block *, int);
1249
1250/*
1251 * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
1252 */
1253int vfs_quota_off(struct super_block *sb, int type)
1254{
1255        int cnt;
1256        struct quota_info *dqopt = sb_dqopt(sb);
1257
1258        lock_kernel();
1259        if (!sb)
1260                goto out;
1261
1262        /* We need to serialize quota_off() for device */
1263        down(&dqopt->dqoff_sem);
1264        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1265                if (type != -1 && cnt != type)
1266                        continue;
1267                if (!is_enabled(dqopt, cnt))
1268                        continue;
1269                reset_enable_flags(dqopt, cnt);
1270
1271                /* Note: these are blocking operations */
1272                remove_dquot_ref(sb, cnt);
1273                invalidate_dquots(sb, cnt);
1274                if (info_dirty(&dqopt->info[cnt]))
1275                        dqopt->ops[cnt]->write_file_info(sb, cnt);
1276                if (dqopt->ops[cnt]->free_file_info)
1277                        dqopt->ops[cnt]->free_file_info(sb, cnt);
1278                put_quota_format(dqopt->info[cnt].dqi_format);
1279
1280                fput(dqopt->files[cnt]);
1281                dqopt->files[cnt] = (struct file *)NULL;
1282                dqopt->info[cnt].dqi_flags = 0;
1283                dqopt->info[cnt].dqi_igrace = 0;
1284                dqopt->info[cnt].dqi_bgrace = 0;
1285                dqopt->ops[cnt] = NULL;
1286        }
1287        up(&dqopt->dqoff_sem);
1288out:
1289        unlock_kernel();
1290        return 0;
1291}
1292
1293int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
1294{
1295        struct file *f = NULL;
1296        struct inode *inode;
1297        struct quota_info *dqopt = sb_dqopt(sb);
1298        struct quota_format_type *fmt = find_quota_format(format_id);
1299        int error;
1300
1301        if (!fmt)
1302                return -ESRCH;
1303        if (is_enabled(dqopt, type)) {
1304                error = -EBUSY;
1305                goto out_fmt;
1306        }
1307
1308        down(&dqopt->dqoff_sem);
1309
1310        f = filp_open(path, O_RDWR, 0600);
1311
1312        error = PTR_ERR(f);
1313        if (IS_ERR(f))
1314                goto out_lock;
1315        dqopt->files[type] = f;
1316        error = -EIO;
1317        if (!f->f_op || !f->f_op->read || !f->f_op->write)
1318                goto out_f;
1319        error = security_ops->quota_on(f);
1320        if (error)
1321                goto out_f;
1322        inode = f->f_dentry->d_inode;
1323        error = -EACCES;
1324        if (!S_ISREG(inode->i_mode))
1325                goto out_f;
1326        error = -EINVAL;
1327        if (!fmt->qf_ops->check_quota_file(sb, type))
1328                goto out_f;
1329        /* We don't want quota on quota files */
1330        dquot_drop(inode);
1331        inode->i_flags |= S_NOQUOTA;
1332
1333        dqopt->ops[type] = fmt->qf_ops;
1334        dqopt->info[type].dqi_format = fmt;
1335        if ((error = dqopt->ops[type]->read_file_info(sb, type)) < 0)
1336                goto out_f;
1337        set_enable_flags(dqopt, type);
1338
1339        add_dquot_ref(sb, type);
1340
1341        up(&dqopt->dqoff_sem);
1342        return 0;
1343
1344out_f:
1345        if (f)
1346                filp_close(f, NULL);
1347        dqopt->files[type] = NULL;
1348out_lock:
1349        up(&dqopt->dqoff_sem);
1350out_fmt:
1351        put_quota_format(fmt);
1352
1353        return error; 
1354}
1355
1356/* Generic routine for getting common part of quota structure */
1357static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
1358{
1359        struct mem_dqblk *dm = &dquot->dq_dqb;
1360
1361        di->dqb_bhardlimit = dm->dqb_bhardlimit;
1362        di->dqb_bsoftlimit = dm->dqb_bsoftlimit;
1363        di->dqb_curspace = dm->dqb_curspace;
1364        di->dqb_ihardlimit = dm->dqb_ihardlimit;
1365        di->dqb_isoftlimit = dm->dqb_isoftlimit;
1366        di->dqb_curinodes = dm->dqb_curinodes;
1367        di->dqb_btime = dm->dqb_btime;
1368        di->dqb_itime = dm->dqb_itime;
1369        di->dqb_valid = QIF_ALL;
1370}
1371
1372int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di)
1373{
1374        struct dquot *dquot = dqget(sb, id, type);
1375
1376        if (!dquot)
1377                return -EINVAL;
1378        do_get_dqblk(dquot, di);
1379        dqput(dquot);
1380        return 0;
1381}
1382
1383/* Generic routine for setting common part of quota structure */
1384static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
1385{
1386        struct mem_dqblk *dm = &dquot->dq_dqb;
1387        int check_blim = 0, check_ilim = 0;
1388
1389        if (di->dqb_valid & QIF_SPACE) {
1390                dm->dqb_curspace = di->dqb_curspace;
1391                check_blim = 1;
1392        }
1393        if (di->dqb_valid & QIF_BLIMITS) {
1394                dm->dqb_bsoftlimit = di->dqb_bsoftlimit;
1395                dm->dqb_bhardlimit = di->dqb_bhardlimit;
1396                check_blim = 1;
1397        }
1398        if (di->dqb_valid & QIF_INODES) {
1399                dm->dqb_curinodes = di->dqb_curinodes;
1400                check_ilim = 1;
1401        }
1402        if (di->dqb_valid & QIF_ILIMITS) {
1403                dm->dqb_isoftlimit = di->dqb_isoftlimit;
1404                dm->dqb_ihardlimit = di->dqb_ihardlimit;
1405                check_ilim = 1;
1406        }
1407        if (di->dqb_valid & QIF_BTIME)
1408                dm->dqb_btime = di->dqb_btime;
1409        if (di->dqb_valid & QIF_ITIME)
1410                dm->dqb_itime = di->dqb_itime;
1411
1412        if (check_blim) {
1413                if (!dm->dqb_bsoftlimit || toqb(dm->dqb_curspace) < dm->dqb_bsoftlimit) {
1414                        dm->dqb_btime = 0;
1415                        dquot->dq_flags &= ~DQ_BLKS;
1416                }
1417                else if (!(di->dqb_valid & QIF_BTIME))  /* Set grace only if user hasn't provided his own... */
1418                        dm->dqb_btime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
1419        }
1420        if (check_ilim) {
1421                if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) {
1422                        dm->dqb_itime = 0;
1423                        dquot->dq_flags &= ~DQ_INODES;
1424                }
1425                else if (!(di->dqb_valid & QIF_ITIME))  /* Set grace only if user hasn't provided his own... */
1426                        dm->dqb_itime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
1427        }
1428        if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit)
1429                dquot->dq_flags &= ~DQ_FAKE;
1430        else
1431                dquot->dq_flags |= DQ_FAKE;
1432        dquot->dq_flags |= DQ_MOD;
1433}
1434
1435int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di)
1436{
1437        struct dquot *dquot = dqget(sb, id, type);
1438
1439        if (!dquot)
1440                return -EINVAL;
1441        do_set_dqblk(dquot, di);
1442        dqput(dquot);
1443        return 0;
1444}
1445
1446/* Generic routine for getting common part of quota file information */
1447int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
1448{
1449        struct mem_dqinfo *mi = sb_dqopt(sb)->info + type;
1450
1451        ii->dqi_bgrace = mi->dqi_bgrace;
1452        ii->dqi_igrace = mi->dqi_igrace;
1453        ii->dqi_flags = mi->dqi_flags & DQF_MASK;
1454        ii->dqi_valid = IIF_ALL;
1455        return 0;
1456}
1457
1458/* Generic routine for setting common part of quota file information */
1459int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
1460{
1461        struct mem_dqinfo *mi = sb_dqopt(sb)->info + type;
1462
1463        if (ii->dqi_valid & IIF_BGRACE)
1464                mi->dqi_bgrace = ii->dqi_bgrace;
1465        if (ii->dqi_valid & IIF_IGRACE)
1466                mi->dqi_igrace = ii->dqi_igrace;
1467        if (ii->dqi_valid & IIF_FLAGS)
1468                mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | (ii->dqi_flags & DQF_MASK);
1469        mark_info_dirty(mi);
1470        return 0;
1471}
1472
1473struct quotactl_ops vfs_quotactl_ops = {
1474        .quota_on       = vfs_quota_on,
1475        .quota_off      = vfs_quota_off,
1476        .quota_sync     = vfs_quota_sync,
1477        .get_info       = vfs_get_dqinfo,
1478        .set_info       = vfs_set_dqinfo,
1479        .get_dqblk      = vfs_get_dqblk,
1480        .set_dqblk      = vfs_set_dqblk
1481};
1482
1483static ctl_table fs_dqstats_table[] = {
1484        {FS_DQ_LOOKUPS, "lookups", &dqstats.lookups, sizeof(int), 0444, NULL, &proc_dointvec},
1485        {FS_DQ_DROPS, "drops", &dqstats.drops, sizeof(int), 0444, NULL, &proc_dointvec},
1486        {FS_DQ_READS, "reads", &dqstats.reads, sizeof(int), 0444, NULL, &proc_dointvec},
1487        {FS_DQ_WRITES, "writes", &dqstats.writes, sizeof(int), 0444, NULL, &proc_dointvec},
1488        {FS_DQ_CACHE_HITS, "cache_hits", &dqstats.cache_hits, sizeof(int), 0444, NULL, &proc_dointvec},
1489        {FS_DQ_ALLOCATED, "allocated_dquots", &dqstats.allocated_dquots, sizeof(int), 0444, NULL, &proc_dointvec},
1490        {FS_DQ_FREE, "free_dquots", &dqstats.free_dquots, sizeof(int), 0444, NULL, &proc_dointvec},
1491        {FS_DQ_SYNCS, "syncs", &dqstats.syncs, sizeof(int), 0444, NULL, &proc_dointvec},
1492        {},
1493};
1494
1495static ctl_table fs_table[] = {
1496        {FS_DQSTATS, "quota", NULL, 0, 0555, fs_dqstats_table},
1497        {},
1498};
1499
1500static ctl_table sys_table[] = {
1501        {CTL_FS, "fs", NULL, 0, 0555, fs_table},
1502        {},
1503};
1504
1505static int __init dquot_init(void)
1506{
1507        int i;
1508
1509        register_sysctl_table(sys_table, 0);
1510        for (i = 0; i < NR_DQHASH; i++)
1511                INIT_LIST_HEAD(dquot_hash + i);
1512        printk(KERN_NOTICE "VFS: Disk quotas v%s\n", __DQUOT_VERSION__);
1513
1514        return 0;
1515}
1516__initcall(dquot_init);
1517
1518EXPORT_SYMBOL(register_quota_format);
1519EXPORT_SYMBOL(unregister_quota_format);
1520EXPORT_SYMBOL(dqstats);
1521
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.