]> git.neil.brown.name Git - LaFS.git/blob - summary.c
README update
[LaFS.git] / summary.c
1 /*
2  * fs/lafs/summary.c
3  * Copyright (C) 2005-2009
4  * Neil Brown <neilb@suse.de>
5  * Released under the GPL, version 2
6  */
7 #include "lafs.h"
8
9 /*
10  * Every time blocks are allocated or deallocated, we must track them:
11  *  per-file
12  *  per-filesystem
13  *  per-user/group/tree
14  */
15 void lafs_summary_update(struct fs *fs, struct inode *ino,
16                          u64 oldphys, u64 newphys,
17                          int is_index, int phase, int moveref)
18 {
19         /* Whether writing a block or truncating, we hold a reference
20          * to ->iblock, so can access it without locking
21          */
22         struct lafs_inode *lai;
23         int future;
24         int diff;
25         if (oldphys && newphys) {
26                 // FIXME what snapshot should I use?
27                 lafs_seg_move(fs, oldphys, newphys, 0, phase, moveref);
28                 return;
29         }
30         if (oldphys == 0 && newphys == 0)
31                 return;
32
33         lai = LAFSI(ino);
34         future = (phase != !!test_bit(B_Phase1, &lai->iblock->b.flags));
35         if (oldphys)
36                 diff = -1;
37         else
38                 diff = 1;
39
40         /* per-file */
41         spin_lock(&ino->i_lock);
42         if (future) {
43                 if (is_index)
44                         lai->piblocks += diff;
45                 else
46                         lai->pblocks += diff;
47         } else {
48                 if (is_index)
49                         lai->ciblocks += diff;
50                 else
51                         lai->cblocks += diff;
52         }
53         if (!is_index) {
54                 if (diff > 0)
55                         lai->ablocks--;
56                 else
57                         ino->i_blocks -=
58                                 1 << (fs->blocksize_bits - 9);
59         }
60         spin_unlock(&ino->i_lock);
61
62         /* per-filesystem */
63         lai = LAFSI(lai->filesys);
64         spin_lock(&lai->vfs_inode.i_lock);
65         if (future)
66                 lai->md.fs.pblocks_used += diff;
67         else
68                 lai->md.fs.cblocks_used += diff;
69
70         if (!is_index) {
71                 BUG_ON(lai->md.fs.ablocks_used == 0 && diff > 0);
72                 if (diff > 0)
73                         lai->md.fs.ablocks_used--;
74         }
75         spin_unlock(&lai->vfs_inode.i_lock);
76
77         /* per user/group/tree */
78
79         lafs_qcommit(fs, ino, diff, phase);
80
81         // FIXME what snapshot should I use?
82         lafs_seg_move(fs, oldphys, newphys, 0, phase, moveref);
83 }
84
85 int lafs_summary_allocate(struct fs *fs, struct inode *ino, int diff)
86 {
87         /* this is where quota checks happen */
88         int err = 0;
89         struct lafs_inode *lai = LAFSI(ino);
90         lai = LAFSI(LAFSI(ino)->filesys);
91         spin_lock(&lai->vfs_inode.i_lock);
92         if (lai->md.fs.blocks_allowed &&
93             diff > 0 &&
94             lai->md.fs.cblocks_used +
95             lai->md.fs.pblocks_used +
96             lai->md.fs.ablocks_used + diff
97             > lai->md.fs.blocks_allowed)
98                 err = -ENOSPC;
99         else
100                 lai->md.fs.ablocks_used += diff;
101
102         spin_unlock(&lai->vfs_inode.i_lock);
103         if (err)
104                 return err;
105
106         err = lafs_quota_allocate(fs, ino, diff * fs->blocksize);
107         if (err) {
108                 spin_lock(&lai->vfs_inode.i_lock);
109                 lai->md.fs.ablocks_used -= diff;
110                 spin_unlock(&lai->vfs_inode.i_lock);
111                 return err;
112         }
113
114         lai = LAFSI(ino);
115         spin_lock(&ino->i_lock);
116         lai->ablocks += diff;
117         ino->i_blocks += (blkcnt_t)diff << (fs->blocksize_bits - 9) ;
118         spin_unlock(&ino->i_lock);
119
120         return 0;
121 }