ialloc.c 9.7 KB
Newer Older
L
Linus Torvalds 已提交
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
21 22 23
 *
 * UFS2 write support added by
 * Evgeniy Dushistov <dushistov@mail.ru>, 2007
L
Linus Torvalds 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36
 */

#include <linux/fs.h>
#include <linux/ufs_fs.h>
#include <linux/time.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <asm/byteorder.h>

37
#include "ufs.h"
L
Linus Torvalds 已提交
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 64 65 66
#include "swab.h"
#include "util.h"

/*
 * 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;
	
E
Evgeniy Dushistov 已提交
67
	UFSD("ENTER, ino %lu\n", inode->i_ino);
L
Linus Torvalds 已提交
68 69 70

	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
E
Evgeniy 已提交
71
	usb1 = ubh_get_usb_first(uspi);
L
Linus Torvalds 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
	
	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\n", 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;
	}
E
Evgeniy Dushistov 已提交
90
	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
91 92 93 94 95 96 97 98 99 100 101 102
	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);

	DQUOT_FREE_INODE(inode);
	DQUOT_DROP(inode);

	clear_inode (inode);

E
Evgeniy Dushistov 已提交
103
	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
L
Linus Torvalds 已提交
104 105
		ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino);
	else {
E
Evgeniy Dushistov 已提交
106
		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
L
Linus Torvalds 已提交
107 108 109
		if (ino < ucpi->c_irotor)
			ucpi->c_irotor = ino;
		fs32_add(sb, &ucg->cg_cs.cs_nifree, 1);
110
		uspi->cs_total.cs_nifree++;
L
Linus Torvalds 已提交
111 112 113 114
		fs32_add(sb, &UFS_SB(sb)->fs_cs(cg).cs_nifree, 1);

		if (is_directory) {
			fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1);
115
			uspi->cs_total.cs_ndir--;
L
Linus Torvalds 已提交
116 117 118 119
			fs32_sub(sb, &UFS_SB(sb)->fs_cs(cg).cs_ndir, 1);
		}
	}

E
Evgeniy Dushistov 已提交
120 121
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
122
	if (sb->s_flags & MS_SYNCHRONOUS) {
123
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
E
Evgeniy Dushistov 已提交
124
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
125 126 127 128
	}
	
	sb->s_dirt = 1;
	unlock_super (sb);
E
Evgeniy Dushistov 已提交
129
	UFSD("EXIT\n");
L
Linus Torvalds 已提交
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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
/*
 * 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\n", 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));
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
		ubh_wait_on_buffer(UCPI_UBH(ucpi));
	}

	UFSD("EXIT\n");
}

L
Linus Torvalds 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
/*
 * 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.
 */
struct inode * ufs_new_inode(struct inode * dir, int mode)
{
	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;
194
	int err = -ENOSPC;
L
Linus Torvalds 已提交
195

E
Evgeniy Dushistov 已提交
196
	UFSD("ENTER\n");
L
Linus Torvalds 已提交
197 198 199 200 201 202 203 204 205 206 207
	
	/* 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;
E
Evgeniy 已提交
208
	usb1 = ubh_get_usb_first(uspi);
L
Linus Torvalds 已提交
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 239 240 241 242 243 244 245 246

	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;
		}
	}
247

L
Linus Torvalds 已提交
248 249 250 251
	goto failed;

cg_found:
	ucpi = ufs_load_cylinder (sb, cg);
252 253
	if (!ucpi) {
		err = -EIO;
L
Linus Torvalds 已提交
254
		goto failed;
255
	}
E
Evgeniy Dushistov 已提交
256
	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
257 258 259 260
	if (!ufs_cg_chkmagic(sb, ucg)) 
		ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");

	start = ucpi->c_irotor;
E
Evgeniy Dushistov 已提交
261
	bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start);
L
Linus Torvalds 已提交
262
	if (!(bit < uspi->s_ipg)) {
E
Evgeniy Dushistov 已提交
263
		bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start);
L
Linus Torvalds 已提交
264 265 266
		if (!(bit < start)) {
			ufs_error (sb, "ufs_new_inode",
			    "cylinder group %u corrupted - error in inode bitmap\n", cg);
267
			err = -EIO;
L
Linus Torvalds 已提交
268 269 270
			goto failed;
		}
	}
E
Evgeniy Dushistov 已提交
271
	UFSD("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg);
E
Evgeniy Dushistov 已提交
272 273
	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
		ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
L
Linus Torvalds 已提交
274 275
	else {
		ufs_panic (sb, "ufs_new_inode", "internal error");
276
		err = -EIO;
L
Linus Torvalds 已提交
277 278
		goto failed;
	}
279 280 281 282 283 284 285 286 287

	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);
	}

L
Linus Torvalds 已提交
288
	fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
289
	uspi->cs_total.cs_nifree--;
L
Linus Torvalds 已提交
290 291 292 293
	fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1);
	
	if (S_ISDIR(mode)) {
		fs32_add(sb, &ucg->cg_cs.cs_ndir, 1);
294
		uspi->cs_total.cs_ndir++;
L
Linus Torvalds 已提交
295 296
		fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1);
	}
E
Evgeniy Dushistov 已提交
297 298
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
299
	if (sb->s_flags & MS_SYNCHRONOUS) {
300
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
E
Evgeniy Dushistov 已提交
301
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
302 303 304
	}
	sb->s_dirt = 1;

305
	inode->i_ino = cg * uspi->s_ipg + bit;
L
Linus Torvalds 已提交
306 307 308 309 310 311 312 313 314 315
	inode->i_mode = mode;
	inode->i_uid = current->fsuid;
	if (dir->i_mode & S_ISGID) {
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			inode->i_mode |= S_ISGID;
	} else
		inode->i_gid = current->fsgid;

	inode->i_blocks = 0;
316
	inode->i_generation = 0;
L
Linus Torvalds 已提交
317 318 319 320 321 322
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
	ufsi->i_flags = UFS_I(dir)->i_flags;
	ufsi->i_lastfrag = 0;
	ufsi->i_shadow = 0;
	ufsi->i_osync = 0;
	ufsi->i_oeftflag = 0;
323
	ufsi->i_dir_start_lookup = 0;
L
Linus Torvalds 已提交
324 325 326 327
	memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
	insert_inode_hash(inode);
	mark_inode_dirty(inode);

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
	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\n",
				    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);
347 348
		ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec);
		ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec);
349 350 351 352 353 354 355
		mark_buffer_dirty(bh);
		unlock_buffer(bh);
		if (sb->s_flags & MS_SYNCHRONOUS)
			sync_dirty_buffer(bh);
		brelse(bh);
	}

L
Linus Torvalds 已提交
356 357 358 359
	unlock_super (sb);

	if (DQUOT_ALLOC_INODE(inode)) {
		DQUOT_DROP(inode);
360 361
		err = -EDQUOT;
		goto fail_without_unlock;
L
Linus Torvalds 已提交
362 363
	}

E
Evgeniy Dushistov 已提交
364 365
	UFSD("allocating inode %lu\n", inode->i_ino);
	UFSD("EXIT\n");
L
Linus Torvalds 已提交
366 367
	return inode;

368 369 370 371 372 373 374 375
fail_remove_inode:
	unlock_super(sb);
fail_without_unlock:
	inode->i_flags |= S_NOQUOTA;
	inode->i_nlink = 0;
	iput(inode);
	UFSD("EXIT (FAILED): err %d\n", err);
	return ERR_PTR(err);
L
Linus Torvalds 已提交
376 377 378 379
failed:
	unlock_super (sb);
	make_bad_inode(inode);
	iput (inode);
380 381
	UFSD("EXIT (FAILED): err %d\n", err);
	return ERR_PTR(err);
L
Linus Torvalds 已提交
382
}