linux-old/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 dquots with dq_count > 0 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 * (C) Copyright 1994 - 1997 Marco van Wieringen 
  49 */
  50
  51#include <linux/errno.h>
  52#include <linux/kernel.h>
  53#include <linux/fs.h>
  54#include <linux/sched.h>
  55#include <linux/types.h>
  56#include <linux/string.h>
  57#include <linux/fcntl.h>
  58#include <linux/stat.h>
  59#include <linux/tty.h>
  60#include <linux/file.h>
  61#include <linux/slab.h>
  62#include <linux/smp_lock.h>
  63#include <linux/init.h>
  64
  65#include <asm/uaccess.h>
  66
  67#define __DQUOT_VERSION__       "dquot_6.4.0"
  68
  69int nr_dquots, nr_free_dquots;
  70
  71static char *quotatypes[] = INITQFNAMES;
  72
  73static inline struct quota_mount_options *sb_dqopt(struct super_block *sb)
  74{
  75        return &sb->s_dquot;
  76}
  77
  78/*
  79 * Dquot List Management:
  80 * The quota code uses three lists for dquot management: the inuse_list,
  81 * free_dquots, and dquot_hash[] array. A single dquot structure may be
  82 * on all three lists, depending on its current state.
  83 *
  84 * All dquots are placed to the end of inuse_list when first created, and this
  85 * list is used for the sync and invalidate operations, which must look
  86 * at every dquot.
  87 *
  88 * Unused dquots (dq_count == 0) are added to the free_dquots list when
  89 * freed, and this list is searched whenever we need an available dquot.
  90 * Dquots are removed from the list as soon as they are used again, and
  91 * nr_free_dquots gives the number of dquots on the list. When dquot is
  92 * invalidated it's completely released from memory.
  93 *
  94 * Dquots with a specific identity (device, type and id) are placed on
  95 * one of the dquot_hash[] hash chains. The provides an efficient search
  96 * mechanism to locate a specific dquot.
  97 */
  98
  99/*
 100 * Note that any operation which operates on dquot data (ie. dq_dqb) mustn't
 101 * block while it's updating/reading it. Otherwise races would occur.
 102 *
 103 * Locked dquots might not be referenced in inodes - operations like
 104 * add_dquot_space() does dqduplicate() and would complain. Currently
 105 * dquot it locked only once in its existence - when it's being read
 106 * to memory on first dqget() and at that time it can't be referenced
 107 * from inode. Write operations on dquots don't hold dquot lock as they
 108 * copy data to internal buffers before writing anyway and copying as well
 109 * as any data update should be atomic. Also nobody can change used
 110 * entries in dquot structure as this is done only when quota is destroyed
 111 * and invalidate_dquots() waits for dquot to have dq_count == 0.
 112 */
 113
 114static LIST_HEAD(inuse_list);
 115static LIST_HEAD(free_dquots);
 116static struct list_head dquot_hash[NR_DQHASH];
 117
 118static struct dqstats dqstats;
 119
 120static void dqput(struct dquot *);
 121static struct dquot *dqduplicate(struct dquot *);
 122
 123static inline char is_enabled(struct quota_mount_options *dqopt, short type)
 124{
 125        switch (type) {
 126                case USRQUOTA:
 127                        return((dqopt->flags & DQUOT_USR_ENABLED) != 0);
 128                case GRPQUOTA:
 129                        return((dqopt->flags & DQUOT_GRP_ENABLED) != 0);
 130        }
 131        return(0);
 132}
 133
 134static inline char sb_has_quota_enabled(struct super_block *sb, short type)
 135{
 136        return is_enabled(sb_dqopt(sb), type);
 137}
 138
 139static inline int const hashfn(kdev_t dev, unsigned int id, short type)
 140{
 141        return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
 142}
 143
 144static inline void insert_dquot_hash(struct dquot *dquot)
 145{
 146        struct list_head *head = dquot_hash + hashfn(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
 147        list_add(&dquot->dq_hash, head);
 148}
 149
 150static inline void remove_dquot_hash(struct dquot *dquot)
 151{
 152        list_del(&dquot->dq_hash);
 153        INIT_LIST_HEAD(&dquot->dq_hash);
 154}
 155
 156static inline struct dquot *find_dquot(unsigned int hashent, kdev_t dev, unsigned int id, short type)
 157{
 158        struct list_head *head;
 159        struct dquot *dquot;
 160
 161        for (head = dquot_hash[hashent].next; head != dquot_hash+hashent; head = head->next) {
 162                dquot = list_entry(head, struct dquot, dq_hash);
 163                if (dquot->dq_dev == dev && dquot->dq_id == id && dquot->dq_type == type)
 164                        return dquot;
 165        }
 166        return NODQUOT;
 167}
 168
 169/* Add a dquot to the head of the free list */
 170static inline void put_dquot_head(struct dquot *dquot)
 171{
 172        list_add(&dquot->dq_free, &free_dquots);
 173        nr_free_dquots++;
 174}
 175
 176/* Add a dquot to the tail of the free list */
 177static inline void put_dquot_last(struct dquot *dquot)
 178{
 179        list_add(&dquot->dq_free, free_dquots.prev);
 180        nr_free_dquots++;
 181}
 182
 183/* Move dquot to the head of free list (it must be already on it) */
 184static inline void move_dquot_head(struct dquot *dquot)
 185{
 186        list_del(&dquot->dq_free);
 187        list_add(&dquot->dq_free, &free_dquots);
 188}
 189
 190static inline void remove_free_dquot(struct dquot *dquot)
 191{
 192        if (list_empty(&dquot->dq_free))
 193                return;
 194        list_del(&dquot->dq_free);
 195        INIT_LIST_HEAD(&dquot->dq_free);
 196        nr_free_dquots--;
 197}
 198
 199static inline void put_inuse(struct dquot *dquot)
 200{
 201        /* We add to the back of inuse list so we don't have to restart
 202         * when traversing this list and we block */
 203        list_add(&dquot->dq_inuse, inuse_list.prev);
 204        nr_dquots++;
 205}
 206
 207static inline void remove_inuse(struct dquot *dquot)
 208{
 209        nr_dquots--;
 210        list_del(&dquot->dq_inuse);
 211}
 212
 213static void __wait_on_dquot(struct dquot *dquot)
 214{
 215        DECLARE_WAITQUEUE(wait, current);
 216
 217        add_wait_queue(&dquot->dq_wait_lock, &wait);
 218repeat:
 219        set_current_state(TASK_UNINTERRUPTIBLE);
 220        if (dquot->dq_flags & DQ_LOCKED) {
 221                schedule();
 222                goto repeat;
 223        }
 224        remove_wait_queue(&dquot->dq_wait_lock, &wait);
 225        current->state = TASK_RUNNING;
 226}
 227
 228static inline void wait_on_dquot(struct dquot *dquot)
 229{
 230        if (dquot->dq_flags & DQ_LOCKED)
 231                __wait_on_dquot(dquot);
 232}
 233
 234static inline void lock_dquot(struct dquot *dquot)
 235{
 236        wait_on_dquot(dquot);
 237        dquot->dq_flags |= DQ_LOCKED;
 238}
 239
 240static inline void unlock_dquot(struct dquot *dquot)
 241{
 242        dquot->dq_flags &= ~DQ_LOCKED;
 243        wake_up(&dquot->dq_wait_lock);
 244}
 245
 246static void __wait_dquot_unused(struct dquot *dquot)
 247{
 248        DECLARE_WAITQUEUE(wait, current);
 249
 250        add_wait_queue(&dquot->dq_wait_free, &wait);
 251repeat:
 252        set_current_state(TASK_UNINTERRUPTIBLE);
 253        if (dquot->dq_count) {
 254                schedule();
 255                goto repeat;
 256        }
 257        remove_wait_queue(&dquot->dq_wait_free, &wait);
 258        current->state = TASK_RUNNING;
 259}
 260
 261/*
 262 *      We don't have to be afraid of deadlocks as we never have quotas on quota files...
 263 */
 264static void write_dquot(struct dquot *dquot)
 265{
 266        short type = dquot->dq_type;
 267        struct file *filp;
 268        mm_segment_t fs;
 269        loff_t offset;
 270        ssize_t ret;
 271        struct semaphore *sem = &dquot->dq_sb->s_dquot.dqio_sem;
 272        struct dqblk dqbuf;
 273
 274        down(sem);
 275        filp = dquot->dq_sb->s_dquot.files[type];
 276        offset = dqoff(dquot->dq_id);
 277        fs = get_fs();
 278        set_fs(KERNEL_DS);
 279
 280        /*
 281         * Note: clear the DQ_MOD flag unconditionally,
 282         * so we don't loop forever on failure.
 283         */
 284        memcpy(&dqbuf, &dquot->dq_dqb, sizeof(struct dqblk));
 285        dquot->dq_flags &= ~DQ_MOD;
 286        ret = 0;
 287        if (filp)
 288                ret = filp->f_op->write(filp, (char *)&dqbuf, 
 289                                        sizeof(struct dqblk), &offset);
 290        if (ret != sizeof(struct dqblk))
 291                printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
 292                        kdevname(dquot->dq_dev));
 293
 294        set_fs(fs);
 295        up(sem);
 296        dqstats.writes++;
 297}
 298
 299static void read_dquot(struct dquot *dquot)
 300{
 301        short type = dquot->dq_type;
 302        struct file *filp;
 303        mm_segment_t fs;
 304        loff_t offset;
 305
 306        filp = dquot->dq_sb->s_dquot.files[type];
 307        if (filp == (struct file *)NULL)
 308                return;
 309
 310        lock_dquot(dquot);
 311        if (!dquot->dq_sb)      /* Invalidated quota? */
 312                goto out_lock;
 313        /* Now we are sure filp is valid - the dquot isn't invalidated */
 314        down(&dquot->dq_sb->s_dquot.dqio_sem);
 315        offset = dqoff(dquot->dq_id);
 316        fs = get_fs();
 317        set_fs(KERNEL_DS);
 318        filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset);
 319        up(&dquot->dq_sb->s_dquot.dqio_sem);
 320        set_fs(fs);
 321
 322        if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
 323            dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
 324                dquot->dq_flags |= DQ_FAKE;
 325        dqstats.reads++;
 326out_lock:
 327        unlock_dquot(dquot);
 328}
 329
 330/* Invalidate all dquots on the list, wait for all users. Note that this function is called
 331 * after quota is disabled so no new quota might be created. As we only insert to the end of
 332 * inuse list, we don't have to restart searching... */
 333static void invalidate_dquots(struct super_block *sb, short type)
 334{
 335        struct dquot *dquot;
 336        struct list_head *head;
 337
 338restart:
 339        for (head = inuse_list.next; head != &inuse_list; head = head->next) {
 340                dquot = list_entry(head, struct dquot, dq_inuse);
 341                if (dquot->dq_sb != sb)
 342                        continue;
 343                if (dquot->dq_type != type)
 344                        continue;
 345                dquot->dq_flags |= DQ_INVAL;
 346                if (dquot->dq_count)
 347                        /*
 348                         *  Wait for any users of quota. As we have already cleared the flags in
 349                         *  superblock and cleared all pointers from inodes we are assured
 350                         *  that there will be no new users of this quota.
 351                         */
 352                        __wait_dquot_unused(dquot);
 353                /* Quota now have no users and it has been written on last dqput() */
 354                remove_dquot_hash(dquot);
 355                remove_free_dquot(dquot);
 356                remove_inuse(dquot);
 357                kmem_cache_free(dquot_cachep, dquot);
 358                goto restart;
 359        }
 360}
 361
 362int sync_dquots(kdev_t dev, short type)
 363{
 364        struct list_head *head;
 365        struct dquot *dquot;
 366
 367        lock_kernel();
 368restart:
 369        for (head = inuse_list.next; head != &inuse_list; head = head->next) {
 370                dquot = list_entry(head, struct dquot, dq_inuse);
 371                if (dev && dquot->dq_dev != dev)
 372                        continue;
 373                if (type != -1 && dquot->dq_type != type)
 374                        continue;
 375                if (!dquot->dq_sb)      /* Invalidated? */
 376                        continue;
 377                if (!(dquot->dq_flags & (DQ_MOD | DQ_LOCKED)))
 378                        continue;
 379                /* Raise use count so quota won't be invalidated. We can't use dqduplicate() as it does too many tests */
 380                dquot->dq_count++;
 381                if (dquot->dq_flags & DQ_LOCKED)
 382                        wait_on_dquot(dquot);
 383                if (dquot->dq_flags & DQ_MOD)
 384                        write_dquot(dquot);
 385                dqput(dquot);
 386                goto restart;
 387        }
 388        dqstats.syncs++;
 389        unlock_kernel();
 390        return 0;
 391}
 392
 393/* Free unused dquots from cache */
 394static void prune_dqcache(int count)
 395{
 396        struct list_head *head;
 397        struct dquot *dquot;
 398
 399        head = free_dquots.prev;
 400        while (head != &free_dquots && count) {
 401                dquot = list_entry(head, struct dquot, dq_free);
 402                remove_dquot_hash(dquot);
 403                remove_free_dquot(dquot);
 404                remove_inuse(dquot);
 405                kmem_cache_free(dquot_cachep, dquot);
 406                count--;
 407                head = free_dquots.prev;
 408        }
 409}
 410
 411int shrink_dqcache_memory(int priority, unsigned int gfp_mask)
 412{
 413        lock_kernel();
 414        prune_dqcache(nr_free_dquots / (priority + 1));
 415        unlock_kernel();
 416        return kmem_cache_shrink(dquot_cachep);
 417}
 418
 419/* NOTE: If you change this function please check whether dqput_blocks() works right... */
 420static void dqput(struct dquot *dquot)
 421{
 422        if (!dquot)
 423                return;
 424        if (!dquot->dq_count) {
 425                printk("VFS: dqput: trying to free free dquot\n");
 426                printk("VFS: device %s, dquot of %s %d\n",
 427                        kdevname(dquot->dq_dev), quotatypes[dquot->dq_type],
 428                        dquot->dq_id);
 429                return;
 430        }
 431
 432        dqstats.drops++;
 433we_slept:
 434        if (dquot->dq_count > 1) {
 435                /* We have more than one user... We can simply decrement use count */
 436                dquot->dq_count--;
 437                return;
 438        }
 439        if (dquot->dq_flags & DQ_MOD) {
 440                write_dquot(dquot);
 441                goto we_slept;
 442        }
 443
 444        /* sanity check */
 445        if (!list_empty(&dquot->dq_free)) {
 446                printk(KERN_ERR "dqput: dquot already on free list??\n");
 447                dquot->dq_count--;      /* J.K. Just decrementing use count seems safer... */
 448                return;
 449        }
 450        dquot->dq_count--;
 451        /* If dquot is going to be invalidated invalidate_dquots() is going to free it so */
 452        if (!(dquot->dq_flags & DQ_INVAL))
 453                put_dquot_last(dquot);  /* Place at end of LRU free queue */
 454        wake_up(&dquot->dq_wait_free);
 455}
 456
 457static struct dquot *get_empty_dquot(void)
 458{
 459        struct dquot *dquot;
 460
 461        dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL);
 462        if(!dquot)
 463                return NODQUOT;
 464
 465        memset((caddr_t)dquot, 0, sizeof(struct dquot));
 466        init_waitqueue_head(&dquot->dq_wait_free);
 467        init_waitqueue_head(&dquot->dq_wait_lock);
 468        INIT_LIST_HEAD(&dquot->dq_free);
 469        INIT_LIST_HEAD(&dquot->dq_inuse);
 470        INIT_LIST_HEAD(&dquot->dq_hash);
 471        dquot->dq_count = 1;
 472        /* all dquots go on the inuse_list */
 473        put_inuse(dquot);
 474
 475        return dquot;
 476}
 477
 478static struct dquot *dqget(struct super_block *sb, unsigned int id, short type)
 479{
 480        unsigned int hashent = hashfn(sb->s_dev, id, type);
 481        struct dquot *dquot, *empty = NODQUOT;
 482        struct quota_mount_options *dqopt = sb_dqopt(sb);
 483
 484we_slept:
 485        if (!is_enabled(dqopt, type)) {
 486                if (empty)
 487                        dqput(empty);
 488                return NODQUOT;
 489        }
 490
 491        if ((dquot = find_dquot(hashent, sb->s_dev, id, type)) == NODQUOT) {
 492                if (empty == NODQUOT) {
 493                        if ((empty = get_empty_dquot()) == NODQUOT)
 494                                schedule();     /* Try to wait for a moment... */
 495                        goto we_slept;
 496                }
 497                dquot = empty;
 498                dquot->dq_id = id;
 499                dquot->dq_type = type;
 500                dquot->dq_dev = sb->s_dev;
 501                dquot->dq_sb = sb;
 502                /* hash it first so it can be found */
 503                insert_dquot_hash(dquot);
 504                read_dquot(dquot);
 505        } else {
 506                if (!dquot->dq_count++)
 507                        remove_free_dquot(dquot);
 508                dqstats.cache_hits++;
 509                wait_on_dquot(dquot);
 510                if (empty)
 511                        dqput(empty);
 512        }
 513
 514        if (!dquot->dq_sb) {    /* Has somebody invalidated entry under us? */
 515                printk(KERN_ERR "VFS: dqget(): Quota invalidated in dqget()!\n");
 516                dqput(dquot);
 517                return NODQUOT;
 518        }
 519        dquot->dq_referenced++;
 520        dqstats.lookups++;
 521
 522        return dquot;
 523}
 524
 525static struct dquot *dqduplicate(struct dquot *dquot)
 526{
 527        if (dquot == NODQUOT)
 528                return NODQUOT;
 529        dquot->dq_count++;
 530        if (!dquot->dq_sb) {
 531                printk(KERN_ERR "VFS: dqduplicate(): Invalidated quota to be duplicated!\n");
 532                dquot->dq_count--;
 533                return NODQUOT;
 534        }
 535        if (dquot->dq_flags & DQ_LOCKED)
 536                printk(KERN_ERR "VFS: dqduplicate(): Locked quota to be duplicated!\n");
 537        dquot->dq_referenced++;
 538        dqstats.lookups++;
 539        return dquot;
 540}
 541
 542static int dqinit_needed(struct inode *inode, short type)
 543{
 544        int cnt;
 545
 546        if (IS_NOQUOTA(inode))
 547                return 0;
 548        if (type != -1)
 549                return inode->i_dquot[type] == NODQUOT;
 550        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 551                if (inode->i_dquot[cnt] == NODQUOT)
 552                        return 1;
 553        return 0;
 554}
 555
 556static void add_dquot_ref(struct super_block *sb, short type)
 557{
 558        struct list_head *p;
 559
 560        if (!sb->dq_op)
 561                return; /* nothing to do */
 562
 563restart:
 564        file_list_lock();
 565        for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
 566                struct file *filp = list_entry(p, struct file, f_list);
 567                struct inode *inode = filp->f_dentry->d_inode;
 568                if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
 569                        struct vfsmount *mnt = mntget(filp->f_vfsmnt);
 570                        struct dentry *dentry = dget(filp->f_dentry);
 571                        file_list_unlock();
 572                        sb->dq_op->initialize(inode, type);
 573                        dput(dentry);
 574                        mntput(mnt);
 575                        /* As we may have blocked we had better restart... */
 576                        goto restart;
 577                }
 578        }
 579        file_list_unlock();
 580}
 581
 582/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
 583static inline int dqput_blocks(struct dquot *dquot)
 584{
 585        if (dquot->dq_count == 1)
 586                return 1;
 587        return 0;
 588}
 589
 590/* Remove references to dquots from inode - add dquot to list for freeing if needed */
 591int remove_inode_dquot_ref(struct inode *inode, short type, struct list_head *tofree_head)
 592{
 593        struct dquot *dquot = inode->i_dquot[type];
 594        int cnt;
 595
 596        inode->i_dquot[type] = NODQUOT;
 597        /* any other quota in use? */
 598        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 599                if (inode->i_dquot[cnt] != NODQUOT)
 600                        goto put_it;
 601        }
 602        inode->i_flags &= ~S_QUOTA;
 603put_it:
 604        if (dquot != NODQUOT) {
 605                if (dqput_blocks(dquot)) {
 606                        if (dquot->dq_count != 1)
 607                                printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", dquot->dq_count);
 608                        list_add(&dquot->dq_free, tofree_head); /* As dquot must have currently users it can't be on the free list... */
 609                        return 1;
 610                }
 611                else
 612                        dqput(dquot);   /* We have guaranteed we won't block */
 613        }
 614        return 0;
 615}
 616
 617/* Free list of dquots - called from inode.c */
 618void put_dquot_list(struct list_head *tofree_head)
 619{
 620        struct list_head *act_head;
 621        struct dquot *dquot;
 622
 623        lock_kernel();
 624        act_head = tofree_head->next;
 625        /* So now we have dquots on the list... Just free them */
 626        while (act_head != tofree_head) {
 627                dquot = list_entry(act_head, struct dquot, dq_free);
 628                act_head = act_head->next;
 629                list_del(&dquot->dq_free);      /* Remove dquot from the list so we won't have problems... */
 630                INIT_LIST_HEAD(&dquot->dq_free);
 631                dqput(dquot);
 632        }
 633        unlock_kernel();
 634}
 635
 636static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
 637{
 638        dquot->dq_curinodes += number;
 639        dquot->dq_flags |= DQ_MOD;
 640}
 641
 642static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
 643{
 644        dquot->dq_curblocks += number;
 645        dquot->dq_flags |= DQ_MOD;
 646}
 647
 648static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
 649{
 650        if (dquot->dq_curinodes > number)
 651                dquot->dq_curinodes -= number;
 652        else
 653                dquot->dq_curinodes = 0;
 654        if (dquot->dq_curinodes < dquot->dq_isoftlimit)
 655                dquot->dq_itime = (time_t) 0;
 656        dquot->dq_flags &= ~DQ_INODES;
 657        dquot->dq_flags |= DQ_MOD;
 658}
 659
 660static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
 661{
 662        if (dquot->dq_curblocks > number)
 663                dquot->dq_curblocks -= number;
 664        else
 665                dquot->dq_curblocks = 0;
 666        if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
 667                dquot->dq_btime = (time_t) 0;
 668        dquot->dq_flags &= ~DQ_BLKS;
 669        dquot->dq_flags |= DQ_MOD;
 670}
 671
 672static inline int need_print_warning(struct dquot *dquot, int flag)
 673{
 674        switch (dquot->dq_type) {
 675                case USRQUOTA:
 676                        return current->fsuid == dquot->dq_id && !(dquot->dq_flags & flag);
 677                case GRPQUOTA:
 678                        return in_group_p(dquot->dq_id) && !(dquot->dq_flags & flag);
 679        }
 680        return 0;
 681}
 682
 683/* Values of warnings */
 684#define NOWARN 0
 685#define IHARDWARN 1
 686#define ISOFTLONGWARN 2
 687#define ISOFTWARN 3
 688#define BHARDWARN 4
 689#define BSOFTLONGWARN 5
 690#define BSOFTWARN 6
 691
 692/* Print warning to user which exceeded quota */
 693static void print_warning(struct dquot *dquot, const char warntype)
 694{
 695        char *msg = NULL;
 696        int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS :
 697          ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES : 0);
 698
 699        if (!need_print_warning(dquot, flag))
 700                return;
 701        dquot->dq_flags |= flag;
 702        tty_write_message(current->tty, (char *)bdevname(dquot->dq_sb->s_dev));
 703        if (warntype == ISOFTWARN || warntype == BSOFTWARN)
 704                tty_write_message(current->tty, ": warning, ");
 705        else
 706                tty_write_message(current->tty, ": write failed, ");
 707        tty_write_message(current->tty, quotatypes[dquot->dq_type]);
 708        switch (warntype) {
 709                case IHARDWARN:
 710                        msg = " file limit reached.\n";
 711                        break;
 712                case ISOFTLONGWARN:
 713                        msg = " file quota exceeded too long.\n";
 714                        break;
 715                case ISOFTWARN:
 716                        msg = " file quota exceeded.\n";
 717                        break;
 718                case BHARDWARN:
 719                        msg = " block limit reached.\n";
 720                        break;
 721                case BSOFTLONGWARN:
 722                        msg = " block quota exceeded too long.\n";
 723                        break;
 724                case BSOFTWARN:
 725                        msg = " block quota exceeded.\n";
 726                        break;
 727        }
 728        tty_write_message(current->tty, msg);
 729}
 730
 731static inline void flush_warnings(struct dquot **dquots, char *warntype)
 732{
 733        int i;
 734
 735        for (i = 0; i < MAXQUOTAS; i++)
 736                if (dquots[i] != NODQUOT && warntype[i] != NOWARN)
 737                        print_warning(dquots[i], warntype[i]);
 738}
 739
 740static inline char ignore_hardlimit(struct dquot *dquot)
 741{
 742        return capable(CAP_SYS_RESOURCE) && !dquot->dq_sb->s_dquot.rsquash[dquot->dq_type];
 743}
 744
 745static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
 746{
 747        *warntype = NOWARN;
 748        if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
 749                return QUOTA_OK;
 750
 751        if (dquot->dq_ihardlimit &&
 752           (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit &&
 753            !ignore_hardlimit(dquot)) {
 754                *warntype = IHARDWARN;
 755                return NO_QUOTA;
 756        }
 757
 758        if (dquot->dq_isoftlimit &&
 759           (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
 760            dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime &&
 761            !ignore_hardlimit(dquot)) {
 762                *warntype = ISOFTLONGWARN;
 763                return NO_QUOTA;
 764        }
 765
 766        if (dquot->dq_isoftlimit &&
 767           (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
 768            dquot->dq_itime == 0) {
 769                *warntype = ISOFTWARN;
 770                dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[dquot->dq_type];
 771        }
 772
 773        return QUOTA_OK;
 774}
 775
 776static int check_bdq(struct dquot *dquot, ulong blocks, char prealloc, char *warntype)
 777{
 778        *warntype = 0;
 779        if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
 780                return QUOTA_OK;
 781
 782        if (dquot->dq_bhardlimit &&
 783           (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit &&
 784            !ignore_hardlimit(dquot)) {
 785                if (!prealloc)
 786                        *warntype = BHARDWARN;
 787                return NO_QUOTA;
 788        }
 789
 790        if (dquot->dq_bsoftlimit &&
 791           (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
 792            dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime &&
 793            !ignore_hardlimit(dquot)) {
 794                if (!prealloc)
 795                        *warntype = BSOFTLONGWARN;
 796                return NO_QUOTA;
 797        }
 798
 799        if (dquot->dq_bsoftlimit &&
 800           (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
 801            dquot->dq_btime == 0) {
 802                if (!prealloc) {
 803                        *warntype = BSOFTWARN;
 804                        dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[dquot->dq_type];
 805                }
 806                else
 807                        /*
 808                         * We don't allow preallocation to exceed softlimit so exceeding will
 809                         * be always printed
 810                         */
 811                        return NO_QUOTA;
 812        }
 813
 814        return QUOTA_OK;
 815}
 816
 817/*
 818 * Initialize a dquot-struct with new quota info. This is used by the
 819 * system call interface functions.
 820 */ 
 821static int set_dqblk(struct super_block *sb, int id, short type, int flags, struct dqblk *dqblk)
 822{
 823        struct dquot *dquot;
 824        int error = -EFAULT;
 825        struct dqblk dq_dqblk;
 826
 827        if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk)))
 828                return error;
 829
 830        if (sb && (dquot = dqget(sb, id, type)) != NODQUOT) {
 831                /* We can't block while changing quota structure... */
 832                if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
 833                        dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
 834                        dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
 835                        dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
 836                        dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
 837                }
 838
 839                if ((flags & SET_QUOTA) || (flags & SET_USE)) {
 840                        if (dquot->dq_isoftlimit &&
 841                            dquot->dq_curinodes < dquot->dq_isoftlimit &&
 842                            dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
 843                                dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[type];
 844                        dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
 845                        if (dquot->dq_curinodes < dquot->dq_isoftlimit)
 846                                dquot->dq_flags &= ~DQ_INODES;
 847                        if (dquot->dq_bsoftlimit &&
 848                            dquot->dq_curblocks < dquot->dq_bsoftlimit &&
 849                            dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
 850                                dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[type];
 851                        dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
 852                        if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
 853                                dquot->dq_flags &= ~DQ_BLKS;
 854                }
 855
 856                if (id == 0) {
 857                        dquot->dq_sb->s_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
 858                        dquot->dq_sb->s_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
 859                }
 860
 861                if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
 862                    dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
 863                        dquot->dq_flags |= DQ_FAKE;
 864                else
 865                        dquot->dq_flags &= ~DQ_FAKE;
 866
 867                dquot->dq_flags |= DQ_MOD;
 868                dqput(dquot);
 869        }
 870        return 0;
 871}
 872
 873static int get_quota(struct super_block *sb, int id, short type, struct dqblk *dqblk)
 874{
 875        struct dquot *dquot;
 876        struct dqblk data;
 877        int error = -ESRCH;
 878
 879        if (!sb || !sb_has_quota_enabled(sb, type))
 880                goto out;
 881        dquot = dqget(sb, id, type);
 882        if (dquot == NODQUOT)
 883                goto out;
 884
 885        memcpy(&data, &dquot->dq_dqb, sizeof(struct dqblk));        /* We copy data to preserve them from changing */
 886        dqput(dquot);
 887        error = -EFAULT;
 888        if (dqblk && !copy_to_user(dqblk, &data, sizeof(struct dqblk)))
 889                error = 0;
 890out:
 891        return error;
 892}
 893
 894static int get_stats(caddr_t addr)
 895{
 896        int error = -EFAULT;
 897        struct dqstats stats;
 898
 899        dqstats.allocated_dquots = nr_dquots;
 900        dqstats.free_dquots = nr_free_dquots;
 901
 902        /* make a copy, in case we page-fault in user space */
 903        memcpy(&stats, &dqstats, sizeof(struct dqstats));
 904        if (!copy_to_user(addr, &stats, sizeof(struct dqstats)))
 905                error = 0;
 906        return error;
 907}
 908
 909static int quota_root_squash(struct super_block *sb, short type, int *addr)
 910{
 911        int new_value, error;
 912
 913        if (!sb)
 914                return(-ENODEV);
 915
 916        error = -EFAULT;
 917        if (!copy_from_user(&new_value, addr, sizeof(int))) {
 918                sb_dqopt(sb)->rsquash[type] = new_value;
 919                error = 0;
 920        }
 921        return error;
 922}
 923
 924#if 0   /* We are not going to support filesystems without i_blocks... */
 925/*
 926 * This is a simple algorithm that calculates the size of a file in blocks.
 927 * This is only used on filesystems that do not have an i_blocks count.
 928 */
 929static u_long isize_to_blocks(loff_t isize, size_t blksize_bits)
 930{
 931        u_long blocks;
 932        u_long indirect;
 933
 934        if (!blksize_bits)
 935                blksize_bits = BLOCK_SIZE_BITS;
 936        blocks = (isize >> blksize_bits) + ((isize & ~((1 << blksize_bits)-1)) ? 1 : 0);
 937        if (blocks > 10) {
 938                indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
 939                if (blocks > (10 + 256)) {
 940                        indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
 941                        if (blocks > (10 + 256 + (256 << 8)))
 942                                indirect++; /* triple indirect blocks */
 943                }
 944                blocks += indirect;
 945        }
 946        return blocks;
 947}
 948#endif
 949
 950/*
 951 * Externally referenced functions through dquot_operations in inode.
 952 *
 953 * Note: this is a blocking operation.
 954 */
 955void dquot_initialize(struct inode *inode, short type)
 956{
 957        struct dquot *dquot[MAXQUOTAS];
 958        unsigned int id = 0;
 959        short cnt;
 960
 961        if (IS_NOQUOTA(inode))
 962                return;
 963        /* Build list of quotas to initialize... We can block here */
 964        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 965                dquot[cnt] = NODQUOT;
 966                if (type != -1 && cnt != type)
 967                        continue;
 968                if (!sb_has_quota_enabled(inode->i_sb, cnt))
 969                        continue;
 970                if (inode->i_dquot[cnt] == NODQUOT) {
 971                        switch (cnt) {
 972                                case USRQUOTA:
 973                                        id = inode->i_uid;
 974                                        break;
 975                                case GRPQUOTA:
 976                                        id = inode->i_gid;
 977                                        break;
 978                        }
 979                        dquot[cnt] = dqget(inode->i_sb, id, cnt);
 980                }
 981        }
 982        /* NOBLOCK START: Here we shouldn't block */
 983        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 984                if (dquot[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt) || inode->i_dquot[cnt] != NODQUOT)
 985                        continue;
 986                inode->i_dquot[cnt] = dquot[cnt];
 987                dquot[cnt] = NODQUOT;
 988                inode->i_flags |= S_QUOTA;
 989        }
 990        /* NOBLOCK END */
 991        /* Put quotas which we didn't use */
 992        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 993                if (dquot[cnt] != NODQUOT)
 994                        dqput(dquot[cnt]);
 995}
 996
 997/*
 998 * Release all quota for the specified inode.
 999 *
1000 * Note: this is a blocking operation.
1001 */
1002void dquot_drop(struct inode *inode)
1003{
1004        struct dquot *dquot;
1005        short cnt;
1006
1007        inode->i_flags &= ~S_QUOTA;
1008        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1009                if (inode->i_dquot[cnt] == NODQUOT)
1010                        continue;
1011                dquot = inode->i_dquot[cnt];
1012                inode->i_dquot[cnt] = NODQUOT;
1013                dqput(dquot);
1014        }
1015}
1016
1017/*
1018 * This operation can block, but only after everything is updated
1019 */
1020int dquot_alloc_block(struct inode *inode, unsigned long number, char warn)
1021{
1022        int cnt, ret = NO_QUOTA;
1023        struct dquot *dquot[MAXQUOTAS];
1024        char warntype[MAXQUOTAS];
1025
1026        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1027                dquot[cnt] = NODQUOT;
1028                warntype[cnt] = NOWARN;
1029        }
1030        /* NOBLOCK Start */
1031        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1032                dquot[cnt] = dqduplicate(inode->i_dquot[cnt]);
1033                if (dquot[cnt] == NODQUOT)
1034                        continue;
1035                if (check_bdq(dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA)
1036                        goto warn_put_all;
1037        }
1038        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1039                if (dquot[cnt] == NODQUOT)
1040                        continue;
1041                dquot_incr_blocks(dquot[cnt], number);
1042        }
1043        inode->i_blocks += number << (BLOCK_SIZE_BITS - 9);
1044        /* NOBLOCK End */
1045        ret = QUOTA_OK;
1046warn_put_all:
1047        flush_warnings(dquot, warntype);
1048        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1049                if (dquot[cnt] != NODQUOT)
1050                        dqput(dquot[cnt]);
1051        return ret;
1052}
1053
1054/*
1055 * This operation can block, but only after everything is updated
1056 */
1057int dquot_alloc_inode(const struct inode *inode, unsigned long number)
1058{
1059        int cnt, ret = NO_QUOTA;
1060        struct dquot *dquot[MAXQUOTAS];
1061        char warntype[MAXQUOTAS];
1062
1063        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1064                dquot[cnt] = NODQUOT;
1065                warntype[cnt] = NOWARN;
1066        }
1067        /* NOBLOCK Start */
1068        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1069                dquot[cnt] = dqduplicate(inode -> i_dquot[cnt]);
1070                if (dquot[cnt] == NODQUOT)
1071                        continue;
1072                if (check_idq(dquot[cnt], number, warntype+cnt) == NO_QUOTA)
1073                        goto warn_put_all;
1074        }
1075
1076        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1077                if (dquot[cnt] == NODQUOT)
1078                        continue;
1079                dquot_incr_inodes(dquot[cnt], number);
1080        }
1081        /* NOBLOCK End */
1082        ret = QUOTA_OK;
1083warn_put_all:
1084        flush_warnings(dquot, warntype);
1085        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1086                if (dquot[cnt] != NODQUOT)
1087                        dqput(dquot[cnt]);
1088        return ret;
1089}
1090
1091/*
1092 * This is a non-blocking operation.
1093 */
1094void dquot_free_block(struct inode *inode, unsigned long number)
1095{
1096        unsigned short cnt;
1097        struct dquot *dquot;
1098
1099        /* NOBLOCK Start */
1100        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1101                dquot = dqduplicate(inode->i_dquot[cnt]);
1102                if (dquot == NODQUOT)
1103                        continue;
1104                dquot_decr_blocks(dquot, number);
1105                dqput(dquot);
1106        }
1107        inode->i_blocks -= number << (BLOCK_SIZE_BITS - 9);
1108        /* NOBLOCK End */
1109}
1110
1111/*
1112 * This is a non-blocking operation.
1113 */
1114void dquot_free_inode(const struct inode *inode, unsigned long number)
1115{
1116        unsigned short cnt;
1117        struct dquot *dquot;
1118
1119        /* NOBLOCK Start */
1120        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1121                dquot = dqduplicate(inode->i_dquot[cnt]);
1122                if (dquot == NODQUOT)
1123                        continue;
1124                dquot_decr_inodes(dquot, number);
1125                dqput(dquot);
1126        }
1127        /* NOBLOCK End */
1128}
1129
1130/*
1131 * Transfer the number of inode and blocks from one diskquota to an other.
1132 *
1133 * This operation can block, but only after everything is updated
1134 */
1135int dquot_transfer(struct inode *inode, struct iattr *iattr)
1136{
1137        unsigned long blocks;
1138        struct dquot *transfer_from[MAXQUOTAS];
1139        struct dquot *transfer_to[MAXQUOTAS];
1140        int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,
1141            chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
1142        char warntype[MAXQUOTAS];
1143
1144        /* Clear the arrays */
1145        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1146                transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
1147                warntype[cnt] = NOWARN;
1148        }
1149        /* First build the transfer_to list - here we can block on reading of dquots... */
1150        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1151                if (!sb_has_quota_enabled(inode->i_sb, cnt))
1152                        continue;
1153                switch (cnt) {
1154                        case USRQUOTA:
1155                                if (!chuid)
1156                                        continue;
1157                                transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_uid, cnt);
1158                                break;
1159                        case GRPQUOTA:
1160                                if (!chgid)
1161                                        continue;
1162                                transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_gid, cnt);
1163                                break;
1164                }
1165        }
1166        /* NOBLOCK START: From now on we shouldn't block */
1167        blocks = (inode->i_blocks >> 1);
1168        /* Build the transfer_from list and check the limits */
1169        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1170                /* The second test can fail when quotaoff is in progress... */
1171                if (transfer_to[cnt] == NODQUOT || !sb_has_quota_enabled(inode->i_sb, cnt))
1172                        continue;
1173                transfer_from[cnt] = dqduplicate(inode->i_dquot[cnt]);
1174                if (transfer_from[cnt] == NODQUOT)      /* Can happen on quotafiles (quota isn't initialized on them)... */
1175                        continue;
1176                if (check_idq(transfer_to[cnt], 1, warntype+cnt) == NO_QUOTA ||
1177                    check_bdq(transfer_to[cnt], blocks, 0, warntype+cnt) == NO_QUOTA)
1178                        goto warn_put_all;
1179        }
1180
1181        /*
1182         * Finally perform the needed transfer from transfer_from to transfer_to
1183         */
1184        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1185                /*
1186                 * Skip changes for same uid or gid or for non-existing quota-type.
1187                 */
1188                if (transfer_from[cnt] == NODQUOT || transfer_to[cnt] == NODQUOT)
1189                        continue;
1190
1191                dquot_decr_inodes(transfer_from[cnt], 1);
1192                dquot_decr_blocks(transfer_from[cnt], blocks);
1193
1194                dquot_incr_inodes(transfer_to[cnt], 1);
1195                dquot_incr_blocks(transfer_to[cnt], blocks);
1196
1197                if (inode->i_dquot[cnt] == NODQUOT)
1198                        BUG();
1199                inode->i_dquot[cnt] = transfer_to[cnt];
1200                /*
1201                 * We've got to release transfer_from[] twice - once for dquot_transfer() and
1202                 * once for inode. We don't want to release transfer_to[] as it's now placed in inode
1203                 */
1204                transfer_to[cnt] = transfer_from[cnt];
1205        }
1206        /* NOBLOCK END. From now on we can block as we wish */
1207        ret = QUOTA_OK;
1208warn_put_all:
1209        flush_warnings(transfer_to, warntype);
1210        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1211                if (transfer_to[cnt] != NODQUOT)
1212                        dqput(transfer_to[cnt]);
1213                if (transfer_from[cnt] != NODQUOT)
1214                        dqput(transfer_from[cnt]);
1215        }
1216        return ret;
1217}
1218
1219static int __init dquot_init(void)
1220{
1221        int i;
1222
1223        for (i = 0; i < NR_DQHASH; i++)
1224                INIT_LIST_HEAD(dquot_hash + i);
1225        printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
1226        return 0;
1227}
1228__initcall(dquot_init);
1229
1230/*
1231 * Definitions of diskquota operations.
1232 */
1233struct dquot_operations dquot_operations = {
1234        dquot_initialize,               /* mandatory */
1235        dquot_drop,                     /* mandatory */
1236        dquot_alloc_block,
1237        dquot_alloc_inode,
1238        dquot_free_block,
1239        dquot_free_inode,
1240        dquot_transfer
1241};
1242
1243static inline void set_enable_flags(struct quota_mount_options *dqopt, short type)
1244{
1245        switch (type) {
1246                case USRQUOTA:
1247                        dqopt->flags |= DQUOT_USR_ENABLED;
1248                        break;
1249                case GRPQUOTA:
1250                        dqopt->flags |= DQUOT_GRP_ENABLED;
1251                        break;
1252        }
1253}
1254
1255static inline void reset_enable_flags(struct quota_mount_options *dqopt, short type)
1256{
1257        switch (type) {
1258                case USRQUOTA:
1259                        dqopt->flags &= ~DQUOT_USR_ENABLED;
1260                        break;
1261                case GRPQUOTA:
1262                        dqopt->flags &= ~DQUOT_GRP_ENABLED;
1263                        break;
1264        }
1265}
1266
1267/* Function in inode.c - remove pointers to dquots in icache */
1268extern void remove_dquot_ref(struct super_block *, short);
1269
1270/*
1271 * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
1272 */
1273int quota_off(struct super_block *sb, short type)
1274{
1275        struct file *filp;
1276        short cnt;
1277        struct quota_mount_options *dqopt = sb_dqopt(sb);
1278
1279        lock_kernel();
1280        if (!sb)
1281                goto out;
1282
1283        /* We need to serialize quota_off() for device */
1284        down(&dqopt->dqoff_sem);
1285        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1286                if (type != -1 && cnt != type)
1287                        continue;
1288                if (!is_enabled(dqopt, cnt))
1289                        continue;
1290                reset_enable_flags(dqopt, cnt);
1291
1292                /* Note: these are blocking operations */
1293                remove_dquot_ref(sb, cnt);
1294                invalidate_dquots(sb, cnt);
1295
1296                filp = dqopt->files[cnt];
1297                dqopt->files[cnt] = (struct file *)NULL;
1298                dqopt->inode_expire[cnt] = 0;
1299                dqopt->block_expire[cnt] = 0;
1300                fput(filp);
1301        }       
1302        up(&dqopt->dqoff_sem);
1303out:
1304        unlock_kernel();
1305        return 0;
1306}
1307
1308static inline int check_quotafile_size(loff_t size)
1309{
1310        ulong blocks = size >> BLOCK_SIZE_BITS;
1311        size_t off = size & (BLOCK_SIZE - 1);
1312
1313        return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk));
1314}
1315
1316static int quota_on(struct super_block *sb, short type, char *path)
1317{
1318        struct file *f;
1319        struct inode *inode;
1320        struct dquot *dquot;
1321        struct quota_mount_options *dqopt = sb_dqopt(sb);
1322        char *tmp;
1323        int error;
1324
1325        if (is_enabled(dqopt, type))
1326                return -EBUSY;
1327
1328        down(&dqopt->dqoff_sem);
1329        tmp = getname(path);
1330        error = PTR_ERR(tmp);
1331        if (IS_ERR(tmp))
1332                goto out_lock;
1333
1334        f = filp_open(tmp, O_RDWR, 0600);
1335        putname(tmp);
1336
1337        error = PTR_ERR(f);
1338        if (IS_ERR(f))
1339                goto out_lock;
1340        error = -EIO;
1341        if (!f->f_op || !f->f_op->read || !f->f_op->write)
1342                goto out_f;
1343        inode = f->f_dentry->d_inode;
1344        error = -EACCES;
1345        if (!S_ISREG(inode->i_mode))
1346                goto out_f;
1347        error = -EINVAL;
1348        if (inode->i_size == 0 || !check_quotafile_size(inode->i_size))
1349                goto out_f;
1350        /* We don't want quota on quota files */
1351        dquot_drop(inode);
1352        inode->i_flags |= S_NOQUOTA;
1353
1354        dqopt->files[type] = f;
1355        sb->dq_op = &dquot_operations;
1356        set_enable_flags(dqopt, type);
1357
1358        dquot = dqget(sb, 0, type);
1359        dqopt->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME;
1360        dqopt->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME;
1361        dqput(dquot);
1362
1363        add_dquot_ref(sb, type);
1364
1365        up(&dqopt->dqoff_sem);
1366        return 0;
1367
1368out_f:
1369        filp_close(f, NULL);
1370out_lock:
1371        up(&dqopt->dqoff_sem);
1372
1373        return error; 
1374}
1375
1376/*
1377 * This is the system call interface. This communicates with
1378 * the user-level programs. Currently this only supports diskquota
1379 * calls. Maybe we need to add the process quotas etc. in the future,
1380 * but we probably should use rlimits for that.
1381 */
1382asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
1383{
1384        int cmds = 0, type = 0, flags = 0;
1385        kdev_t dev;
1386        struct super_block *sb = NULL;
1387        int ret = -EINVAL;
1388
1389        lock_kernel();
1390        cmds = cmd >> SUBCMDSHIFT;
1391        type = cmd & SUBCMDMASK;
1392
1393        if ((u_int) type >= MAXQUOTAS)
1394                goto out;
1395        if (id & ~0xFFFF)
1396                goto out;
1397
1398        ret = -EPERM;
1399        switch (cmds) {
1400                case Q_SYNC:
1401                case Q_GETSTATS:
1402                        break;
1403                case Q_GETQUOTA:
1404                        if (((type == USRQUOTA && current->euid != id) ||
1405                             (type == GRPQUOTA && !in_egroup_p(id))) &&
1406                            !capable(CAP_SYS_ADMIN))
1407                                goto out;
1408                        break;
1409                default:
1410                        if (!capable(CAP_SYS_ADMIN))
1411                                goto out;
1412        }
1413
1414        ret = -EINVAL;
1415        dev = NODEV;
1416        if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {
1417                mode_t mode;
1418                struct nameidata nd;
1419
1420                ret = user_path_walk(special, &nd);
1421                if (ret)
1422                        goto out;
1423
1424                dev = nd.dentry->d_inode->i_rdev;
1425                mode = nd.dentry->d_inode->i_mode;
1426                path_release(&nd);
1427
1428                ret = -ENOTBLK;
1429                if (!S_ISBLK(mode))
1430                        goto out;
1431                ret = -ENODEV;
1432                sb = get_super(dev);
1433                if (!sb)
1434                        goto out;
1435        }
1436
1437        ret = -EINVAL;
1438        switch (cmds) {
1439                case Q_QUOTAON:
1440                        ret = quota_on(sb, type, (char *) addr);
1441                        goto out;
1442                case Q_QUOTAOFF:
1443                        ret = quota_off(sb, type);
1444                        goto out;
1445                case Q_GETQUOTA:
1446                        ret = get_quota(sb, id, type, (struct dqblk *) addr);
1447                        goto out;
1448                case Q_SETQUOTA:
1449                        flags |= SET_QUOTA;
1450                        break;
1451                case Q_SETUSE:
1452                        flags |= SET_USE;
1453                        break;
1454                case Q_SETQLIM:
1455                        flags |= SET_QLIMIT;
1456                        break;
1457                case Q_SYNC:
1458                        ret = sync_dquots(dev, type);
1459                        goto out;
1460                case Q_GETSTATS:
1461                        ret = get_stats(addr);
1462                        goto out;
1463                case Q_RSQUASH:
1464                        ret = quota_root_squash(sb, type, (int *) addr);
1465                        goto out;
1466                default:
1467                        goto out;
1468        }
1469
1470        ret = -NODEV;
1471        if (sb && sb_has_quota_enabled(sb, type))
1472                ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr);
1473out:
1474        if (sb)
1475                drop_super(sb);
1476        unlock_kernel();
1477        return ret;
1478}
1479
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.