OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [dquot.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.