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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
3
 *
4
 * This program is free software; you can redistribute it and/or modify it
5
 * under the terms of version 2 of the GNU General Public License as
6
 * published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it would be useful, but
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * Further, this software is distributed without any warranty that it is
13
 * free of the rightful claim of any third person regarding infringement
14
 * or the like.  Any license provided herein, whether implied or
15
 * otherwise, applies only to this software file.  Patent licenses, if
16
 * any, provided herein do not apply to combinations of this program with
17
 * other software, or any other product whatsoever.
18
 *
19
 * You should have received a copy of the GNU General Public License along
20
 * with this program; if not, write the Free Software Foundation, Inc., 59
21
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22
 *
23
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24
 * Mountain View, CA  94043, or:
25
 *
26
 * http://www.sgi.com
27
 *
28
 * For further information regarding this notice, see:
29
 *
30
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31
 */
32
 
33
#include "xfs.h"
34
#include "xfs_fs.h"
35
#include "xfs_inum.h"
36
#include "xfs_log.h"
37
#include "xfs_trans.h"
38
#include "xfs_sb.h"
39
#include "xfs_ag.h"
40
#include "xfs_dir.h"
41
#include "xfs_dir2.h"
42
#include "xfs_alloc.h"
43
#include "xfs_dmapi.h"
44
#include "xfs_quota.h"
45
#include "xfs_mount.h"
46
#include "xfs_alloc_btree.h"
47
#include "xfs_bmap_btree.h"
48
#include "xfs_ialloc_btree.h"
49
#include "xfs_btree.h"
50
#include "xfs_ialloc.h"
51
#include "xfs_attr_sf.h"
52
#include "xfs_dir_sf.h"
53
#include "xfs_dir2_sf.h"
54
#include "xfs_dinode.h"
55
#include "xfs_inode.h"
56
#include "xfs_bmap.h"
57
#include "xfs_bit.h"
58
#include "xfs_rtalloc.h"
59
#include "xfs_error.h"
60
#include "xfs_itable.h"
61
#include "xfs_rw.h"
62
#include "xfs_acl.h"
63
#include "xfs_cap.h"
64
#include "xfs_mac.h"
65
#include "xfs_attr.h"
66
#include "xfs_buf_item.h"
67
#include "xfs_trans_priv.h"
68
 
69
#include "xfs_qm.h"
70
 
71
STATIC void     xfs_trans_alloc_dqinfo(xfs_trans_t *);
72
 
73
/*
74
 * Add the locked dquot to the transaction.
75
 * The dquot must be locked, and it cannot be associated with any
76
 * transaction.
77
 */
78
void
79
xfs_trans_dqjoin(
80
        xfs_trans_t     *tp,
81
        xfs_dquot_t     *dqp)
82
{
83
        xfs_dq_logitem_t    *lp;
84
 
85
        ASSERT(! XFS_DQ_IS_ADDEDTO_TRX(tp, dqp));
86
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
87
        ASSERT(XFS_DQ_IS_LOGITEM_INITD(dqp));
88
        lp = &dqp->q_logitem;
89
 
90
        /*
91
         * Get a log_item_desc to point at the new item.
92
         */
93
        (void) xfs_trans_add_item(tp, (xfs_log_item_t*)(lp));
94
 
95
        /*
96
         * Initialize i_transp so we can later determine if this dquot is
97
         * associated with this transaction.
98
         */
99
        dqp->q_transp = tp;
100
}
101
 
102
 
103
/*
104
 * This is called to mark the dquot as needing
105
 * to be logged when the transaction is committed.  The dquot must
106
 * already be associated with the given transaction.
107
 * Note that it marks the entire transaction as dirty. In the ordinary
108
 * case, this gets called via xfs_trans_commit, after the transaction
109
 * is already dirty. However, there's nothing stop this from getting
110
 * called directly, as done by xfs_qm_scall_setqlim. Hence, the TRANS_DIRTY
111
 * flag.
112
 */
113
void
114
xfs_trans_log_dquot(
115
        xfs_trans_t     *tp,
116
        xfs_dquot_t     *dqp)
117
{
118
        xfs_log_item_desc_t     *lidp;
119
 
120
        ASSERT(XFS_DQ_IS_ADDEDTO_TRX(tp, dqp));
121
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
122
 
123
        lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(&dqp->q_logitem));
124
        ASSERT(lidp != NULL);
125
 
126
        tp->t_flags |= XFS_TRANS_DIRTY;
127
        lidp->lid_flags |= XFS_LID_DIRTY;
128
}
129
 
130
/*
131
 * Carry forward whatever is left of the quota blk reservation to
132
 * the spanky new transaction
133
 */
134
STATIC void
135
xfs_trans_dup_dqinfo(
136
        xfs_trans_t     *otp,
137
        xfs_trans_t     *ntp)
138
{
139
        xfs_dqtrx_t     *oq, *nq;
140
        int             i,j;
141
        xfs_dqtrx_t     *oqa, *nqa;
142
 
143
        if (!otp->t_dqinfo)
144
                return;
145
 
146
        xfs_trans_alloc_dqinfo(ntp);
147
        oqa = otp->t_dqinfo->dqa_usrdquots;
148
        nqa = ntp->t_dqinfo->dqa_usrdquots;
149
 
150
        /*
151
         * Because the quota blk reservation is carried forward,
152
         * it is also necessary to carry forward the DQ_DIRTY flag.
153
         */
154
        if(otp->t_flags & XFS_TRANS_DQ_DIRTY)
155
                ntp->t_flags |= XFS_TRANS_DQ_DIRTY;
156
 
157
        for (j = 0; j < 2; j++) {
158
                for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
159
                        if (oqa[i].qt_dquot == NULL)
160
                                break;
161
                        oq = &oqa[i];
162
                        nq = &nqa[i];
163
 
164
                        nq->qt_dquot = oq->qt_dquot;
165
                        nq->qt_bcount_delta = nq->qt_icount_delta = 0;
166
                        nq->qt_rtbcount_delta = 0;
167
 
168
                        /*
169
                         * Transfer whatever is left of the reservations.
170
                         */
171
                        nq->qt_blk_res = oq->qt_blk_res - oq->qt_blk_res_used;
172
                        oq->qt_blk_res = oq->qt_blk_res_used;
173
 
174
                        nq->qt_rtblk_res = oq->qt_rtblk_res -
175
                                oq->qt_rtblk_res_used;
176
                        oq->qt_rtblk_res = oq->qt_rtblk_res_used;
177
 
178
                        nq->qt_ino_res = oq->qt_ino_res - oq->qt_ino_res_used;
179
                        oq->qt_ino_res = oq->qt_ino_res_used;
180
 
181
                }
182
                oqa = otp->t_dqinfo->dqa_grpdquots;
183
                nqa = ntp->t_dqinfo->dqa_grpdquots;
184
        }
185
}
186
 
187
/*
188
 * Wrap around mod_dquot to account for both user and group quotas.
189
 */
190
void
191
xfs_trans_mod_dquot_byino(
192
        xfs_trans_t     *tp,
193
        xfs_inode_t     *ip,
194
        uint            field,
195
        long            delta)
196
{
197
        xfs_mount_t     *mp;
198
 
199
        ASSERT(tp);
200
        mp = tp->t_mountp;
201
 
202
        if (!XFS_IS_QUOTA_ON(mp) ||
203
            ip->i_ino == mp->m_sb.sb_uquotino ||
204
            ip->i_ino == mp->m_sb.sb_gquotino)
205
                return;
206
 
207
        if (tp->t_dqinfo == NULL)
208
                xfs_trans_alloc_dqinfo(tp);
209
 
210
        if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) {
211
                (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
212
        }
213
        if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
214
                (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
215
        }
216
}
217
 
218
STATIC xfs_dqtrx_t *
219
xfs_trans_get_dqtrx(
220
        xfs_trans_t     *tp,
221
        xfs_dquot_t     *dqp)
222
{
223
        int             i;
224
        xfs_dqtrx_t     *qa;
225
 
226
        for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
227
                qa = XFS_QM_DQP_TO_DQACCT(tp, dqp);
228
 
229
                if (qa[i].qt_dquot == NULL ||
230
                    qa[i].qt_dquot == dqp) {
231
                        return (&qa[i]);
232
                }
233
        }
234
 
235
        return (NULL);
236
}
237
 
238
/*
239
 * Make the changes in the transaction structure.
240
 * The moral equivalent to xfs_trans_mod_sb().
241
 * We don't touch any fields in the dquot, so we don't care
242
 * if it's locked or not (most of the time it won't be).
243
 */
244
void
245
xfs_trans_mod_dquot(
246
        xfs_trans_t     *tp,
247
        xfs_dquot_t     *dqp,
248
        uint            field,
249
        long            delta)
250
{
251
        xfs_dqtrx_t     *qtrx;
252
 
253
        ASSERT(tp);
254
        qtrx = NULL;
255
 
256
        if (tp->t_dqinfo == NULL)
257
                xfs_trans_alloc_dqinfo(tp);
258
        /*
259
         * Find either the first free slot or the slot that belongs
260
         * to this dquot.
261
         */
262
        qtrx = xfs_trans_get_dqtrx(tp, dqp);
263
        ASSERT(qtrx);
264
        if (qtrx->qt_dquot == NULL)
265
                qtrx->qt_dquot = dqp;
266
 
267
        switch (field) {
268
 
269
                /*
270
                 * regular disk blk reservation
271
                 */
272
              case XFS_TRANS_DQ_RES_BLKS:
273
                qtrx->qt_blk_res += (ulong)delta;
274
                break;
275
 
276
                /*
277
                 * inode reservation
278
                 */
279
              case XFS_TRANS_DQ_RES_INOS:
280
                qtrx->qt_ino_res += (ulong)delta;
281
                break;
282
 
283
                /*
284
                 * disk blocks used.
285
                 */
286
              case XFS_TRANS_DQ_BCOUNT:
287
                if (qtrx->qt_blk_res && delta > 0) {
288
                        qtrx->qt_blk_res_used += (ulong)delta;
289
                        ASSERT(qtrx->qt_blk_res >= qtrx->qt_blk_res_used);
290
                }
291
                qtrx->qt_bcount_delta += delta;
292
                break;
293
 
294
              case XFS_TRANS_DQ_DELBCOUNT:
295
                qtrx->qt_delbcnt_delta += delta;
296
                break;
297
 
298
                /*
299
                 * Inode Count
300
                 */
301
              case XFS_TRANS_DQ_ICOUNT:
302
                if (qtrx->qt_ino_res && delta > 0) {
303
                        qtrx->qt_ino_res_used += (ulong)delta;
304
                        ASSERT(qtrx->qt_ino_res >= qtrx->qt_ino_res_used);
305
                }
306
                qtrx->qt_icount_delta += delta;
307
                break;
308
 
309
                /*
310
                 * rtblk reservation
311
                 */
312
              case XFS_TRANS_DQ_RES_RTBLKS:
313
                qtrx->qt_rtblk_res += (ulong)delta;
314
                break;
315
 
316
                /*
317
                 * rtblk count
318
                 */
319
              case XFS_TRANS_DQ_RTBCOUNT:
320
                if (qtrx->qt_rtblk_res && delta > 0) {
321
                        qtrx->qt_rtblk_res_used += (ulong)delta;
322
                        ASSERT(qtrx->qt_rtblk_res >= qtrx->qt_rtblk_res_used);
323
                }
324
                qtrx->qt_rtbcount_delta += delta;
325
                break;
326
 
327
              case XFS_TRANS_DQ_DELRTBCOUNT:
328
                qtrx->qt_delrtb_delta += delta;
329
                break;
330
 
331
              default:
332
                ASSERT(0);
333
        }
334
        tp->t_flags |= XFS_TRANS_DQ_DIRTY;
335
}
336
 
337
 
338
/*
339
 * Given an array of dqtrx structures, lock all the dquots associated
340
 * and join them to the transaction, provided they have been modified.
341
 * We know that the highest number of dquots (of one type - usr OR grp),
342
 * involved in a transaction is 2 and that both usr and grp combined - 3.
343
 * So, we don't attempt to make this very generic.
344
 */
345
STATIC void
346
xfs_trans_dqlockedjoin(
347
        xfs_trans_t     *tp,
348
        xfs_dqtrx_t     *q)
349
{
350
        ASSERT(q[0].qt_dquot != NULL);
351
        if (q[1].qt_dquot == NULL) {
352
                xfs_dqlock(q[0].qt_dquot);
353
                xfs_trans_dqjoin(tp, q[0].qt_dquot);
354
        } else {
355
                ASSERT(XFS_QM_TRANS_MAXDQS == 2);
356
                xfs_dqlock2(q[0].qt_dquot, q[1].qt_dquot);
357
                xfs_trans_dqjoin(tp, q[0].qt_dquot);
358
                xfs_trans_dqjoin(tp, q[1].qt_dquot);
359
        }
360
}
361
 
362
 
363
/*
364
 * Called by xfs_trans_commit() and similar in spirit to
365
 * xfs_trans_apply_sb_deltas().
366
 * Go thru all the dquots belonging to this transaction and modify the
367
 * INCORE dquot to reflect the actual usages.
368
 * Unreserve just the reservations done by this transaction.
369
 * dquot is still left locked at exit.
370
 */
371
void
372
xfs_trans_apply_dquot_deltas(
373
        xfs_trans_t             *tp)
374
{
375
        int                     i, j;
376
        xfs_dquot_t             *dqp;
377
        xfs_dqtrx_t             *qtrx, *qa;
378
        xfs_disk_dquot_t        *d;
379
        long                    totalbdelta;
380
        long                    totalrtbdelta;
381
 
382
        if (! (tp->t_flags & XFS_TRANS_DQ_DIRTY))
383
                return;
384
 
385
        ASSERT(tp->t_dqinfo);
386
        qa = tp->t_dqinfo->dqa_usrdquots;
387
        for (j = 0; j < 2; j++) {
388
                if (qa[0].qt_dquot == NULL) {
389
                        qa = tp->t_dqinfo->dqa_grpdquots;
390
                        continue;
391
                }
392
 
393
                /*
394
                 * Lock all of the dquots and join them to the transaction.
395
                 */
396
                xfs_trans_dqlockedjoin(tp, qa);
397
 
398
                for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
399
                        qtrx = &qa[i];
400
                        /*
401
                         * The array of dquots is filled
402
                         * sequentially, not sparsely.
403
                         */
404
                        if ((dqp = qtrx->qt_dquot) == NULL)
405
                                break;
406
 
407
                        ASSERT(XFS_DQ_IS_LOCKED(dqp));
408
                        ASSERT(XFS_DQ_IS_ADDEDTO_TRX(tp, dqp));
409
 
410
                        /*
411
                         * adjust the actual number of blocks used
412
                         */
413
                        d = &dqp->q_core;
414
 
415
                        /*
416
                         * The issue here is - sometimes we don't make a blkquota
417
                         * reservation intentionally to be fair to users
418
                         * (when the amount is small). On the other hand,
419
                         * delayed allocs do make reservations, but that's
420
                         * outside of a transaction, so we have no
421
                         * idea how much was really reserved.
422
                         * So, here we've accumulated delayed allocation blks and
423
                         * non-delay blks. The assumption is that the
424
                         * delayed ones are always reserved (outside of a
425
                         * transaction), and the others may or may not have
426
                         * quota reservations.
427
                         */
428
                        totalbdelta = qtrx->qt_bcount_delta +
429
                                qtrx->qt_delbcnt_delta;
430
                        totalrtbdelta = qtrx->qt_rtbcount_delta +
431
                                qtrx->qt_delrtb_delta;
432
#ifdef QUOTADEBUG
433
                        if (totalbdelta < 0)
434
                                ASSERT(INT_GET(d->d_bcount, ARCH_CONVERT) >=
435
                                       (xfs_qcnt_t) -totalbdelta);
436
 
437
                        if (totalrtbdelta < 0)
438
                                ASSERT(INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
439
                                       (xfs_qcnt_t) -totalrtbdelta);
440
 
441
                        if (qtrx->qt_icount_delta < 0)
442
                                ASSERT(INT_GET(d->d_icount, ARCH_CONVERT) >=
443
                                       (xfs_qcnt_t) -qtrx->qt_icount_delta);
444
#endif
445
                        if (totalbdelta)
446
                                INT_MOD(d->d_bcount, ARCH_CONVERT, (xfs_qcnt_t)totalbdelta);
447
 
448
                        if (qtrx->qt_icount_delta)
449
                                INT_MOD(d->d_icount, ARCH_CONVERT, (xfs_qcnt_t)qtrx->qt_icount_delta);
450
 
451
                        if (totalrtbdelta)
452
                                INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta);
453
 
454
                        /*
455
                         * Start/reset the timer(s) if needed.
456
                         */
457
                        xfs_qm_adjust_dqtimers(tp->t_mountp, d);
458
 
459
                        dqp->dq_flags |= XFS_DQ_DIRTY;
460
                        /*
461
                         * add this to the list of items to get logged
462
                         */
463
                        xfs_trans_log_dquot(tp, dqp);
464
                        /*
465
                         * Take off what's left of the original reservation.
466
                         * In case of delayed allocations, there's no
467
                         * reservation that a transaction structure knows of.
468
                         */
469
                        if (qtrx->qt_blk_res != 0) {
470
                                if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
471
                                        if (qtrx->qt_blk_res >
472
                                            qtrx->qt_blk_res_used)
473
                                                dqp->q_res_bcount -= (xfs_qcnt_t)
474
                                                        (qtrx->qt_blk_res -
475
                                                         qtrx->qt_blk_res_used);
476
                                        else
477
                                                dqp->q_res_bcount -= (xfs_qcnt_t)
478
                                                        (qtrx->qt_blk_res_used -
479
                                                         qtrx->qt_blk_res);
480
                                }
481
                        } else {
482
                                /*
483
                                 * These blks were never reserved, either inside
484
                                 * a transaction or outside one (in a delayed
485
                                 * allocation). Also, this isn't always a
486
                                 * negative number since we sometimes
487
                                 * deliberately skip quota reservations.
488
                                 */
489
                                if (qtrx->qt_bcount_delta) {
490
                                        dqp->q_res_bcount +=
491
                                              (xfs_qcnt_t)qtrx->qt_bcount_delta;
492
                                }
493
                        }
494
                        /*
495
                         * Adjust the RT reservation.
496
                         */
497
                        if (qtrx->qt_rtblk_res != 0) {
498
                                if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
499
                                        if (qtrx->qt_rtblk_res >
500
                                            qtrx->qt_rtblk_res_used)
501
                                               dqp->q_res_rtbcount -= (xfs_qcnt_t)
502
                                                       (qtrx->qt_rtblk_res -
503
                                                        qtrx->qt_rtblk_res_used);
504
                                        else
505
                                               dqp->q_res_rtbcount -= (xfs_qcnt_t)
506
                                                       (qtrx->qt_rtblk_res_used -
507
                                                        qtrx->qt_rtblk_res);
508
                                }
509
                        } else {
510
                                if (qtrx->qt_rtbcount_delta)
511
                                        dqp->q_res_rtbcount +=
512
                                            (xfs_qcnt_t)qtrx->qt_rtbcount_delta;
513
                        }
514
 
515
                        /*
516
                         * Adjust the inode reservation.
517
                         */
518
                        if (qtrx->qt_ino_res != 0) {
519
                                ASSERT(qtrx->qt_ino_res >=
520
                                       qtrx->qt_ino_res_used);
521
                                if (qtrx->qt_ino_res > qtrx->qt_ino_res_used)
522
                                        dqp->q_res_icount -= (xfs_qcnt_t)
523
                                                (qtrx->qt_ino_res -
524
                                                 qtrx->qt_ino_res_used);
525
                        } else {
526
                                if (qtrx->qt_icount_delta)
527
                                        dqp->q_res_icount +=
528
                                            (xfs_qcnt_t)qtrx->qt_icount_delta;
529
                        }
530
 
531
 
532
#ifdef QUOTADEBUG
533
                        if (qtrx->qt_rtblk_res != 0)
534
                                cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
535
                                        (int) qtrx->qt_rtblk_res, dqp);
536
#endif
537
                        ASSERT(dqp->q_res_bcount >=
538
                                INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
539
                        ASSERT(dqp->q_res_icount >=
540
                                INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
541
                        ASSERT(dqp->q_res_rtbcount >=
542
                                INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT));
543
                }
544
                /*
545
                 * Do the group quotas next
546
                 */
547
                qa = tp->t_dqinfo->dqa_grpdquots;
548
        }
549
}
550
 
551
/*
552
 * Release the reservations, and adjust the dquots accordingly.
553
 * This is called only when the transaction is being aborted. If by
554
 * any chance we have done dquot modifications incore (ie. deltas) already,
555
 * we simply throw those away, since that's the expected behavior
556
 * when a transaction is curtailed without a commit.
557
 */
558
STATIC void
559
xfs_trans_unreserve_and_mod_dquots(
560
        xfs_trans_t             *tp)
561
{
562
        int                     i, j;
563
        xfs_dquot_t             *dqp;
564
        xfs_dqtrx_t             *qtrx, *qa;
565
        boolean_t               locked;
566
 
567
        if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY))
568
                return;
569
 
570
        qa = tp->t_dqinfo->dqa_usrdquots;
571
 
572
        for (j = 0; j < 2; j++) {
573
                for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
574
                        qtrx = &qa[i];
575
                        /*
576
                         * We assume that the array of dquots is filled
577
                         * sequentially, not sparsely.
578
                         */
579
                        if ((dqp = qtrx->qt_dquot) == NULL)
580
                                break;
581
                        /*
582
                         * Unreserve the original reservation. We don't care
583
                         * about the number of blocks used field, or deltas.
584
                         * Also we don't bother to zero the fields.
585
                         */
586
                        locked = B_FALSE;
587
                        if (qtrx->qt_blk_res) {
588
                                xfs_dqlock(dqp);
589
                                locked = B_TRUE;
590
                                dqp->q_res_bcount -=
591
                                        (xfs_qcnt_t)qtrx->qt_blk_res;
592
                        }
593
                        if (qtrx->qt_ino_res) {
594
                                if (!locked) {
595
                                        xfs_dqlock(dqp);
596
                                        locked = B_TRUE;
597
                                }
598
                                dqp->q_res_icount -=
599
                                        (xfs_qcnt_t)qtrx->qt_ino_res;
600
                        }
601
 
602
                        if (qtrx->qt_rtblk_res) {
603
                                if (!locked) {
604
                                        xfs_dqlock(dqp);
605
                                        locked = B_TRUE;
606
                                }
607
                                dqp->q_res_rtbcount -=
608
                                        (xfs_qcnt_t)qtrx->qt_rtblk_res;
609
                        }
610
                        if (locked)
611
                                xfs_dqunlock(dqp);
612
 
613
                }
614
                qa = tp->t_dqinfo->dqa_grpdquots;
615
        }
616
}
617
 
618
/*
619
 * This reserves disk blocks and inodes against a dquot.
620
 * Flags indicate if the dquot is to be locked here and also
621
 * if the blk reservation is for RT or regular blocks.
622
 * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
623
 * Returns EDQUOT if quota is exceeded.
624
 */
625
STATIC int
626
xfs_trans_dqresv(
627
        xfs_trans_t     *tp,
628
        xfs_dquot_t     *dqp,
629
        long            nblks,
630
        long            ninos,
631
        uint            flags)
632
{
633
        int             error;
634
        xfs_qcnt_t      hardlimit;
635
        xfs_qcnt_t      softlimit;
636
        time_t          btimer;
637
        xfs_qcnt_t      *resbcountp;
638
 
639
        if (! (flags & XFS_QMOPT_DQLOCK)) {
640
                xfs_dqlock(dqp);
641
        }
642
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
643
        if (flags & XFS_TRANS_DQ_RES_BLKS) {
644
                hardlimit = INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT);
645
                softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
646
                btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
647
                resbcountp = &dqp->q_res_bcount;
648
        } else {
649
                ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
650
                hardlimit = INT_GET(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT);
651
                softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
652
                btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
653
                resbcountp = &dqp->q_res_rtbcount;
654
        }
655
        error = 0;
656
 
657
        if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
658
            !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT) &&
659
            XFS_IS_QUOTA_ENFORCED(dqp->q_mount)) {
660
#ifdef QUOTADEBUG
661
                cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"
662
                          " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit);
663
#endif
664
                if (nblks > 0) {
665
                        /*
666
                         * dquot is locked already. See if we'd go over the
667
                         * hardlimit or exceed the timelimit if we allocate
668
                         * nblks.
669
                         */
670
                        if (hardlimit > 0ULL &&
671
                             (hardlimit <= nblks + *resbcountp)) {
672
                                error = EDQUOT;
673
                                goto error_return;
674
                        }
675
 
676
                        if (softlimit > 0ULL &&
677
                             (softlimit <= nblks + *resbcountp)) {
678
                                /*
679
                                 * If timer or warnings has expired,
680
                                 * return EDQUOT
681
                                 */
682
                                if ((btimer != 0 && get_seconds() > btimer) ||
683
                                    (!INT_ISZERO(dqp->q_core.d_bwarns, ARCH_CONVERT) &&
684
                                     INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
685
                                     XFS_QI_BWARNLIMIT(dqp->q_mount))) {
686
                                        error = EDQUOT;
687
                                        goto error_return;
688
                                }
689
                        }
690
                }
691
                if (ninos > 0) {
692
                        if (INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) > 0ULL &&
693
                            INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
694
                            INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)) {
695
                                error = EDQUOT;
696
                                goto error_return;
697
                        } else if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) > 0ULL &&
698
                                   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
699
                                   INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
700
                                /*
701
                                 * If timer or warnings has expired,
702
                                 * return EDQUOT
703
                                 */
704
                                if ((!INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) &&
705
                                     get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
706
                                    (!INT_ISZERO(dqp->q_core.d_iwarns, ARCH_CONVERT) &&
707
                                     INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
708
                                     XFS_QI_IWARNLIMIT(dqp->q_mount))) {
709
                                        error = EDQUOT;
710
                                        goto error_return;
711
                                }
712
                        }
713
                }
714
        }
715
 
716
        /*
717
         * Change the reservation, but not the actual usage.
718
         * Note that q_res_bcount = q_core.d_bcount + resv
719
         */
720
        (*resbcountp) += (xfs_qcnt_t)nblks;
721
        if (ninos != 0)
722
                dqp->q_res_icount += (xfs_qcnt_t)ninos;
723
 
724
        /*
725
         * note the reservation amt in the trans struct too,
726
         * so that the transaction knows how much was reserved by
727
         * it against this particular dquot.
728
         * We don't do this when we are reserving for a delayed allocation,
729
         * because we don't have the luxury of a transaction envelope then.
730
         */
731
        if (tp) {
732
                ASSERT(tp->t_dqinfo);
733
                ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
734
                if (nblks != 0)
735
                        xfs_trans_mod_dquot(tp, dqp,
736
                                            flags & XFS_QMOPT_RESBLK_MASK,
737
                                            nblks);
738
                if (ninos != 0)
739
                        xfs_trans_mod_dquot(tp, dqp,
740
                                            XFS_TRANS_DQ_RES_INOS,
741
                                            ninos);
742
        }
743
        ASSERT(dqp->q_res_bcount >= INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
744
        ASSERT(dqp->q_res_rtbcount >= INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT));
745
        ASSERT(dqp->q_res_icount >= INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
746
 
747
error_return:
748
        if (! (flags & XFS_QMOPT_DQLOCK)) {
749
                xfs_dqunlock(dqp);
750
        }
751
        return (error);
752
}
753
 
754
 
755
/*
756
 * Given a dquot(s), make disk block and/or inode reservations against them.
757
 * The fact that this does the reservation against both the usr and
758
 * grp quotas is important, because this follows a both-or-nothing
759
 * approach.
760
 *
761
 * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
762
 *         XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
763
 *         XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
764
 *         XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
765
 * dquots are unlocked on return, if they were not locked by caller.
766
 */
767
int
768
xfs_trans_reserve_quota_bydquots(
769
        xfs_trans_t     *tp,
770
        xfs_mount_t     *mp,
771
        xfs_dquot_t     *udqp,
772
        xfs_dquot_t     *gdqp,
773
        long            nblks,
774
        long            ninos,
775
        uint            flags)
776
{
777
        int             resvd;
778
 
779
        if (! XFS_IS_QUOTA_ON(mp))
780
                return (0);
781
 
782
        if (tp && tp->t_dqinfo == NULL)
783
                xfs_trans_alloc_dqinfo(tp);
784
 
785
        ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
786
        resvd = 0;
787
 
788
        if (udqp) {
789
                if (xfs_trans_dqresv(tp, udqp, nblks, ninos, flags))
790
                        return (EDQUOT);
791
                resvd = 1;
792
        }
793
 
794
        if (gdqp) {
795
                if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) {
796
                        /*
797
                         * can't do it, so backout previous reservation
798
                         */
799
                        if (resvd) {
800
                                xfs_trans_dqresv(tp, udqp,  -nblks, -ninos,
801
                                                 flags);
802
                        }
803
                        return (EDQUOT);
804
                }
805
        }
806
 
807
        /*
808
         * Didnt change anything critical, so, no need to log
809
         */
810
        return (0);
811
}
812
 
813
 
814
/*
815
 * Lock the dquot and change the reservation if we can.
816
 * This doesn't change the actual usage, just the reservation.
817
 * The inode sent in is locked.
818
 *
819
 * Returns 0 on success, EDQUOT or other errors otherwise
820
 */
821
STATIC int
822
xfs_trans_reserve_quota_nblks(
823
        xfs_trans_t     *tp,
824
        xfs_mount_t     *mp,
825
        xfs_inode_t     *ip,
826
        long            nblks,
827
        long            ninos,
828
        uint            type)
829
{
830
        int             error;
831
 
832
        if (!XFS_IS_QUOTA_ON(mp))
833
                return (0);
834
 
835
        ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
836
        ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
837
 
838
        ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
839
        ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
840
        ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||
841
               (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);
842
 
843
        /*
844
         * Reserve nblks against these dquots, with trans as the mediator.
845
         */
846
        error = xfs_trans_reserve_quota_bydquots(tp, mp,
847
                                                 ip->i_udquot, ip->i_gdquot,
848
                                                 nblks, ninos,
849
                                                 type);
850
        return (error);
851
}
852
 
853
/*
854
 * This routine is called to allocate a quotaoff log item.
855
 */
856
xfs_qoff_logitem_t *
857
xfs_trans_get_qoff_item(
858
        xfs_trans_t             *tp,
859
        xfs_qoff_logitem_t      *startqoff,
860
        uint                    flags)
861
{
862
        xfs_qoff_logitem_t      *q;
863
 
864
        ASSERT(tp != NULL);
865
 
866
        q = xfs_qm_qoff_logitem_init(tp->t_mountp, startqoff, flags);
867
        ASSERT(q != NULL);
868
 
869
        /*
870
         * Get a log_item_desc to point at the new item.
871
         */
872
        (void) xfs_trans_add_item(tp, (xfs_log_item_t*)q);
873
 
874
        return (q);
875
}
876
 
877
 
878
/*
879
 * This is called to mark the quotaoff logitem as needing
880
 * to be logged when the transaction is committed.  The logitem must
881
 * already be associated with the given transaction.
882
 */
883
void
884
xfs_trans_log_quotaoff_item(
885
        xfs_trans_t             *tp,
886
        xfs_qoff_logitem_t      *qlp)
887
{
888
        xfs_log_item_desc_t     *lidp;
889
 
890
        lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)qlp);
891
        ASSERT(lidp != NULL);
892
 
893
        tp->t_flags |= XFS_TRANS_DIRTY;
894
        lidp->lid_flags |= XFS_LID_DIRTY;
895
}
896
 
897
STATIC void
898
xfs_trans_alloc_dqinfo(
899
        xfs_trans_t     *tp)
900
{
901
        (tp)->t_dqinfo = kmem_zone_zalloc(xfs_Gqm->qm_dqtrxzone, KM_SLEEP);
902
}
903
 
904
STATIC void
905
xfs_trans_free_dqinfo(
906
        xfs_trans_t     *tp)
907
{
908
        if (!tp->t_dqinfo)
909
                return;
910
        kmem_zone_free(xfs_Gqm->qm_dqtrxzone, (tp)->t_dqinfo);
911
        (tp)->t_dqinfo = NULL;
912
}
913
 
914
xfs_dqtrxops_t  xfs_trans_dquot_ops = {
915
        .qo_dup_dqinfo                  = xfs_trans_dup_dqinfo,
916
        .qo_free_dqinfo                 = xfs_trans_free_dqinfo,
917
        .qo_mod_dquot_byino             = xfs_trans_mod_dquot_byino,
918
        .qo_apply_dquot_deltas          = xfs_trans_apply_dquot_deltas,
919
        .qo_reserve_quota_nblks         = xfs_trans_reserve_quota_nblks,
920
        .qo_reserve_quota_bydquots      = xfs_trans_reserve_quota_bydquots,
921
        .qo_unreserve_and_mod_dquots    = xfs_trans_unreserve_and_mod_dquots,
922
};

powered by: WebSVN 2.1.0

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