Blame view

fs/ufs/ialloc.c 9.17 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   *  linux/fs/ufs/ialloc.c
   *
   * Copyright (c) 1998
   * Daniel Pirkl <daniel.pirkl@email.cz>
   * Charles University, Faculty of Mathematics and Physics
   *
   *  from
   *
   *  linux/fs/ext2/ialloc.c
   *
   * Copyright (C) 1992, 1993, 1994, 1995
   * Remy Card (card@masi.ibp.fr)
   * Laboratoire MASI - Institut Blaise Pascal
   * Universite Pierre et Marie Curie (Paris VI)
   *
   *  BSD ufs-inspired inode and directory allocation by 
   *  Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
   *  Big-endian to little-endian byte-swapping/bitmaps by
   *        David S. Miller (davem@caip.rutgers.edu), 1995
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
21
22
23
   *
   * UFS2 write support added by
   * Evgeniy Dushistov <dushistov@mail.ru>, 2007
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
   */
  
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
  #include <linux/time.h>
  #include <linux/stat.h>
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
  #include <linux/buffer_head.h>
  #include <linux/sched.h>
  #include <linux/bitops.h>
  #include <asm/byteorder.h>
e54205988   Mike Frysinger   drop linux/ufs_fs...
34
  #include "ufs_fs.h"
bcd6d4ecf   Christoph Hellwig   ufs: move non-lay...
35
  #include "ufs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  #include "swab.h"
  #include "util.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  /*
   * NOTE! When we get the inode, we're the only people
   * that have access to it, and as such there are no
   * race conditions we have to worry about. The inode
   * is not on the hash-lists, and it cannot be reached
   * through the filesystem because the directory entry
   * has been deleted earlier.
   *
   * HOWEVER: we must make sure that we get no aliases,
   * which means that we have to call "clear_inode()"
   * _before_ we mark the inode not in use in the inode
   * bitmaps. Otherwise a newly created file might use
   * the same inode number (not actually the same pointer
   * though), and then we'd have two inodes sharing the
   * same inode number and space on the harddisk.
   */
  void ufs_free_inode (struct inode * inode)
  {
  	struct super_block * sb;
  	struct ufs_sb_private_info * uspi;
  	struct ufs_super_block_first * usb1;
  	struct ufs_cg_private_info * ucpi;
  	struct ufs_cylinder_group * ucg;
  	int is_directory;
  	unsigned ino, cg, bit;
  	
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
64
65
  	UFSD("ENTER, ino %lu
  ", inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
  
  	sb = inode->i_sb;
  	uspi = UFS_SB(sb)->s_uspi;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
69
  	usb1 = ubh_get_usb_first(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  	
  	ino = inode->i_ino;
  
  	lock_super (sb);
  
  	if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) {
  		ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u
  ", ino);
  		unlock_super (sb);
  		return;
  	}
  	
  	cg = ufs_inotocg (ino);
  	bit = ufs_inotocgoff (ino);
  	ucpi = ufs_load_cylinder (sb, cg);
  	if (!ucpi) {
  		unlock_super (sb);
  		return;
  	}
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
89
  	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
  	if (!ufs_cg_chkmagic(sb, ucg))
  		ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number");
  
  	ucg->cg_time = cpu_to_fs32(sb, get_seconds());
  
  	is_directory = S_ISDIR(inode->i_mode);
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
96
  	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  		ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino);
  	else {
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
99
  		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
  		if (ino < ucpi->c_irotor)
  			ucpi->c_irotor = ino;
  		fs32_add(sb, &ucg->cg_cs.cs_nifree, 1);
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
103
  		uspi->cs_total.cs_nifree++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
  		fs32_add(sb, &UFS_SB(sb)->fs_cs(cg).cs_nifree, 1);
  
  		if (is_directory) {
  			fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1);
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
108
  			uspi->cs_total.cs_ndir--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
  			fs32_sub(sb, &UFS_SB(sb)->fs_cs(cg).cs_ndir, 1);
  		}
  	}
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
112
113
  	ubh_mark_buffer_dirty (USPI_UBH(uspi));
  	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
9cb569d60   Christoph Hellwig   remove SWRITE* I/...
114
115
  	if (sb->s_flags & MS_SYNCHRONOUS)
  		ubh_sync_block(UCPI_UBH(ucpi));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
  	
  	sb->s_dirt = 1;
  	unlock_super (sb);
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
119
120
  	UFSD("EXIT
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
  }
  
  /*
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
   * Nullify new chunk of inodes,
   * BSD people also set ui_gen field of inode
   * during nullification, but we not care about
   * that because of linux ufs do not support NFS
   */
  static void ufs2_init_inodes_chunk(struct super_block *sb,
  				   struct ufs_cg_private_info *ucpi,
  				   struct ufs_cylinder_group *ucg)
  {
  	struct buffer_head *bh;
  	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
  	sector_t beg = uspi->s_sbbase +
  		ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg +
  			      fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk));
  	sector_t end = beg + uspi->s_fpb;
  
  	UFSD("ENTER cgno %d
  ", ucpi->c_cgx);
  
  	for (; beg < end; ++beg) {
  		bh = sb_getblk(sb, beg);
  		lock_buffer(bh);
  		memset(bh->b_data, 0, sb->s_blocksize);
  		set_buffer_uptodate(bh);
  		mark_buffer_dirty(bh);
  		unlock_buffer(bh);
  		if (sb->s_flags & MS_SYNCHRONOUS)
  			sync_dirty_buffer(bh);
  		brelse(bh);
  	}
  
  	fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb);
  	ubh_mark_buffer_dirty(UCPI_UBH(ucpi));
9cb569d60   Christoph Hellwig   remove SWRITE* I/...
157
158
  	if (sb->s_flags & MS_SYNCHRONOUS)
  		ubh_sync_block(UCPI_UBH(ucpi));
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
159
160
161
162
163
164
  
  	UFSD("EXIT
  ");
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
168
169
170
171
172
173
   * There are two policies for allocating an inode.  If the new inode is
   * a directory, then a forward search is made for a block group with both
   * free space and a low directory-to-inode ratio; if that fails, then of
   * the groups with above-average free space, that group with the fewest
   * directories already is chosen.
   *
   * For other inodes, search forward from the parent directory's block
   * group to find a free inode.
   */
6a9a06d9c   Al Viro   ufs: propagate um...
174
  struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
179
180
181
182
183
184
  {
  	struct super_block * sb;
  	struct ufs_sb_info * sbi;
  	struct ufs_sb_private_info * uspi;
  	struct ufs_super_block_first * usb1;
  	struct ufs_cg_private_info * ucpi;
  	struct ufs_cylinder_group * ucg;
  	struct inode * inode;
  	unsigned cg, bit, i, j, start;
  	struct ufs_inode_info *ufsi;
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
185
  	int err = -ENOSPC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186

abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
187
188
  	UFSD("ENTER
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
194
195
196
197
198
199
  	
  	/* Cannot create files in a deleted directory */
  	if (!dir || !dir->i_nlink)
  		return ERR_PTR(-EPERM);
  	sb = dir->i_sb;
  	inode = new_inode(sb);
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  	ufsi = UFS_I(inode);
  	sbi = UFS_SB(sb);
  	uspi = sbi->s_uspi;
7b4ee73e2   Evgeniy   [PATCH] ufs cleanup
200
  	usb1 = ubh_get_usb_first(uspi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  
  	lock_super (sb);
  
  	/*
  	 * Try to place the inode in its parent directory
  	 */
  	i = ufs_inotocg(dir->i_ino);
  	if (sbi->fs_cs(i).cs_nifree) {
  		cg = i;
  		goto cg_found;
  	}
  
  	/*
  	 * Use a quadratic hash to find a group with a free inode
  	 */
  	for ( j = 1; j < uspi->s_ncg; j <<= 1 ) {
  		i += j;
  		if (i >= uspi->s_ncg)
  			i -= uspi->s_ncg;
  		if (sbi->fs_cs(i).cs_nifree) {
  			cg = i;
  			goto cg_found;
  		}
  	}
  
  	/*
  	 * That failed: try linear search for a free inode
  	 */
  	i = ufs_inotocg(dir->i_ino) + 1;
  	for (j = 2; j < uspi->s_ncg; j++) {
  		i++;
  		if (i >= uspi->s_ncg)
  			i = 0;
  		if (sbi->fs_cs(i).cs_nifree) {
  			cg = i;
  			goto cg_found;
  		}
  	}
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
239

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
243
  	goto failed;
  
  cg_found:
  	ucpi = ufs_load_cylinder (sb, cg);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
244
245
  	if (!ucpi) {
  		err = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  		goto failed;
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
247
  	}
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
248
  	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
  	if (!ufs_cg_chkmagic(sb, ucg)) 
  		ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
  
  	start = ucpi->c_irotor;
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
253
  	bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  	if (!(bit < uspi->s_ipg)) {
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
255
  		bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
  		if (!(bit < start)) {
  			ufs_error (sb, "ufs_new_inode",
  			    "cylinder group %u corrupted - error in inode bitmap
  ", cg);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
260
  			err = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
  			goto failed;
  		}
  	}
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
264
265
  	UFSD("start = %u, bit = %u, ipg = %u
  ", start, bit, uspi->s_ipg);
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
266
267
  	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
  		ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
  	else {
  		ufs_panic (sb, "ufs_new_inode", "internal error");
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
270
  		err = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
  		goto failed;
  	}
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
273
274
275
276
277
278
279
280
  
  	if (uspi->fs_magic == UFS2_MAGIC) {
  		u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk);
  
  		if (bit + uspi->s_inopb > initediblk &&
  		    initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk))
  			ufs2_init_inodes_chunk(sb, ucpi, ucg);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  	fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
282
  	uspi->cs_total.cs_nifree--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
  	fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1);
  	
  	if (S_ISDIR(mode)) {
  		fs32_add(sb, &ucg->cg_cs.cs_ndir, 1);
ee3ffd6c1   Evgeniy Dushistov   [PATCH] ufs: make...
287
  		uspi->cs_total.cs_ndir++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
  		fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1);
  	}
9695ef16e   Evgeniy Dushistov   [PATCH] ufs: wron...
290
291
  	ubh_mark_buffer_dirty (USPI_UBH(uspi));
  	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
9cb569d60   Christoph Hellwig   remove SWRITE* I/...
292
293
  	if (sb->s_flags & MS_SYNCHRONOUS)
  		ubh_sync_block(UCPI_UBH(ucpi));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
  	sb->s_dirt = 1;
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
295
  	inode->i_ino = cg * uspi->s_ipg + bit;
be8ded597   Dmitry Monakhov   ufs: replace inod...
296
  	inode_init_owner(inode, dir, mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  	inode->i_blocks = 0;
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
298
  	inode->i_generation = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
  	ufsi->i_flags = UFS_I(dir)->i_flags;
  	ufsi->i_lastfrag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
  	ufsi->i_shadow = 0;
  	ufsi->i_osync = 0;
  	ufsi->i_oeftflag = 0;
dd187a260   Evgeniy Dushistov   [PATCH] ufs: litt...
305
  	ufsi->i_dir_start_lookup = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  	memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  	insert_inode_hash(inode);
  	mark_inode_dirty(inode);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  	if (uspi->fs_magic == UFS2_MAGIC) {
  		struct buffer_head *bh;
  		struct ufs2_inode *ufs2_inode;
  
  		/*
  		 * setup birth date, we do it here because of there is no sense
  		 * to hold it in struct ufs_inode_info, and lose 64 bit
  		 */
  		bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
  		if (!bh) {
  			ufs_warning(sb, "ufs_read_inode",
  				    "unable to read inode %lu
  ",
  				    inode->i_ino);
  			err = -EIO;
  			goto fail_remove_inode;
  		}
  		lock_buffer(bh);
  		ufs2_inode = (struct ufs2_inode *)bh->b_data;
  		ufs2_inode += ufs_inotofsbo(inode->i_ino);
2189850f4   Evgeniy Dushistov   [PATCH] ufs2: mor...
329
330
  		ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec);
  		ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
331
332
333
334
335
336
  		mark_buffer_dirty(bh);
  		unlock_buffer(bh);
  		if (sb->s_flags & MS_SYNCHRONOUS)
  			sync_dirty_buffer(bh);
  		brelse(bh);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  	unlock_super (sb);
abf5d15fd   Evgeniy Dushistov   [PATCH] ufs: easy...
338
339
340
341
  	UFSD("allocating inode %lu
  ", inode->i_ino);
  	UFSD("EXIT
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
  	return inode;
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
343
344
  fail_remove_inode:
  	unlock_super(sb);
6d6b77f16   Miklos Szeredi   filesystems: add ...
345
  	clear_nlink(inode);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
346
347
348
349
  	iput(inode);
  	UFSD("EXIT (FAILED): err %d
  ", err);
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
  failed:
  	unlock_super (sb);
  	make_bad_inode(inode);
  	iput (inode);
3313e2926   Evgeniy Dushistov   [PATCH] ufs2 writ...
354
355
356
  	UFSD("EXIT (FAILED): err %d
  ", err);
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  }