]> git.neil.brown.name Git - lafs-utils.git/blob - lib/lafs_segment_count.c
lafs: allow some commands to open busy devices with --force
[lafs-utils.git] / lib / lafs_segment_count.c
1
2 /* lafs_segment_count
3  * adjust the usage count for the segment containing a given block
4  */
5
6 #include <lafs/lafs.h>
7
8 static void delay_update(struct lafs *fs, int dev, loff_t seg, int diff)
9 {
10         struct lafs_delayed *d = fs->delayed;
11
12         while (d && (d->dev != dev || d->seg != seg))
13                 d = d->next;
14         if (!d) {
15                 d = malloc(sizeof(*d));
16                 d->next = fs->delayed;
17                 fs->delayed = d;
18                 d->dev = dev;
19                 d->seg = seg;
20                 d->diff = 0;
21         }
22         d->diff += diff;
23 }
24
25 void segment_count(struct lafs *fs, int dev, loff_t seg, int diff)
26 {
27         struct lafs_device *dv;
28         struct lafs_dblk *db;
29         uint32_t *p;
30         int cnt;
31         loff_t addr;
32
33         dv = dev_by_num(fs, dev);
34         addr = dv->tablesize + seg / (fs->blocksize >> USAGE_SHIFT);
35
36         db = lafs_dblk(dv->segsum, addr);
37         lafs_load_dblk(db);
38         p = (void*)db->b.data;
39         cnt = __le32_to_cpu(p[seg % (fs->blocksize >> USAGE_SHIFT)]);
40         cnt += diff;
41         p[seg % (fs->blocksize >> USAGE_SHIFT)] = __cpu_to_le32(cnt);
42         lafs_sched_blk(&db->b);
43 }
44
45
46 void lafs_segment_count(struct lafs *fs, loff_t addr, int diff)
47 {
48         int dev;
49         loff_t seg;
50         loff_t offset;
51
52         virttoseg(fs, addr, &dev, &seg, &offset);
53
54         if (fs->flags & LAFS_DELAY_UPDATES) {
55                 delay_update(fs, dev, seg, diff);
56                 return;
57         }
58         segment_count(fs, dev, seg, diff);
59 }
60
61 void lafs_segment_apply_delayed(struct lafs *fs)
62 {
63         struct lafs_delayed *delayed = fs->delayed;
64
65         if (fs->flags & LAFS_DELAY_UPDATES)
66                 abort();
67         fs->delayed = NULL;
68
69         while (delayed) {
70                 struct lafs_delayed *d = delayed;
71                 delayed = d->next;
72                 segment_count(fs, d->dev, d->seg, d->diff);
73                 free(d);
74         }
75 }