Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
balloc.c
Go to the documentation of this file.
1 /*
2  * linux/fs/sysv/balloc.c
3  *
4  * minix/bitmap.c
5  * Copyright (C) 1991, 1992 Linus Torvalds
6  *
7  * ext/freelists.c
8  * Copyright (C) 1992 Remy Card ([email protected])
9  *
10  * xenix/alloc.c
11  * Copyright (C) 1992 Doug Evans
12  *
13  * coh/alloc.c
14  * Copyright (C) 1993 Pascal Haible, Bruno Haible
15  *
16  * sysv/balloc.c
17  * Copyright (C) 1993 Bruno Haible
18  *
19  * This file contains code for allocating/freeing blocks.
20  */
21 
22 #include <linux/buffer_head.h>
23 #include <linux/string.h>
24 #include "sysv.h"
25 
26 /* We don't trust the value of
27  sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
28  but we nevertheless keep it up to date. */
29 
30 static inline sysv_zone_t *get_chunk(struct super_block *sb, struct buffer_head *bh)
31 {
32  char *bh_data = bh->b_data;
33 
34  if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4)
35  return (sysv_zone_t*)(bh_data+4);
36  else
37  return (sysv_zone_t*)(bh_data+2);
38 }
39 
40 /* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
41 
43 {
44  struct sysv_sb_info * sbi = SYSV_SB(sb);
45  struct buffer_head * bh;
46  sysv_zone_t *blocks = sbi->s_bcache;
47  unsigned count;
48  unsigned block = fs32_to_cpu(sbi, nr);
49 
50  /*
51  * This code does not work at all for AFS (it has a bitmap
52  * free list). As AFS is supposed to be read-only no one
53  * should call this for an AFS filesystem anyway...
54  */
55  if (sbi->s_type == FSTYPE_AFS)
56  return;
57 
58  if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
59  printk("sysv_free_block: trying to free block not in datazone\n");
60  return;
61  }
62 
63  mutex_lock(&sbi->s_lock);
64  count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
65 
66  if (count > sbi->s_flc_size) {
67  printk("sysv_free_block: flc_count > flc_size\n");
68  mutex_unlock(&sbi->s_lock);
69  return;
70  }
71  /* If the free list head in super-block is full, it is copied
72  * into this block being freed, ditto if it's completely empty
73  * (applies only on Coherent).
74  */
75  if (count == sbi->s_flc_size || count == 0) {
76  block += sbi->s_block_base;
77  bh = sb_getblk(sb, block);
78  if (!bh) {
79  printk("sysv_free_block: getblk() failed\n");
80  mutex_unlock(&sbi->s_lock);
81  return;
82  }
83  memset(bh->b_data, 0, sb->s_blocksize);
84  *(__fs16*)bh->b_data = cpu_to_fs16(sbi, count);
85  memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
87  set_buffer_uptodate(bh);
88  brelse(bh);
89  count = 0;
90  }
91  sbi->s_bcache[count++] = nr;
92 
93  *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
94  fs32_add(sbi, sbi->s_free_blocks, 1);
95  dirty_sb(sb);
96  mutex_unlock(&sbi->s_lock);
97 }
98 
100 {
101  struct sysv_sb_info *sbi = SYSV_SB(sb);
102  unsigned int block;
103  sysv_zone_t nr;
104  struct buffer_head * bh;
105  unsigned count;
106 
107  mutex_lock(&sbi->s_lock);
108  count = fs16_to_cpu(sbi, *sbi->s_bcache_count);
109 
110  if (count == 0) /* Applies only to Coherent FS */
111  goto Enospc;
112  nr = sbi->s_bcache[--count];
113  if (nr == 0) /* Applies only to Xenix FS, SystemV FS */
114  goto Enospc;
115 
116  block = fs32_to_cpu(sbi, nr);
117 
118  *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
119 
120  if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
121  printk("sysv_new_block: new block %d is not in data zone\n",
122  block);
123  goto Enospc;
124  }
125 
126  if (count == 0) { /* the last block continues the free list */
127  unsigned count;
128 
129  block += sbi->s_block_base;
130  if (!(bh = sb_bread(sb, block))) {
131  printk("sysv_new_block: cannot read free-list block\n");
132  /* retry this same block next time */
133  *sbi->s_bcache_count = cpu_to_fs16(sbi, 1);
134  goto Enospc;
135  }
136  count = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
137  if (count > sbi->s_flc_size) {
138  printk("sysv_new_block: free-list block with >flc_size entries\n");
139  brelse(bh);
140  goto Enospc;
141  }
142  *sbi->s_bcache_count = cpu_to_fs16(sbi, count);
143  memcpy(sbi->s_bcache, get_chunk(sb, bh),
144  count * sizeof(sysv_zone_t));
145  brelse(bh);
146  }
147  /* Now the free list head in the superblock is valid again. */
148  fs32_add(sbi, sbi->s_free_blocks, -1);
149  dirty_sb(sb);
150  mutex_unlock(&sbi->s_lock);
151  return nr;
152 
153 Enospc:
154  mutex_unlock(&sbi->s_lock);
155  return 0;
156 }
157 
158 unsigned long sysv_count_free_blocks(struct super_block * sb)
159 {
160  struct sysv_sb_info * sbi = SYSV_SB(sb);
161  int sb_count;
162  int count;
163  struct buffer_head * bh = NULL;
164  sysv_zone_t *blocks;
165  unsigned block;
166  int n;
167 
168  /*
169  * This code does not work at all for AFS (it has a bitmap
170  * free list). As AFS is supposed to be read-only we just
171  * lie and say it has no free block at all.
172  */
173  if (sbi->s_type == FSTYPE_AFS)
174  return 0;
175 
176  mutex_lock(&sbi->s_lock);
177  sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks);
178 
179  if (0)
180  goto trust_sb;
181 
182  /* this causes a lot of disk traffic ... */
183  count = 0;
184  n = fs16_to_cpu(sbi, *sbi->s_bcache_count);
185  blocks = sbi->s_bcache;
186  while (1) {
188  if (n > sbi->s_flc_size)
189  goto E2big;
190  zone = 0;
191  while (n && (zone = blocks[--n]) != 0)
192  count++;
193  if (zone == 0)
194  break;
195 
196  block = fs32_to_cpu(sbi, zone);
197  if (bh)
198  brelse(bh);
199 
200  if (block < sbi->s_firstdatazone || block >= sbi->s_nzones)
201  goto Einval;
202  block += sbi->s_block_base;
203  bh = sb_bread(sb, block);
204  if (!bh)
205  goto Eio;
206  n = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
207  blocks = get_chunk(sb, bh);
208  }
209  if (bh)
210  brelse(bh);
211  if (count != sb_count)
212  goto Ecount;
213 done:
214  mutex_unlock(&sbi->s_lock);
215  return count;
216 
217 Einval:
218  printk("sysv_count_free_blocks: new block %d is not in data zone\n",
219  block);
220  goto trust_sb;
221 Eio:
222  printk("sysv_count_free_blocks: cannot read free-list block\n");
223  goto trust_sb;
224 E2big:
225  printk("sysv_count_free_blocks: >flc_size entries in free-list block\n");
226  if (bh)
227  brelse(bh);
228 trust_sb:
229  count = sb_count;
230  goto done;
231 Ecount:
232  printk("sysv_count_free_blocks: free block count was %d, "
233  "correcting to %d\n", sb_count, count);
234  if (!(sb->s_flags & MS_RDONLY)) {
235  *sbi->s_free_blocks = cpu_to_fs32(sbi, count);
236  dirty_sb(sb);
237  }
238  goto done;
239 }